From: Ping-Ke Shih <pkshih@xxxxxxxxxxx> 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 <pkshih@xxxxxxxxxxx> --- .../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, ¶); + 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 <pkshih@xxxxxxxxxxx>"); +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