From: Ping-Ke Shih <pks...@realtek.com>

The structure halmac_ops defined in wifi.h, and this commit implements and
hooks ops to the structure, so a symbol rtl_halmac_get_ops_pointer is
expoerted to access this module. Meanwhile, we implement ops defined and
needed by this module.

Signed-off-by: Ping-Ke Shih <pks...@realtek.com>
---
 .../wireless/realtek/rtlwifi/halmac/rtl_halmac.c   | 1403 ++++++++++++++++++++
 .../wireless/realtek/rtlwifi/halmac/rtl_halmac.h   |   77 ++
 2 files changed, 1480 insertions(+)
 create mode 100644 drivers/net/wireless/realtek/rtlwifi/halmac/rtl_halmac.c
 create mode 100644 drivers/net/wireless/realtek/rtlwifi/halmac/rtl_halmac.h

diff --git a/drivers/net/wireless/realtek/rtlwifi/halmac/rtl_halmac.c 
b/drivers/net/wireless/realtek/rtlwifi/halmac/rtl_halmac.c
new file mode 100644
index 000000000000..d9b81824728d
--- /dev/null
+++ b/drivers/net/wireless/realtek/rtlwifi/halmac/rtl_halmac.c
@@ -0,0 +1,1403 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2016 - 2018 Realtek Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ 
******************************************************************************/
+
+#include "halmac_api.h"
+#include "rtl_halmac.h"
+#include <linux/module.h>
+#include <linux/vmalloc.h>
+
+#define rtlpriv_to_halmac(priv)                                                
\
+       ((struct halmac_adapter *)((priv)->halmac.internal))
+
+#define DEFAULT_INDICATOR_TIMELMT msecs_to_jiffies(1000) /* ms */
+
+const struct rtl_halmac_ops rtl_halmac_operation = {
+       .halmac_init_adapter = rtl_halmac_init_adapter,
+       .halmac_deinit_adapter = rtl_halmac_deinit_adapter,
+       .halmac_init_hal = rtl_halmac_init_hal,
+       .halmac_deinit_hal = rtl_halmac_deinit_hal,
+       .halmac_poweron = rtl_halmac_poweron,
+       .halmac_poweroff = rtl_halmac_poweroff,
+
+       .halmac_phy_power_switch = rtl_halmac_phy_power_switch,
+       .halmac_set_mac_address = rtl_halmac_set_mac_address,
+       .halmac_set_bssid = rtl_halmac_set_bssid,
+
+       .halmac_get_physical_efuse_size = rtl_halmac_get_physical_efuse_size,
+       .halmac_read_physical_efuse_map = rtl_halmac_read_physical_efuse_map,
+       .halmac_get_logical_efuse_size = rtl_halmac_get_logical_efuse_size,
+       .halmac_read_logical_efuse_map = rtl_halmac_read_logical_efuse_map,
+
+       .halmac_set_bandwidth = rtl_halmac_set_bandwidth,
+
+       .halmac_c2h_handle = rtl_halmac_c2h_handle,
+
+       .halmac_chk_txdesc = rtl_halmac_chk_txdesc,
+       .halmac_iqk = rtl_halmac_iqk,
+};
+EXPORT_SYMBOL(rtl_halmac_operation);
+
+enum pltfm_ret_status {
+       FLTFM_RET_FAIL = 0,
+       FLTFM_RET_SUCCESS = 1,
+};
+
+static u8 _halmac_reg_read_8(void *p, u32 offset)
+{
+       struct rtl_priv *rtlpriv = (struct rtl_priv *)p;
+
+       return rtl_read_byte(rtlpriv, offset);
+}
+
+static u16 _halmac_reg_read_16(void *p, u32 offset)
+{
+       struct rtl_priv *rtlpriv = (struct rtl_priv *)p;
+
+       return rtl_read_word(rtlpriv, offset);
+}
+
+static u32 _halmac_reg_read_32(void *p, u32 offset)
+{
+       struct rtl_priv *rtlpriv = (struct rtl_priv *)p;
+
+       return rtl_read_dword(rtlpriv, offset);
+}
+
+static void _halmac_reg_write_8(void *p, u32 offset, u8 val)
+{
+       struct rtl_priv *rtlpriv = (struct rtl_priv *)p;
+
+       rtl_write_byte(rtlpriv, offset, val);
+}
+
+static void _halmac_reg_write_16(void *p, u32 offset, u16 val)
+{
+       struct rtl_priv *rtlpriv = (struct rtl_priv *)p;
+
+       rtl_write_word(rtlpriv, offset, val);
+}
+
+static void _halmac_reg_write_32(void *p, u32 offset, u32 val)
+{
+       struct rtl_priv *rtlpriv = (struct rtl_priv *)p;
+
+       rtl_write_dword(rtlpriv, offset, val);
+}
+
+static u8 _halmac_write_data_rsvd_page(void *p, u8 *buf, u32 size)
+{
+       struct rtl_priv *rtlpriv = (struct rtl_priv *)p;
+
+       if (rtlpriv->cfg->ops->halmac_cb_write_data_rsvd_page &&
+           rtlpriv->cfg->ops->halmac_cb_write_data_rsvd_page(rtlpriv, buf,
+                                                             size))
+               return FLTFM_RET_SUCCESS;
+
+       return FLTFM_RET_FAIL;
+}
+
+static u8 _halmac_write_data_h2c(void *p, u8 *buf, u32 size)
+{
+       struct rtl_priv *rtlpriv = (struct rtl_priv *)p;
+
+       if (rtlpriv->cfg->ops->halmac_cb_write_data_h2c &&
+           rtlpriv->cfg->ops->halmac_cb_write_data_h2c(rtlpriv, buf, size))
+               return FLTFM_RET_SUCCESS;
+
+       return FLTFM_RET_FAIL;
+}
+
+static const char *const RTL_HALMAC_FEATURE_NAME[] = {
+       "HALMAC_FEATURE_CFG_PARA",
+       "HALMAC_FEATURE_DUMP_PHYSICAL_EFUSE",
+       "HALMAC_FEATURE_DUMP_LOGICAL_EFUSE",
+       "HALMAC_FEATURE_UPDATE_PACKET",
+       "HALMAC_FEATURE_UPDATE_DATAPACK",
+       "HALMAC_FEATURE_RUN_DATAPACK",
+       "HALMAC_FEATURE_CHANNEL_SWITCH",
+       "HALMAC_FEATURE_IQK",
+       "HALMAC_FEATURE_POWER_TRACKING",
+       "HALMAC_FEATURE_PSD",
+       "HALMAC_FEATURE_ALL"};
+
+static inline bool is_valid_id_status(struct rtl_priv *rtlpriv,
+                                     enum halmac_feature_id id,
+                                     enum halmac_cmd_process_status status)
+{
+       switch (id) {
+       case HALMAC_FEATURE_CFG_PARA:
+               RT_TRACE(rtlpriv, COMP_HALMAC, DBG_LOUD, "%s: %s\n", __func__,
+                        RTL_HALMAC_FEATURE_NAME[id]);
+               break;
+       case HALMAC_FEATURE_DUMP_PHYSICAL_EFUSE:
+               RT_TRACE(rtlpriv, COMP_HALMAC, DBG_LOUD, "%s: %s\n", __func__,
+                        RTL_HALMAC_FEATURE_NAME[id]);
+               if (status != HALMAC_CMD_PROCESS_DONE) {
+                       RT_TRACE(rtlpriv, COMP_HALMAC, DBG_LOUD,
+                                "%s: <WARN> id(%d) unspecified status(%d)!\n",
+                                __func__, id, status);
+               }
+               break;
+       case HALMAC_FEATURE_DUMP_LOGICAL_EFUSE:
+               RT_TRACE(rtlpriv, COMP_HALMAC, DBG_LOUD, "%s: %s\n", __func__,
+                        RTL_HALMAC_FEATURE_NAME[id]);
+               if (status != HALMAC_CMD_PROCESS_DONE) {
+                       RT_TRACE(rtlpriv, COMP_HALMAC, DBG_LOUD,
+                                "%s: <WARN> id(%d) unspecified status(%d)!\n",
+                                __func__, id, status);
+               }
+               break;
+       case HALMAC_FEATURE_UPDATE_PACKET:
+               RT_TRACE(rtlpriv, COMP_HALMAC, DBG_LOUD, "%s: %s\n", __func__,
+                        RTL_HALMAC_FEATURE_NAME[id]);
+               break;
+       case HALMAC_FEATURE_UPDATE_DATAPACK:
+               RT_TRACE(rtlpriv, COMP_HALMAC, DBG_LOUD, "%s: %s\n", __func__,
+                        RTL_HALMAC_FEATURE_NAME[id]);
+               break;
+       case HALMAC_FEATURE_RUN_DATAPACK:
+               RT_TRACE(rtlpriv, COMP_HALMAC, DBG_LOUD, "%s: %s\n", __func__,
+                        RTL_HALMAC_FEATURE_NAME[id]);
+               break;
+       case HALMAC_FEATURE_CHANNEL_SWITCH:
+               RT_TRACE(rtlpriv, COMP_HALMAC, DBG_LOUD, "%s: %s\n", __func__,
+                        RTL_HALMAC_FEATURE_NAME[id]);
+               break;
+       case HALMAC_FEATURE_IQK:
+               RT_TRACE(rtlpriv, COMP_HALMAC, DBG_LOUD, "%s: %s\n", __func__,
+                        RTL_HALMAC_FEATURE_NAME[id]);
+               break;
+       case HALMAC_FEATURE_POWER_TRACKING:
+               RT_TRACE(rtlpriv, COMP_HALMAC, DBG_LOUD, "%s: %s\n", __func__,
+                        RTL_HALMAC_FEATURE_NAME[id]);
+               break;
+       case HALMAC_FEATURE_PSD:
+               RT_TRACE(rtlpriv, COMP_HALMAC, DBG_LOUD, "%s: %s\n", __func__,
+                        RTL_HALMAC_FEATURE_NAME[id]);
+               break;
+       case HALMAC_FEATURE_ALL:
+               RT_TRACE(rtlpriv, COMP_HALMAC, DBG_LOUD, "%s: %s\n", __func__,
+                        RTL_HALMAC_FEATURE_NAME[id]);
+               break;
+       default:
+               RT_TRACE(rtlpriv, COMP_HALMAC, DBG_LOUD,
+                        "%s: unknown feature id(%d)\n", __func__, id);
+               return false;
+       }
+
+       return true;
+}
+
+static int init_halmac_event_with_waittime(struct rtl_priv *rtlpriv,
+                                          enum halmac_feature_id id, u8 *buf,
+                                          u32 size, u32 time)
+{
+       struct rtl_halmac_indicator *indicator = &rtlpriv->halmac.indicator[id];
+       struct completion *comp = indicator->comp;
+
+       if (!comp) {
+               comp = kzalloc(sizeof(*comp), GFP_KERNEL);
+               if (!comp)
+                       return -ENOMEM;
+       } else {
+               RT_TRACE(rtlpriv, COMP_HALMAC, DBG_LOUD,
+                        "%s: <WARN> id(%d) sctx is not NULL!!\n", __func__,
+                        id);
+               indicator->comp = NULL;
+       }
+
+       init_completion(comp);
+       indicator->wait_ms = time;
+       indicator->buffer = buf;
+       indicator->buf_size = size;
+       indicator->ret_size = 0;
+       indicator->status = 0;
+
+       /* fill sctx at least to sure other variables are all ready! */
+       indicator->comp = comp;
+
+       return 0;
+}
+
+static inline int init_halmac_event(struct rtl_priv *rtlpriv,
+                                   enum halmac_feature_id id, u8 *buf,
+                                   u32 size)
+{
+       return init_halmac_event_with_waittime(rtlpriv, id, buf, size,
+                                              DEFAULT_INDICATOR_TIMELMT);
+}
+
+static void free_halmac_event(struct rtl_priv *rtlpriv,
+                             enum halmac_feature_id id)
+{
+       struct rtl_halmac_indicator *indicator = &rtlpriv->halmac.indicator[id];
+       struct completion *comp = indicator->comp;
+
+       if (!comp)
+               return;
+
+       indicator->comp = NULL;
+       kfree(comp);
+}
+
+static int wait_halmac_event(struct rtl_priv *rtlpriv,
+                            enum halmac_feature_id id)
+{
+       struct rtl_halmac_indicator *indicator;
+       int ret;
+
+       indicator = &rtlpriv->halmac.indicator[id];
+
+       if (!indicator->comp)
+               return -EINVAL;
+
+       ret = wait_for_completion_timeout(indicator->comp, indicator->wait_ms);
+
+       free_halmac_event(rtlpriv, id);
+       if (ret > 0)
+               return 0;
+
+       return -ETIME;
+}
+
+static u8
+_halmac_event_indication(void *p, enum halmac_feature_id feature_id,
+                        enum halmac_cmd_process_status process_status, u8 *buf,
+                        u32 size)
+{
+       struct rtl_priv *rtlpriv;
+       struct rtl_halmac_indicator *tbl, *indicator;
+       struct completion *comp;
+       u32 cpsz;
+
+       rtlpriv = (struct rtl_priv *)p;
+       tbl = rtlpriv->halmac.indicator;
+
+       if (!is_valid_id_status(rtlpriv, feature_id, process_status))
+               return FLTFM_RET_FAIL;
+
+       indicator = &tbl[feature_id];
+       indicator->status = process_status;
+       indicator->ret_size = size;
+       if (!indicator->comp) {
+               RT_TRACE(rtlpriv, COMP_HALMAC, DBG_LOUD,
+                        "%s: No feature id(%d) waiting!!\n", __func__,
+                        feature_id);
+               return FLTFM_RET_FAIL;
+       }
+       comp = indicator->comp;
+
+       if (process_status == HALMAC_CMD_PROCESS_ERROR) {
+               RT_TRACE(rtlpriv, COMP_HALMAC, DBG_LOUD,
+                        "%s: Something wrong id(%d)!!\n", __func__,
+                        feature_id);
+               complete(comp); /* may provide error code */
+               return FLTFM_RET_SUCCESS;
+       }
+
+       if (size > indicator->buf_size) {
+               RT_TRACE(rtlpriv, COMP_HALMAC, DBG_LOUD,
+                        "%s: <WARN> id(%d) buffer is not enough(%d<%d), data 
will be truncated!\n",
+                        __func__, feature_id, indicator->buf_size, size);
+               cpsz = indicator->buf_size;
+       } else {
+               cpsz = size;
+       }
+
+       if (cpsz && indicator->buffer)
+               memcpy(indicator->buffer, buf, cpsz);
+
+       complete(comp);
+
+       return FLTFM_RET_SUCCESS;
+}
+
+static struct halmac_platform_api rtl_halmac_platform_api = {
+       /* R/W register */
+       .REG_READ_8 = _halmac_reg_read_8,
+       .REG_READ_16 = _halmac_reg_read_16,
+       .REG_READ_32 = _halmac_reg_read_32,
+       .REG_WRITE_8 = _halmac_reg_write_8,
+       .REG_WRITE_16 = _halmac_reg_write_16,
+       .REG_WRITE_32 = _halmac_reg_write_32,
+
+       /* impletement in HAL-IC level */
+       .SEND_RSVD_PAGE = _halmac_write_data_rsvd_page,
+       .SEND_H2C_PKT = _halmac_write_data_h2c,
+       .EVENT_INDICATION = _halmac_event_indication,
+};
+
+static int init_priv(struct rtl_halmac *halmac)
+{
+       struct rtl_halmac_indicator *indicator;
+       u32 count, size;
+
+       count = HALMAC_FEATURE_ALL + 1;
+       size = sizeof(*indicator) * count;
+       indicator = kzalloc(size, GFP_KERNEL);
+       if (!indicator)
+               return -EINVAL;
+       halmac->indicator = indicator;
+
+       return 0;
+}
+
+static void deinit_priv(struct rtl_halmac *halmac)
+{
+       struct rtl_halmac_indicator *indicator;
+
+       indicator = halmac->indicator;
+       halmac->indicator = NULL;
+       kfree(indicator);
+}
+
+int rtl_halmac_init_adapter(struct rtl_priv *rtlpriv)
+{
+       struct halmac_adapter *halmac;
+       struct halmac_api *api;
+       enum halmac_interface intf;
+       enum halmac_ret_status status;
+       int err = 0;
+       struct halmac_platform_api *pf_api = &rtl_halmac_platform_api;
+
+       halmac = rtlpriv_to_halmac(rtlpriv);
+       if (halmac) {
+               err = 0;
+               goto out;
+       }
+
+       err = init_priv(&rtlpriv->halmac);
+       if (err)
+               goto out;
+
+       intf = HALMAC_INTERFACE_PCIE;
+       status = halmac_init_adapter(rtlpriv, pf_api, intf, &halmac, &api);
+       if (status != HALMAC_RET_SUCCESS) {
+               pr_err("%s: halmac_init_adapter fail!(status=%d)\n",
+                      __func__, status);
+               err = -EINVAL;
+               goto out;
+       }
+
+       rtlpriv->halmac.internal = halmac;
+
+       status = api->halmac_interface_integration_tuning(halmac);
+       if (status != HALMAC_RET_SUCCESS) {
+               pr_err("%s: halmac_interface_integration_tuning 
fail!(status=%d)\n",
+                      __func__, status);
+               err = -EINVAL;
+               goto out;
+       }
+
+       status = api->halmac_phy_cfg(halmac, HALMAC_INTF_PHY_PLATFORM_ALL);
+       if (status != HALMAC_RET_SUCCESS) {
+               pr_err("%s: halmac_phy_cfg fail!(status=%d)\n",
+                      __func__, status);
+               err = -EINVAL;
+               goto out;
+       }
+
+out:
+       if (err)
+               rtl_halmac_deinit_adapter(rtlpriv);
+
+       return err;
+}
+
+int rtl_halmac_deinit_adapter(struct rtl_priv *rtlpriv)
+{
+       struct halmac_adapter *halmac;
+       enum halmac_ret_status status;
+       int err = 0;
+
+       halmac = rtlpriv_to_halmac(rtlpriv);
+       if (!halmac) {
+               err = 0;
+               goto out;
+       }
+
+       deinit_priv(&rtlpriv->halmac);
+
+       halmac_halt_api(halmac);
+
+       status = halmac_deinit_adapter(halmac);
+       rtlpriv->halmac.internal = NULL;
+       if (status != HALMAC_RET_SUCCESS) {
+               err = -EINVAL;
+               goto out;
+       }
+
+out:
+       return err;
+}
+
+int rtl_halmac_poweron(struct rtl_priv *rtlpriv)
+{
+       struct halmac_adapter *halmac;
+       struct halmac_api *api;
+       enum halmac_ret_status status;
+       int err = -EINVAL;
+
+       halmac = rtlpriv_to_halmac(rtlpriv);
+       if (!halmac)
+               goto out;
+
+       api = HALMAC_GET_API(halmac);
+
+       status = api->halmac_pre_init_system_cfg(halmac);
+       if (status != HALMAC_RET_SUCCESS)
+               goto out;
+
+       status = api->halmac_mac_power_switch(halmac, HALMAC_MAC_POWER_ON);
+       if (status != HALMAC_RET_SUCCESS)
+               goto out;
+
+       status = api->halmac_init_system_cfg(halmac);
+       if (status != HALMAC_RET_SUCCESS)
+               goto out;
+
+       err = 0;
+out:
+       return err;
+}
+
+int rtl_halmac_poweroff(struct rtl_priv *rtlpriv)
+{
+       struct halmac_adapter *halmac;
+       struct halmac_api *api;
+       enum halmac_ret_status status;
+       int err = -EINVAL;
+
+       halmac = rtlpriv_to_halmac(rtlpriv);
+       if (!halmac)
+               goto out;
+
+       api = HALMAC_GET_API(halmac);
+
+       status = api->halmac_mac_power_switch(halmac, HALMAC_MAC_POWER_OFF);
+       if (status != HALMAC_RET_SUCCESS)
+               goto out;
+
+       err = 0;
+out:
+       return err;
+}
+
+int rtl_halmac_config_rx_info(struct rtl_priv *rtlpriv,
+                             enum halmac_drv_info info)
+{
+       struct halmac_adapter *halmac;
+       struct halmac_api *api;
+       enum halmac_ret_status status;
+       int err = -EINVAL;
+
+       halmac = rtlpriv_to_halmac(rtlpriv);
+       api = HALMAC_GET_API(halmac);
+
+       status = api->halmac_cfg_drv_info(halmac, info);
+       if (status != HALMAC_RET_SUCCESS)
+               goto out;
+
+       err = 0;
+out:
+       return err;
+}
+
+static enum halmac_ret_status init_mac_flow(struct rtl_priv *rtlpriv)
+{
+       struct halmac_adapter *halmac;
+       struct halmac_api *api;
+       enum halmac_ret_status status;
+       enum halmac_trx_mode trx_mode;
+       enum halmac_wireless_mode mode;
+       u8 wifi_test = 0;
+       int err;
+
+       halmac = rtlpriv_to_halmac(rtlpriv);
+       api = HALMAC_GET_API(halmac);
+
+       if (wifi_test)
+               trx_mode = HALMAC_TRX_MODE_WMM;
+       else
+               trx_mode = HALMAC_TRX_MODE_NORMAL;
+
+       status = api->halmac_init_mac_cfg(halmac, trx_mode);
+       if (status != HALMAC_RET_SUCCESS)
+               goto out;
+
+       err = rtl_halmac_rx_agg_switch(rtlpriv, true);
+       if (err)
+               goto out;
+
+       if (rtlpriv->cfg->maps[RTL_RC_VHT_RATE_1SS_MCS7])
+               mode = HALMAC_WIRELESS_MODE_AC;
+       else if (rtlpriv->cfg->maps[RTL_RC_HT_RATEMCS7])
+               mode = HALMAC_WIRELESS_MODE_N;
+       else if (rtlpriv->cfg->maps[RTL_RC_OFDM_RATE6M])
+               mode = HALMAC_WIRELESS_MODE_G;
+       else
+               mode = HALMAC_WIRELESS_MODE_B;
+
+       status = api->halmac_cfg_operation_mode(halmac, mode);
+
+       if (status != HALMAC_RET_SUCCESS)
+               goto out;
+
+out:
+       return status;
+}
+
+static inline enum halmac_rf_type _rf_type_drv2halmac(enum rf_type rf_drv)
+{
+       enum halmac_rf_type rf_mac;
+
+       switch (rf_drv) {
+       case RF_1T2R:
+               rf_mac = HALMAC_RF_1T2R;
+               break;
+       case RF_2T2R:
+               rf_mac = HALMAC_RF_2T2R;
+               break;
+       case RF_1T1R:
+               rf_mac = HALMAC_RF_1T1R;
+               break;
+       case RF_2T2R_GREEN:
+               rf_mac = HALMAC_RF_2T2R_GREEN;
+               break;
+       default:
+               rf_mac = HALMAC_RF_1T1R;
+               break;
+       }
+
+       return rf_mac;
+}
+
+static enum bb_path _rf_type_to_ant_path(enum rf_type rf)
+{
+       enum bb_path path;
+
+       switch (rf) {
+       case RF_1T1R:
+       case RF_1T2R:
+               path = BB_PATH_A;
+               break;
+       case RF_2T2R:
+       case RF_2T3R:
+       case RF_2T4R:
+               path = BB_PATH_AB;
+               break;
+       case RF_3T3R:
+       case RF_3T4R:
+               path = BB_PATH_ABC;
+               break;
+       case RF_4T4R:
+       default:
+               path = BB_PATH_ABCD;
+               break;
+       }
+
+       return path;
+}
+
+static int _send_general_info(struct rtl_priv *rtlpriv)
+{
+       struct halmac_adapter *halmac;
+       struct halmac_api *api;
+       struct halmac_general_info info;
+       enum halmac_ret_status status;
+       enum bb_path path = BB_PATH_A;
+
+       halmac = rtlpriv_to_halmac(rtlpriv);
+       if (!halmac)
+               return -EINVAL;
+       api = HALMAC_GET_API(halmac);
+
+       memset(&info, 0, sizeof(info));
+       info.rfe_type = rtlpriv->rtlhal.rfe_type;
+       info.rf_type = _rf_type_drv2halmac(rtlpriv->phy.rf_type);
+       path = _rf_type_to_ant_path(rtlpriv->phy.rf_type);
+       info.tx_ant_status = (u8)path;
+       info.rx_ant_status = (u8)path;
+
+       status = api->halmac_send_general_info(halmac, &info);
+       switch (status) {
+       case HALMAC_RET_SUCCESS:
+               break;
+       case HALMAC_RET_NO_DLFW:
+               RT_TRACE(rtlpriv, COMP_HALMAC, DBG_WARNING,
+                        "%s: halmac_send_general_info() fail because fw not 
dl!\n",
+                        __func__);
+       /* fall through */
+       default:
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+static int _halmac_init_hal(struct rtl_priv *rtlpriv, u8 *fw, u32 fwsize)
+{
+       struct halmac_adapter *halmac;
+       struct halmac_api *api;
+       enum halmac_ret_status status;
+       bool ok;
+       bool fw_ok = false;
+       int err, err_ret = -EINVAL;
+
+       halmac = rtlpriv_to_halmac(rtlpriv);
+       if (!halmac)
+               goto out;
+       api = HALMAC_GET_API(halmac);
+
+       /* StatePowerOff */
+       err = rtl_halmac_poweron(rtlpriv);
+       if (err)
+               goto out;
+
+       /* StatePowerOn */
+
+       /* DownloadFW */
+       if (fw && fwsize) {
+               err = rtl_halmac_dlfw(rtlpriv, fw, fwsize, 0);
+               if (err)
+                       goto out;
+               fw_ok = true;
+       }
+
+       /* InitMACFlow */
+       status = init_mac_flow(rtlpriv);
+       if (status != HALMAC_RET_SUCCESS)
+               goto out;
+
+       /* halmac_send_general_info */
+       if (fw_ok) {
+               err = _send_general_info(rtlpriv);
+               if (err)
+                       goto out;
+       }
+
+       /* Init Phy parameter-MAC */
+       if (rtlpriv->cfg->ops->halmac_cb_init_mac_register)
+               ok = rtlpriv->cfg->ops->halmac_cb_init_mac_register(rtlpriv);
+       else
+               ok = false;
+
+       if (!ok)
+               goto out;
+
+       /* StateMacInitialized */
+
+       /* halmac_cfg_drv_info */
+       err = rtl_halmac_config_rx_info(rtlpriv, HALMAC_DRV_INFO_PHY_STATUS);
+       if (err)
+               goto out;
+
+       /* Init BB, RF */
+       if (rtlpriv->cfg->ops->halmac_cb_init_bb_rf_register)
+               ok = rtlpriv->cfg->ops->halmac_cb_init_bb_rf_register(rtlpriv);
+       else
+               ok = false;
+
+       if (!ok)
+               goto out;
+
+       status = api->halmac_init_interface_cfg(halmac);
+       if (status != HALMAC_RET_SUCCESS)
+               goto out;
+
+       /* StateRxIdle */
+
+       err_ret = 0;
+out:
+       return err_ret;
+}
+
+int rtl_halmac_init_hal(struct rtl_priv *rtlpriv)
+{
+       if (!rtlpriv->rtlhal.pfirmware || rtlpriv->rtlhal.fwsize == 0)
+               return -EINVAL;
+
+       return _halmac_init_hal(rtlpriv, rtlpriv->rtlhal.pfirmware,
+                               rtlpriv->rtlhal.fwsize);
+}
+
+int rtl_halmac_deinit_hal(struct rtl_priv *rtlpriv)
+{
+       struct halmac_adapter *halmac;
+       struct halmac_api *api;
+       enum halmac_ret_status status;
+       int err = -EINVAL;
+
+       halmac = rtlpriv_to_halmac(rtlpriv);
+       if (!halmac)
+               goto out;
+       api = HALMAC_GET_API(halmac);
+
+       status = api->halmac_deinit_interface_cfg(halmac);
+       if (status != HALMAC_RET_SUCCESS)
+               goto out;
+
+       status = api->halmac_mac_power_switch(halmac, HALMAC_MAC_POWER_OFF);
+       if (status != HALMAC_RET_SUCCESS)
+               goto out;
+
+       err = 0;
+out:
+       return err;
+}
+
+int rtl_halmac_self_verify(struct rtl_priv *rtlpriv)
+{
+       struct halmac_adapter *mac;
+       struct halmac_api *api;
+       enum halmac_ret_status status;
+       int err = -EINVAL;
+
+       mac = rtlpriv_to_halmac(rtlpriv);
+       api = HALMAC_GET_API(mac);
+
+       status = api->halmac_verify_platform_api(mac);
+       if (status != HALMAC_RET_SUCCESS)
+               goto out;
+
+       status = api->halmac_h2c_lb(mac);
+       if (status != HALMAC_RET_SUCCESS)
+               goto out;
+
+       err = 0;
+out:
+       return err;
+}
+
+int rtl_halmac_dlfw(struct rtl_priv *rtlpriv, u8 *fw, u32 fwsize, bool redl)
+{
+       struct halmac_adapter *mac;
+       struct halmac_api *api;
+       enum halmac_ret_status status;
+       struct halmac_fw_version fw_version;
+       int err = 0;
+
+       mac = rtlpriv_to_halmac(rtlpriv);
+       api = HALMAC_GET_API(mac);
+
+       if (!fw || fwsize == 0)
+               return -EINVAL;
+
+       /* 1. Driver Stop Tx */
+       /* ToDo */
+
+       /* 2. Driver Check Tx FIFO is empty */
+       /* ToDo */
+
+       /* 3. Config MAX download size */
+       api->halmac_cfg_max_dl_size(mac, 0x1000);
+
+       /* 4. Download Firmware */
+       status = api->halmac_download_firmware(mac, fw, fwsize);
+       if (status != HALMAC_RET_SUCCESS)
+               return -EINVAL;
+
+       status = api->halmac_get_fw_version(mac, &fw_version);
+       if (status == HALMAC_RET_SUCCESS) {
+               rtlpriv->rtlhal.fw_version = fw_version.version;
+               rtlpriv->rtlhal.fw_subversion =
+                       (fw_version.sub_version << 8) | (fw_version.sub_index);
+
+               RT_TRACE(rtlpriv, COMP_HALMAC, DBG_DMESG,
+                        "halmac report firmware version %04X.%04X\n",
+                        rtlpriv->rtlhal.fw_version,
+                        rtlpriv->rtlhal.fw_subversion);
+       }
+
+       if (redl)
+               err = _send_general_info(rtlpriv);
+
+       /* 5. Driver resume TX if needed */
+       /* ToDo */
+
+       /* 6. Reset driver variables if needed */
+
+       return err;
+}
+
+int rtl_halmac_phy_power_switch(struct rtl_priv *rtlpriv, u8 enable)
+{
+       struct halmac_adapter *halmac;
+       struct halmac_api *api;
+       enum halmac_ret_status status;
+
+       halmac = rtlpriv_to_halmac(rtlpriv);
+       if (!halmac)
+               return -EINVAL;
+       api = HALMAC_GET_API(halmac);
+
+       status = api->halmac_set_hw_value(halmac, HALMAC_HW_EN_BB_RF, &enable);
+       if (status != HALMAC_RET_SUCCESS)
+               return -EINVAL;
+
+       return 0;
+}
+
+static bool _is_fw_read_cmd_down(struct rtl_priv *rtlpriv, u8 msgbox_num)
+{
+       bool read_down = false;
+       int retry_cnts = 100;
+       u8 valid;
+
+       RT_TRACE(rtlpriv, COMP_HALMAC, DBG_LOUD,
+                "%s, reg_1cc(%x), msg_box(%d)...\n", __func__,
+                rtl_read_byte(rtlpriv, REG_HMETFR), msgbox_num);
+
+       do {
+               valid = rtl_read_byte(rtlpriv, REG_HMETFR) & BIT(msgbox_num);
+               if (valid == 0)
+                       read_down = true;
+               else
+                       schedule();
+       } while ((!read_down) && (retry_cnts--));
+
+       return read_down;
+}
+
+/* for H2C cmd */
+#define MAX_H2C_BOX_NUMS 4
+#define MESSAGE_BOX_SIZE 4
+#define EX_MESSAGE_BOX_SIZE 4
+
+int rtl_halmac_send_h2c(struct rtl_priv *rtlpriv, u8 *h2c)
+{
+       u8 h2c_box_num = 0;
+       u32 msgbox_addr = 0;
+       u32 msgbox_ex_addr = 0;
+       __le32 h2c_cmd = 0;
+       __le32 h2c_cmd_ex = 0;
+       s32 ret = -EINVAL;
+       unsigned long flag = 0;
+       struct rtl_hal *rtlhal = rtl_hal(rtlpriv);
+
+       if (!h2c) {
+               RT_TRACE(rtlpriv, COMP_HALMAC, DBG_LOUD, "%s: pbuf is NULL\n",
+                        __func__);
+               return ret;
+       }
+
+       spin_lock_irqsave(&rtlpriv->locks.h2c_lock, flag);
+
+       /* pay attention to if race condition happened in  H2C cmd setting */
+       h2c_box_num = rtlhal->last_hmeboxnum;
+
+       if (!_is_fw_read_cmd_down(rtlpriv, h2c_box_num)) {
+               RT_TRACE(rtlpriv, COMP_HALMAC, DBG_LOUD,
+                        " fw read cmd failed...\n");
+               goto exit;
+       }
+
+       /* Write Ext command(byte 4 -7) */
+       msgbox_ex_addr = REG_HMEBOX_E0 + (h2c_box_num * EX_MESSAGE_BOX_SIZE);
+       memcpy((u8 *)(&h2c_cmd_ex), h2c + 4, EX_MESSAGE_BOX_SIZE);
+       rtl_write_dword(rtlpriv, msgbox_ex_addr, le32_to_cpu(h2c_cmd_ex));
+
+       /* Write command (byte 0 -3 ) */
+       msgbox_addr = REG_HMEBOX0 + (h2c_box_num * MESSAGE_BOX_SIZE);
+       memcpy((u8 *)(&h2c_cmd), h2c, 4);
+       rtl_write_dword(rtlpriv, msgbox_addr, le32_to_cpu(h2c_cmd));
+
+       /* update last msg box number */
+       rtlhal->last_hmeboxnum = (h2c_box_num + 1) % MAX_H2C_BOX_NUMS;
+       ret = 0;
+
+exit:
+       spin_unlock_irqrestore(&rtlpriv->locks.h2c_lock, flag);
+       return ret;
+}
+
+int rtl_halmac_c2h_handle(struct rtl_priv *rtlpriv, u8 *c2h, u32 size)
+{
+       struct halmac_adapter *mac;
+       struct halmac_api *api;
+       enum halmac_ret_status status;
+
+       mac = rtlpriv_to_halmac(rtlpriv);
+       api = HALMAC_GET_API(mac);
+
+       status = api->halmac_get_c2h_info(mac, c2h, size);
+       if (status != HALMAC_RET_SUCCESS)
+               return -EINVAL;
+
+       return 0;
+}
+
+int rtl_halmac_get_physical_efuse_size(struct rtl_priv *rtlpriv, u32 *size)
+{
+       struct halmac_adapter *mac;
+       struct halmac_api *api;
+       enum halmac_ret_status status;
+       u32 val;
+
+       mac = rtlpriv_to_halmac(rtlpriv);
+       api = HALMAC_GET_API(mac);
+
+       status = api->halmac_get_efuse_size(mac, &val);
+       if (status != HALMAC_RET_SUCCESS)
+               return -EINVAL;
+
+       *size = val;
+       return 0;
+}
+
+int rtl_halmac_read_physical_efuse_map(struct rtl_priv *rtlpriv, u8 *map,
+                                      u32 size)
+{
+       struct halmac_adapter *mac;
+       struct halmac_api *api;
+       enum halmac_ret_status status;
+       enum halmac_feature_id id;
+       int ret;
+
+       mac = rtlpriv_to_halmac(rtlpriv);
+       api = HALMAC_GET_API(mac);
+       id = HALMAC_FEATURE_DUMP_PHYSICAL_EFUSE;
+
+       ret = init_halmac_event(rtlpriv, id, map, size);
+       if (ret)
+               return -EINVAL;
+
+       status = api->halmac_dump_efuse_map(mac, HALMAC_EFUSE_R_DRV);
+       if (status != HALMAC_RET_SUCCESS) {
+               free_halmac_event(rtlpriv, id);
+               return -EINVAL;
+       }
+
+       ret = wait_halmac_event(rtlpriv, id);
+       if (ret)
+               return -EINVAL;
+
+       return 0;
+}
+
+int rtl_halmac_read_physical_efuse(struct rtl_priv *rtlpriv, u32 offset,
+                                  u32 cnt, u8 *data)
+{
+       struct halmac_adapter *mac;
+       struct halmac_api *api;
+       enum halmac_ret_status status;
+       u8 v;
+       u32 i;
+
+       mac = rtlpriv_to_halmac(rtlpriv);
+       api = HALMAC_GET_API(mac);
+
+       for (i = 0; i < cnt; i++) {
+               status = api->halmac_read_efuse(mac, offset + i, &v);
+               if (status != HALMAC_RET_SUCCESS)
+                       return -EINVAL;
+               data[i] = v;
+       }
+
+       return 0;
+}
+
+int rtl_halmac_write_physical_efuse(struct rtl_priv *rtlpriv, u32 offset,
+                                   u32 cnt, u8 *data)
+{
+       struct halmac_adapter *mac;
+       struct halmac_api *api;
+       enum halmac_ret_status status;
+       u32 i;
+
+       mac = rtlpriv_to_halmac(rtlpriv);
+       api = HALMAC_GET_API(mac);
+
+       for (i = 0; i < cnt; i++) {
+               status = api->halmac_write_efuse(mac, offset + i, data[i]);
+               if (status != HALMAC_RET_SUCCESS)
+                       return -EINVAL;
+       }
+
+       return 0;
+}
+
+int rtl_halmac_get_logical_efuse_size(struct rtl_priv *rtlpriv, u32 *size)
+{
+       struct halmac_adapter *mac;
+       struct halmac_api *api;
+       enum halmac_ret_status status;
+       u32 val;
+
+       mac = rtlpriv_to_halmac(rtlpriv);
+       api = HALMAC_GET_API(mac);
+
+       status = api->halmac_get_logical_efuse_size(mac, &val);
+       if (status != HALMAC_RET_SUCCESS)
+               return -EINVAL;
+
+       *size = val;
+       return 0;
+}
+
+int rtl_halmac_read_logical_efuse_map(struct rtl_priv *rtlpriv, u8 *map,
+                                     u32 size)
+{
+       struct halmac_adapter *mac;
+       struct halmac_api *api;
+       enum halmac_ret_status status;
+       enum halmac_feature_id id;
+       int ret;
+
+       mac = rtlpriv_to_halmac(rtlpriv);
+       api = HALMAC_GET_API(mac);
+       id = HALMAC_FEATURE_DUMP_LOGICAL_EFUSE;
+
+       ret = init_halmac_event(rtlpriv, id, map, size);
+       if (ret)
+               return -EINVAL;
+
+       status = api->halmac_dump_logical_efuse_map(mac, HALMAC_EFUSE_R_AUTO);
+       if (status != HALMAC_RET_SUCCESS) {
+               free_halmac_event(rtlpriv, id);
+               return -EINVAL;
+       }
+
+       ret = wait_halmac_event(rtlpriv, id);
+       if (ret)
+               return -EINVAL;
+
+       return 0;
+}
+
+int rtl_halmac_write_logical_efuse_map(struct rtl_priv *rtlpriv, u8 *map,
+                                      u32 size, u8 *maskmap, u32 masksize)
+{
+       struct halmac_adapter *mac;
+       struct halmac_api *api;
+       struct halmac_pg_efuse_info pginfo;
+       enum halmac_ret_status status;
+
+       mac = rtlpriv_to_halmac(rtlpriv);
+       api = HALMAC_GET_API(mac);
+
+       pginfo.efuse_map = map;
+       pginfo.efuse_map_size = size;
+       pginfo.efuse_mask = maskmap;
+       pginfo.efuse_mask_size = masksize;
+
+       status = api->halmac_pg_efuse_by_map(mac, &pginfo, HALMAC_EFUSE_R_AUTO);
+       if (status != HALMAC_RET_SUCCESS)
+               return -EINVAL;
+
+       return 0;
+}
+
+int rtl_halmac_read_logical_efuse(struct rtl_priv *rtlpriv, u32 offset, u32 
cnt,
+                                 u8 *data)
+{
+       struct halmac_adapter *mac;
+       struct halmac_api *api;
+       enum halmac_ret_status status;
+       u8 v;
+       u32 i;
+
+       mac = rtlpriv_to_halmac(rtlpriv);
+       api = HALMAC_GET_API(mac);
+
+       for (i = 0; i < cnt; i++) {
+               status = api->halmac_read_logical_efuse(mac, offset + i, &v);
+               if (status != HALMAC_RET_SUCCESS)
+                       return -EINVAL;
+               data[i] = v;
+       }
+
+       return 0;
+}
+
+int rtl_halmac_write_logical_efuse(struct rtl_priv *rtlpriv, u32 offset,
+                                  u32 cnt, u8 *data)
+{
+       struct halmac_adapter *mac;
+       struct halmac_api *api;
+       enum halmac_ret_status status;
+       u32 i;
+
+       mac = rtlpriv_to_halmac(rtlpriv);
+       api = HALMAC_GET_API(mac);
+
+       for (i = 0; i < cnt; i++) {
+               status = api->halmac_write_logical_efuse(mac, offset + i,
+                                                        data[i]);
+               if (status != HALMAC_RET_SUCCESS)
+                       return -EINVAL;
+       }
+
+       return 0;
+}
+
+int rtl_halmac_set_mac_address(struct rtl_priv *rtlpriv, u8 hwport, u8 *addr)
+{
+       struct halmac_adapter *halmac;
+       struct halmac_api *api;
+       u8 port;
+       union halmac_wlan_addr hwa;
+       enum halmac_ret_status status;
+       int err = -EINVAL;
+
+       halmac = rtlpriv_to_halmac(rtlpriv);
+       api = HALMAC_GET_API(halmac);
+
+       port = hwport;
+       memset(&hwa, 0, sizeof(hwa));
+       ether_addr_copy(hwa.addr, addr);
+
+       status = api->halmac_cfg_mac_addr(halmac, port, &hwa);
+       if (status != HALMAC_RET_SUCCESS)
+               goto out;
+
+       err = 0;
+out:
+       return err;
+}
+
+int rtl_halmac_set_bssid(struct rtl_priv *rtlpriv, u8 hwport, u8 *addr)
+{
+       struct halmac_adapter *halmac;
+       struct halmac_api *api;
+       u8 port;
+       union halmac_wlan_addr hwa;
+       enum halmac_ret_status status;
+       int err = -EINVAL;
+
+       halmac = rtlpriv_to_halmac(rtlpriv);
+       api = HALMAC_GET_API(halmac);
+       port = hwport;
+
+       memset(&hwa, 0, sizeof(hwa));
+       ether_addr_copy(hwa.addr, addr);
+       status = api->halmac_cfg_bssid(halmac, port, &hwa);
+       if (status != HALMAC_RET_SUCCESS)
+               goto out;
+
+       err = 0;
+out:
+       return err;
+}
+
+int rtl_halmac_set_bandwidth(struct rtl_priv *rtlpriv, u8 channel,
+                            u8 pri_ch_idx, u8 bw)
+{
+       struct halmac_adapter *mac;
+       struct halmac_api *api;
+       enum halmac_ret_status status;
+
+       mac = rtlpriv_to_halmac(rtlpriv);
+       api = HALMAC_GET_API(mac);
+
+       status = api->halmac_cfg_ch_bw(mac, channel, pri_ch_idx, bw);
+       if (status != HALMAC_RET_SUCCESS)
+               return -EINVAL;
+
+       return 0;
+}
+
+int rtl_halmac_get_hw_value(struct rtl_priv *rtlpriv, enum halmac_hw_id hw_id,
+                           void *pvalue)
+{
+       struct halmac_adapter *mac;
+       struct halmac_api *api;
+       enum halmac_ret_status status;
+
+       mac = rtlpriv_to_halmac(rtlpriv);
+       api = HALMAC_GET_API(mac);
+
+       status = api->halmac_get_hw_value(mac, hw_id, pvalue);
+       if (status != HALMAC_RET_SUCCESS)
+               return -EINVAL;
+
+       return 0;
+}
+
+int rtl_halmac_dump_fifo(struct rtl_priv *rtlpriv,
+                        enum hal_fifo_sel halmac_fifo_sel)
+{
+       struct halmac_adapter *mac;
+       struct halmac_api *api;
+       enum halmac_ret_status status;
+       u8 *pfifo_map = NULL;
+       u32 fifo_size = 0;
+       s8 ret = 0;
+
+       mac = rtlpriv_to_halmac(rtlpriv);
+       api = HALMAC_GET_API(mac);
+
+       fifo_size = api->halmac_get_fifo_size(mac, halmac_fifo_sel);
+       if (fifo_size)
+               pfifo_map = vmalloc(fifo_size);
+       if (!pfifo_map)
+               return -EINVAL;
+
+       status = api->halmac_dump_fifo(mac, halmac_fifo_sel, 0, fifo_size,
+                                      pfifo_map);
+
+       if (status != HALMAC_RET_SUCCESS) {
+               ret = -EINVAL;
+               goto _exit;
+       }
+
+_exit:
+       if (pfifo_map)
+               vfree(pfifo_map);
+       return ret;
+}
+
+int rtl_halmac_rx_agg_switch(struct rtl_priv *rtlpriv, bool enable)
+{
+       struct halmac_adapter *halmac;
+       struct halmac_api *api;
+       struct halmac_rxagg_cfg rxaggcfg;
+       enum halmac_ret_status status;
+       int err = -EINVAL;
+
+       halmac = rtlpriv_to_halmac(rtlpriv);
+       api = HALMAC_GET_API(halmac);
+       memset((void *)&rxaggcfg, 0, sizeof(rxaggcfg));
+
+       if (enable) {
+               /* enable RX agg. */
+               /* PCIE do nothing */
+       } else {
+               /* disable RX agg. */
+               rxaggcfg.mode = HALMAC_RX_AGG_MODE_NONE;
+       }
+
+       status = api->halmac_cfg_rx_aggregation(halmac, &rxaggcfg);
+       if (status != HALMAC_RET_SUCCESS)
+               goto out;
+
+       err = 0;
+out:
+       return err;
+}
+
+int rtl_halmac_get_wow_reason(struct rtl_priv *rtlpriv, u8 *reason)
+{
+       u8 val8;
+       int err = -EINVAL;
+
+       val8 = rtl_read_byte(rtlpriv, 0x1C7);
+       if (val8 == 0xEA)
+               goto out;
+
+       *reason = val8;
+       err = 0;
+out:
+       return err;
+}
+
+int rtl_halmac_get_drv_info_sz(struct rtl_priv *rtlpriv, u8 *sz)
+{
+       u8 dw = 6; /* max number */
+
+       *sz = dw * 8;
+       return 0;
+}
+
+int rtl_halmac_get_rsvd_drv_pg_bndy(struct rtl_priv *rtlpriv, u16 *drv_pg)
+{
+       enum halmac_ret_status status;
+       struct halmac_adapter *halmac = rtlpriv_to_halmac(rtlpriv);
+       struct halmac_api *api = HALMAC_GET_API(halmac);
+
+       status = api->halmac_get_hw_value(halmac, HALMAC_HW_RSVD_PG_BNDY,
+                                         drv_pg);
+       if (status != HALMAC_RET_SUCCESS)
+               return -EINVAL;
+
+       return 0;
+}
+
+int rtl_halmac_chk_txdesc(struct rtl_priv *rtlpriv, u8 *txdesc, u32 size)
+{
+       struct halmac_adapter *mac;
+       struct halmac_api *api;
+       enum halmac_ret_status status;
+
+       mac = rtlpriv_to_halmac(rtlpriv);
+       api = HALMAC_GET_API(mac);
+
+       status = api->halmac_chk_txdesc(mac, txdesc, size);
+
+       if (status != HALMAC_RET_SUCCESS)
+               return -EINVAL;
+
+       return 0;
+}
+
+int rtl_halmac_iqk(struct rtl_priv *rtlpriv, u8 clear, u8 segment)
+{
+       struct halmac_adapter *mac;
+       struct halmac_api *api;
+       enum halmac_ret_status status;
+       enum halmac_feature_id id;
+       struct halmac_iqk_para para;
+       int ret;
+       u8 retry = 3;
+       u8 delay = 1; /* ms */
+       unsigned long us;
+
+       mac = rtlpriv_to_halmac(rtlpriv);
+       api = HALMAC_GET_API(mac);
+       id = HALMAC_FEATURE_IQK;
+
+       ret = init_halmac_event(rtlpriv, id, NULL, 0);
+       if (ret)
+               return -EINVAL;
+
+       para.clear = clear;
+       para.segment_iqk = segment;
+
+       do {
+               status = api->halmac_start_iqk(mac, &para);
+               if (status != HALMAC_RET_BUSY_STATE)
+                       break;
+               RT_TRACE(rtlpriv, COMP_HALMAC, DBG_LOUD,
+                        "%s: Fail to start IQK, status is BUSY! retry=%d\n",
+                        __func__, retry);
+
+               if (!retry)
+                       break;
+               retry--;
+
+               if (delay < 20) {
+                       us = delay * 1000UL;
+                       usleep_range(us, us + 1000UL);
+               } else {
+                       msleep(delay);
+               }
+
+       } while (1);
+
+       if (status != HALMAC_RET_SUCCESS) {
+               free_halmac_event(rtlpriv, id);
+               return -EINVAL;
+       }
+
+       ret = wait_halmac_event(rtlpriv, id);
+       if (ret)
+               return -EINVAL;
+
+       return 0;
+}
+
+MODULE_AUTHOR("Ping-Ke Shih    <pks...@realtek.com>");
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("Realtek 802.11n PCI wireless module hamlac");
diff --git a/drivers/net/wireless/realtek/rtlwifi/halmac/rtl_halmac.h 
b/drivers/net/wireless/realtek/rtlwifi/halmac/rtl_halmac.h
new file mode 100644
index 000000000000..33cd2f913697
--- /dev/null
+++ b/drivers/net/wireless/realtek/rtlwifi/halmac/rtl_halmac.h
@@ -0,0 +1,77 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2016 - 2018 Realtek Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ 
******************************************************************************/
+
+#ifndef _RTL_HALMAC_H_
+#define _RTL_HALMAC_H_
+
+#include "halmac_api.h"
+
+int rtl_halmac_init_adapter(struct rtl_priv *rtlpriv);
+int rtl_halmac_deinit_adapter(struct rtl_priv *rtlpriv);
+int rtl_halmac_poweron(struct rtl_priv *rtlpriv);
+int rtl_halmac_poweroff(struct rtl_priv *rtlpriv);
+int rtl_halmac_init_hal(struct rtl_priv *rtlpriv);
+int rtl_halmac_init_hal_fw(struct rtl_priv *rtlpriv, u8 *fw, u32 fwsize);
+int rtl_halmac_init_hal_fw_file(struct rtl_priv *rtlpriv, u8 *fwpath);
+int rtl_halmac_deinit_hal(struct rtl_priv *rtlpriv);
+int rtl_halmac_self_verify(struct rtl_priv *rtlpriv);
+int rtl_halmac_dlfw(struct rtl_priv *rtlpriv, u8 *fw, u32 fwsize, bool redl);
+int rtl_halmac_dlfw_from_file(struct rtl_priv *rtlpriv, u8 *fwpath);
+int rtl_halmac_phy_power_switch(struct rtl_priv *rtlpriv, u8 enable);
+int rtl_halmac_send_h2c(struct rtl_priv *rtlpriv, u8 *h2c);
+int rtl_halmac_c2h_handle(struct rtl_priv *rtlpriv, u8 *c2h, u32 size);
+
+int rtl_halmac_get_physical_efuse_size(struct rtl_priv *rtlpriv, u32 *size);
+int rtl_halmac_read_physical_efuse_map(struct rtl_priv *rtlpriv, u8 *map,
+                                      u32 size);
+int rtl_halmac_read_physical_efuse(struct rtl_priv *rtlpriv, u32 offset,
+                                  u32 cnt, u8 *data);
+int rtl_halmac_write_physical_efuse(struct rtl_priv *rtlpriv, u32 offset,
+                                   u32 cnt, u8 *data);
+int rtl_halmac_get_logical_efuse_size(struct rtl_priv *rtlpriv, u32 *size);
+int rtl_halmac_read_logical_efuse_map(struct rtl_priv *rtlpriv, u8 *map,
+                                     u32 size);
+int rtl_halmac_write_logical_efuse_map(struct rtl_priv *rtlpriv, u8 *map,
+                                      u32 size, u8 *maskmap, u32 masksize);
+int rtl_halmac_read_logical_efuse(struct rtl_priv *rtlpriv, u32 offset, u32 
cnt,
+                                 u8 *data);
+int rtl_halmac_write_logical_efuse(struct rtl_priv *rtlpriv, u32 offset,
+                                  u32 cnt, u8 *data);
+
+int rtl_halmac_config_rx_info(struct rtl_priv *rtlpriv, enum halmac_drv_info);
+int rtl_halmac_set_mac_address(struct rtl_priv *rtlpriv, u8 hwport, u8 *addr);
+int rtl_halmac_set_bssid(struct rtl_priv *d, u8 hwport, u8 *addr);
+
+int rtl_halmac_set_bandwidth(struct rtl_priv *rtlpriv, u8 channel,
+                            u8 pri_ch_idx, u8 bw);
+int rtl_halmac_rx_agg_switch(struct rtl_priv *rtlpriv, bool enable);
+int rtl_halmac_get_hw_value(struct rtl_priv *d, enum halmac_hw_id hw_id,
+                           void *pvalue);
+int rtl_halmac_dump_fifo(struct rtl_priv *rtlpriv,
+                        enum hal_fifo_sel halmac_fifo_sel);
+
+int rtl_halmac_get_wow_reason(struct rtl_priv *rtlpriv, u8 *reason);
+int rtl_halmac_get_drv_info_sz(struct rtl_priv *d, u8 *sz);
+
+int rtl_halmac_get_rsvd_drv_pg_bndy(struct rtl_priv *dvobj, u16 *drv_pg);
+int rtl_halmac_download_rsvd_page(struct rtl_priv *dvobj, u8 pg_offset,
+                                 u8 *pbuf, u32 size);
+
+int rtl_halmac_chk_txdesc(struct rtl_priv *rtlpriv, u8 *txdesc, u32 size);
+int rtl_halmac_iqk(struct rtl_priv *rtlpriv, u8 clear, u8 segment);
+
+extern const struct rtl_halmac_ops rtl_halmac_operation;
+
+#endif /* _RTL_HALMAC_H_ */
-- 
2.15.1

Reply via email to