mirror of
https://github.com/morrownr/8821cu-20210916.git
synced 2024-11-30 00:57:57 +00:00
3454 lines
94 KiB
C
3454 lines
94 KiB
C
/******************************************************************************
|
|
*
|
|
* Copyright(c) 2016 - 2019 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_common_88xx.h"
|
|
#include "halmac_88xx_cfg.h"
|
|
#include "halmac_init_88xx.h"
|
|
#include "halmac_cfg_wmac_88xx.h"
|
|
#include "halmac_efuse_88xx.h"
|
|
#include "halmac_bb_rf_88xx.h"
|
|
#if HALMAC_USB_SUPPORT
|
|
#include "halmac_usb_88xx.h"
|
|
#endif
|
|
#if HALMAC_SDIO_SUPPORT
|
|
#include "halmac_sdio_88xx.h"
|
|
#endif
|
|
#if HALMAC_PCIE_SUPPORT
|
|
#include "halmac_pcie_88xx.h"
|
|
#endif
|
|
#include "halmac_mimo_88xx.h"
|
|
|
|
#if HALMAC_88XX_SUPPORT
|
|
|
|
#define CFG_PARAM_H2C_INFO_SIZE 12
|
|
#define ORIGINAL_H2C_CMD_SIZE 8
|
|
|
|
#define WLHDR_PROT_VER 0
|
|
|
|
#define WLHDR_TYPE_MGMT 0
|
|
#define WLHDR_TYPE_CTRL 1
|
|
#define WLHDR_TYPE_DATA 2
|
|
|
|
/* mgmt frame */
|
|
#define WLHDR_SUB_TYPE_ASSOC_REQ 0
|
|
#define WLHDR_SUB_TYPE_ASSOC_RSPNS 1
|
|
#define WLHDR_SUB_TYPE_REASSOC_REQ 2
|
|
#define WLHDR_SUB_TYPE_REASSOC_RSPNS 3
|
|
#define WLHDR_SUB_TYPE_PROBE_REQ 4
|
|
#define WLHDR_SUB_TYPE_PROBE_RSPNS 5
|
|
#define WLHDR_SUB_TYPE_BCN 8
|
|
#define WLHDR_SUB_TYPE_DISASSOC 10
|
|
#define WLHDR_SUB_TYPE_AUTH 11
|
|
#define WLHDR_SUB_TYPE_DEAUTH 12
|
|
#define WLHDR_SUB_TYPE_ACTION 13
|
|
#define WLHDR_SUB_TYPE_ACTION_NOACK 14
|
|
|
|
/* ctrl frame */
|
|
#define WLHDR_SUB_TYPE_BF_RPT_POLL 4
|
|
#define WLHDR_SUB_TYPE_NDPA 5
|
|
|
|
/* data frame */
|
|
#define WLHDR_SUB_TYPE_DATA 0
|
|
#define WLHDR_SUB_TYPE_NULL 4
|
|
#define WLHDR_SUB_TYPE_QOS_DATA 8
|
|
#define WLHDR_SUB_TYPE_QOS_NULL 12
|
|
|
|
#define LTECOEX_ACCESS_CTRL REG_WL2LTECOEX_INDIRECT_ACCESS_CTRL_V1
|
|
|
|
struct wlhdr_frame_ctrl {
|
|
u16 protocol:2;
|
|
u16 type:2;
|
|
u16 sub_type:4;
|
|
u16 to_ds:1;
|
|
u16 from_ds:1;
|
|
u16 more_frag:1;
|
|
u16 retry:1;
|
|
u16 pwr_mgmt:1;
|
|
u16 more_data:1;
|
|
u16 protect_frame:1;
|
|
u16 order:1;
|
|
};
|
|
|
|
static enum halmac_ret_status
|
|
parse_c2h_pkt_88xx(struct halmac_adapter *adapter, u8 *buf, u32 size);
|
|
|
|
static enum halmac_ret_status
|
|
get_c2h_dbg_88xx(struct halmac_adapter *adapter, u8 *buf, u32 size);
|
|
|
|
static enum halmac_ret_status
|
|
get_h2c_ack_88xx(struct halmac_adapter *adapter, u8 *buf, u32 size);
|
|
|
|
static enum halmac_ret_status
|
|
get_scan_ch_notify_88xx(struct halmac_adapter *adapter, u8 *buf, u32 size);
|
|
|
|
static enum halmac_ret_status
|
|
get_scan_rpt_88xx(struct halmac_adapter *adapter, u8 *buf, u32 size);
|
|
|
|
static enum halmac_ret_status
|
|
get_h2c_ack_cfg_param_88xx(struct halmac_adapter *adapter, u8 *buf, u32 size);
|
|
|
|
static enum halmac_ret_status
|
|
get_h2c_ack_update_pkt_88xx(struct halmac_adapter *adapter, u8 *buf, u32 size);
|
|
|
|
static enum halmac_ret_status
|
|
get_h2c_ack_send_scan_pkt_88xx(struct halmac_adapter *adapter, u8 *buf,
|
|
u32 size);
|
|
|
|
static enum halmac_ret_status
|
|
get_h2c_ack_drop_scan_pkt_88xx(struct halmac_adapter *adapter, u8 *buf,
|
|
u32 size);
|
|
|
|
static enum halmac_ret_status
|
|
get_h2c_ack_update_datapkt_88xx(struct halmac_adapter *adapter, u8 *buf,
|
|
u32 size);
|
|
|
|
static enum halmac_ret_status
|
|
get_h2c_ack_run_datapkt_88xx(struct halmac_adapter *adapter, u8 *buf, u32 size);
|
|
|
|
static enum halmac_ret_status
|
|
get_h2c_ack_ch_switch_88xx(struct halmac_adapter *adapter, u8 *buf, u32 size);
|
|
|
|
static enum halmac_ret_status
|
|
malloc_cfg_param_buf_88xx(struct halmac_adapter *adapter, u8 full_fifo);
|
|
|
|
static enum halmac_cmd_construct_state
|
|
cfg_param_cmd_cnstr_state_88xx(struct halmac_adapter *adapter);
|
|
|
|
static enum halmac_ret_status
|
|
proc_cfg_param_88xx(struct halmac_adapter *adapter,
|
|
struct halmac_phy_parameter_info *param, u8 full_fifo);
|
|
|
|
static enum halmac_ret_status
|
|
send_cfg_param_h2c_88xx(struct halmac_adapter *adapter);
|
|
|
|
static enum halmac_ret_status
|
|
cnv_cfg_param_state_88xx(struct halmac_adapter *adapter,
|
|
enum halmac_cmd_construct_state dest_state);
|
|
|
|
static enum halmac_ret_status
|
|
add_param_buf_88xx(struct halmac_adapter *adapter,
|
|
struct halmac_phy_parameter_info *param, u8 *buf,
|
|
u8 *end_cmd);
|
|
|
|
static enum halmac_ret_status
|
|
gen_cfg_param_h2c_88xx(struct halmac_adapter *adapter, u8 *buff);
|
|
|
|
static enum halmac_ret_status
|
|
send_h2c_update_packet_88xx(struct halmac_adapter *adapter,
|
|
enum halmac_packet_id pkt_id, u8 *pkt, u32 size);
|
|
|
|
static enum halmac_ret_status
|
|
send_h2c_send_scan_packet_88xx(struct halmac_adapter *adapter,
|
|
u8 index, u8 *pkt, u32 size);
|
|
|
|
static enum halmac_ret_status
|
|
send_h2c_drop_scan_packet_88xx(struct halmac_adapter *adapter,
|
|
struct halmac_drop_pkt_option *option);
|
|
|
|
static enum halmac_ret_status
|
|
send_bt_coex_cmd_88xx(struct halmac_adapter *adapter, u8 *buf, u32 size,
|
|
u8 ack);
|
|
|
|
static enum halmac_ret_status
|
|
read_buf_88xx(struct halmac_adapter *adapter, u32 offset, u32 size,
|
|
enum hal_fifo_sel sel, u8 *data);
|
|
|
|
static enum halmac_cmd_construct_state
|
|
scan_cmd_cnstr_state_88xx(struct halmac_adapter *adapter);
|
|
|
|
static enum halmac_ret_status
|
|
cnv_scan_state_88xx(struct halmac_adapter *adapter,
|
|
enum halmac_cmd_construct_state dest_state);
|
|
|
|
static enum halmac_ret_status
|
|
proc_ctrl_ch_switch_88xx(struct halmac_adapter *adapter,
|
|
struct halmac_ch_switch_option *opt);
|
|
|
|
static enum halmac_ret_status
|
|
proc_p2pps_88xx(struct halmac_adapter *adapter, struct halmac_p2pps *info);
|
|
|
|
static enum halmac_ret_status
|
|
get_cfg_param_status_88xx(struct halmac_adapter *adapter,
|
|
enum halmac_cmd_process_status *proc_status);
|
|
|
|
static enum halmac_ret_status
|
|
get_ch_switch_status_88xx(struct halmac_adapter *adapter,
|
|
enum halmac_cmd_process_status *proc_status);
|
|
|
|
static enum halmac_ret_status
|
|
get_update_packet_status_88xx(struct halmac_adapter *adapter,
|
|
enum halmac_cmd_process_status *proc_status);
|
|
|
|
static enum halmac_ret_status
|
|
get_send_scan_packet_status_88xx(struct halmac_adapter *adapter,
|
|
enum halmac_cmd_process_status *proc_status);
|
|
|
|
static enum halmac_ret_status
|
|
get_drop_scan_packet_status_88xx(struct halmac_adapter *adapter,
|
|
enum halmac_cmd_process_status *proc_status);
|
|
|
|
static enum halmac_ret_status
|
|
pwr_sub_seq_parser_88xx(struct halmac_adapter *adapter, u8 cut, u8 intf,
|
|
struct halmac_wlan_pwr_cfg *cmd);
|
|
|
|
static void
|
|
pwr_state_88xx(struct halmac_adapter *adapter, enum halmac_mac_power *state);
|
|
|
|
static enum halmac_ret_status
|
|
pwr_cmd_polling_88xx(struct halmac_adapter *adapter,
|
|
struct halmac_wlan_pwr_cfg *cmd);
|
|
|
|
static void
|
|
get_pq_mapping_88xx(struct halmac_adapter *adapter,
|
|
struct halmac_rqpn_map *mapping);
|
|
|
|
static void
|
|
dump_reg_sdio_88xx(struct halmac_adapter *adapter);
|
|
|
|
static enum halmac_ret_status
|
|
wlhdr_valid_88xx(struct halmac_adapter *adapter, u8 *buf);
|
|
|
|
static u8
|
|
wlhdr_mgmt_valid_88xx(struct halmac_adapter *adapter,
|
|
struct wlhdr_frame_ctrl *wlhdr);
|
|
|
|
static u8
|
|
wlhdr_ctrl_valid_88xx(struct halmac_adapter *adapter,
|
|
struct wlhdr_frame_ctrl *wlhdr);
|
|
|
|
static u8
|
|
wlhdr_data_valid_88xx(struct halmac_adapter *adapter,
|
|
struct wlhdr_frame_ctrl *wlhdr);
|
|
|
|
static void
|
|
dump_reg_88xx(struct halmac_adapter *adapter);
|
|
|
|
static u8
|
|
packet_in_nlo_88xx(struct halmac_adapter *adapter,
|
|
enum halmac_packet_id pkt_id);
|
|
|
|
static enum halmac_packet_id
|
|
get_real_pkt_id_88xx(struct halmac_adapter *adapter,
|
|
enum halmac_packet_id pkt_id);
|
|
|
|
static u32
|
|
get_update_packet_page_size(struct halmac_adapter *adapter, u32 size);
|
|
|
|
/**
|
|
* ofld_func_cfg_88xx() - config offload function
|
|
* @adapter : the adapter of halmac
|
|
* @info : offload function information
|
|
* Author : Ivan Lin
|
|
* Return : enum halmac_ret_status
|
|
* More details of status code can be found in prototype document
|
|
*/
|
|
enum halmac_ret_status
|
|
ofld_func_cfg_88xx(struct halmac_adapter *adapter,
|
|
struct halmac_ofld_func_info *info)
|
|
{
|
|
if (adapter->intf == HALMAC_INTERFACE_SDIO &&
|
|
info->rsvd_pg_drv_buf_max_sz > SDIO_TX_MAX_SIZE_88XX)
|
|
return HALMAC_RET_FAIL;
|
|
|
|
adapter->pltfm_info.malloc_size = info->halmac_malloc_max_sz;
|
|
adapter->pltfm_info.rsvd_pg_size = info->rsvd_pg_drv_buf_max_sz;
|
|
|
|
return HALMAC_RET_SUCCESS;
|
|
}
|
|
|
|
/**
|
|
* dl_drv_rsvd_page_88xx() - download packet to rsvd page
|
|
* @adapter : the adapter of halmac
|
|
* @pg_offset : page offset of driver's rsvd page
|
|
* @halmac_buf : data to be downloaded, tx_desc is not included
|
|
* @halmac_size : data size to be downloaded
|
|
* Author : KaiYuan Chang
|
|
* Return : enum halmac_ret_status
|
|
* More details of status code can be found in prototype document
|
|
*/
|
|
enum halmac_ret_status
|
|
dl_drv_rsvd_page_88xx(struct halmac_adapter *adapter, u8 pg_offset, u8 *buf,
|
|
u32 size)
|
|
{
|
|
enum halmac_ret_status status;
|
|
u32 pg_size;
|
|
u32 pg_num = 0;
|
|
u16 pg_addr = 0;
|
|
|
|
PLTFM_MSG_TRACE("[TRACE]%s ===>\n", __func__);
|
|
|
|
pg_size = adapter->hw_cfg_info.page_size;
|
|
pg_num = size / pg_size + ((size & (pg_size - 1)) ? 1 : 0);
|
|
if (pg_offset + pg_num > adapter->txff_alloc.rsvd_drv_pg_num) {
|
|
PLTFM_MSG_ERR("[ERR] pkt overflow!!\n");
|
|
return HALMAC_RET_DRV_DL_ERR;
|
|
}
|
|
|
|
pg_addr = adapter->txff_alloc.rsvd_drv_addr + pg_offset;
|
|
|
|
status = dl_rsvd_page_88xx(adapter, pg_addr, buf, size);
|
|
|
|
if (status != HALMAC_RET_SUCCESS) {
|
|
PLTFM_MSG_ERR("[ERR]dl rsvd page fail!!\n");
|
|
return status;
|
|
}
|
|
|
|
PLTFM_MSG_TRACE("[TRACE]%s <===\n", __func__);
|
|
|
|
return HALMAC_RET_SUCCESS;
|
|
}
|
|
|
|
enum halmac_ret_status
|
|
dl_rsvd_page_88xx(struct halmac_adapter *adapter, u16 pg_addr, u8 *buf,
|
|
u32 size)
|
|
{
|
|
u8 restore[2];
|
|
u8 value8;
|
|
u16 rsvd_pg_head;
|
|
u32 cnt;
|
|
enum halmac_rsvd_pg_state *state = &adapter->halmac_state.rsvd_pg_state;
|
|
struct halmac_api *api = (struct halmac_api *)adapter->halmac_api;
|
|
enum halmac_ret_status status = HALMAC_RET_SUCCESS;
|
|
|
|
if (size == 0) {
|
|
PLTFM_MSG_TRACE("[TRACE]pkt size = 0\n");
|
|
return HALMAC_RET_ZERO_LEN_RSVD_PACKET;
|
|
}
|
|
|
|
if (*state == HALMAC_RSVD_PG_STATE_BUSY)
|
|
return HALMAC_RET_BUSY_STATE;
|
|
|
|
*state = HALMAC_RSVD_PG_STATE_BUSY;
|
|
|
|
pg_addr &= BIT_MASK_BCN_HEAD_1_V1;
|
|
HALMAC_REG_W16(REG_FIFOPAGE_CTRL_2, (u16)(pg_addr | BIT(15)));
|
|
|
|
value8 = HALMAC_REG_R8(REG_CR + 1);
|
|
restore[0] = value8;
|
|
value8 = (u8)(value8 | BIT(0));
|
|
HALMAC_REG_W8(REG_CR + 1, value8);
|
|
|
|
value8 = HALMAC_REG_R8(REG_FWHW_TXQ_CTRL + 2);
|
|
restore[1] = value8;
|
|
value8 = (u8)(value8 & ~(BIT(6)));
|
|
HALMAC_REG_W8(REG_FWHW_TXQ_CTRL + 2, value8);
|
|
|
|
if (PLTFM_SEND_RSVD_PAGE(buf, size) == 0) {
|
|
PLTFM_MSG_ERR("[ERR]send rvsd pg(pltfm)!!\n");
|
|
status = HALMAC_RET_DL_RSVD_PAGE_FAIL;
|
|
goto DL_RSVD_PG_END;
|
|
}
|
|
|
|
cnt = 1000;
|
|
while (!(HALMAC_REG_R8(REG_FIFOPAGE_CTRL_2 + 1) & BIT(7))) {
|
|
PLTFM_DELAY_US(10);
|
|
cnt--;
|
|
if (cnt == 0) {
|
|
PLTFM_MSG_ERR("[ERR]bcn valid!!\n");
|
|
status = HALMAC_RET_POLLING_BCN_VALID_FAIL;
|
|
break;
|
|
}
|
|
}
|
|
DL_RSVD_PG_END:
|
|
rsvd_pg_head = adapter->txff_alloc.rsvd_boundary;
|
|
HALMAC_REG_W16(REG_FIFOPAGE_CTRL_2, rsvd_pg_head | BIT(15));
|
|
HALMAC_REG_W8(REG_FWHW_TXQ_CTRL + 2, restore[1]);
|
|
HALMAC_REG_W8(REG_CR + 1, restore[0]);
|
|
|
|
*state = HALMAC_RSVD_PG_STATE_IDLE;
|
|
|
|
return status;
|
|
}
|
|
|
|
enum halmac_ret_status
|
|
get_hw_value_88xx(struct halmac_adapter *adapter, enum halmac_hw_id hw_id,
|
|
void *value)
|
|
{
|
|
PLTFM_MSG_TRACE("[TRACE]%s ===>\n", __func__);
|
|
|
|
switch (hw_id) {
|
|
case HALMAC_HW_RQPN_MAPPING:
|
|
get_pq_mapping_88xx(adapter, (struct halmac_rqpn_map *)value);
|
|
break;
|
|
case HALMAC_HW_EFUSE_SIZE:
|
|
*(u32 *)value = adapter->hw_cfg_info.efuse_size;
|
|
break;
|
|
case HALMAC_HW_EEPROM_SIZE:
|
|
*(u32 *)value = adapter->hw_cfg_info.eeprom_size;
|
|
break;
|
|
case HALMAC_HW_BT_BANK_EFUSE_SIZE:
|
|
*(u32 *)value = adapter->hw_cfg_info.bt_efuse_size;
|
|
break;
|
|
case HALMAC_HW_BT_BANK1_EFUSE_SIZE:
|
|
case HALMAC_HW_BT_BANK2_EFUSE_SIZE:
|
|
*(u32 *)value = 0;
|
|
break;
|
|
case HALMAC_HW_TXFIFO_SIZE:
|
|
*(u32 *)value = adapter->hw_cfg_info.tx_fifo_size;
|
|
break;
|
|
case HALMAC_HW_RXFIFO_SIZE:
|
|
*(u32 *)value = adapter->hw_cfg_info.rx_fifo_size;
|
|
break;
|
|
case HALMAC_HW_RSVD_PG_BNDY:
|
|
*(u16 *)value = adapter->txff_alloc.rsvd_drv_addr;
|
|
break;
|
|
case HALMAC_HW_CAM_ENTRY_NUM:
|
|
*(u8 *)value = adapter->hw_cfg_info.cam_entry_num;
|
|
break;
|
|
case HALMAC_HW_WLAN_EFUSE_AVAILABLE_SIZE:
|
|
get_efuse_available_size_88xx(adapter, (u32 *)value);
|
|
break;
|
|
case HALMAC_HW_IC_VERSION:
|
|
*(u8 *)value = adapter->chip_ver;
|
|
break;
|
|
case HALMAC_HW_PAGE_SIZE:
|
|
*(u32 *)value = adapter->hw_cfg_info.page_size;
|
|
break;
|
|
case HALMAC_HW_TX_AGG_ALIGN_SIZE:
|
|
*(u16 *)value = adapter->hw_cfg_info.tx_align_size;
|
|
break;
|
|
case HALMAC_HW_RX_AGG_ALIGN_SIZE:
|
|
*(u8 *)value = 8;
|
|
break;
|
|
case HALMAC_HW_DRV_INFO_SIZE:
|
|
*(u8 *)value = adapter->drv_info_size;
|
|
break;
|
|
case HALMAC_HW_TXFF_ALLOCATION:
|
|
PLTFM_MEMCPY(value, &adapter->txff_alloc,
|
|
sizeof(struct halmac_txff_allocation));
|
|
break;
|
|
case HALMAC_HW_RSVD_EFUSE_SIZE:
|
|
*(u32 *)value = get_rsvd_efuse_size_88xx(adapter);
|
|
break;
|
|
case HALMAC_HW_FW_HDR_SIZE:
|
|
*(u32 *)value = WLAN_FW_HDR_SIZE;
|
|
break;
|
|
case HALMAC_HW_TX_DESC_SIZE:
|
|
*(u32 *)value = adapter->hw_cfg_info.txdesc_size;
|
|
break;
|
|
case HALMAC_HW_RX_DESC_SIZE:
|
|
*(u32 *)value = adapter->hw_cfg_info.rxdesc_size;
|
|
break;
|
|
case HALMAC_HW_ORI_H2C_SIZE:
|
|
*(u32 *)value = ORIGINAL_H2C_CMD_SIZE;
|
|
break;
|
|
case HALMAC_HW_RSVD_DRV_PGNUM:
|
|
*(u16 *)value = adapter->txff_alloc.rsvd_drv_pg_num;
|
|
break;
|
|
case HALMAC_HW_TX_PAGE_SIZE:
|
|
*(u16 *)value = TX_PAGE_SIZE_88XX;
|
|
break;
|
|
case HALMAC_HW_USB_TXAGG_DESC_NUM:
|
|
*(u8 *)value = adapter->hw_cfg_info.usb_txagg_num;
|
|
break;
|
|
case HALMAC_HW_AC_OQT_SIZE:
|
|
*(u8 *)value = adapter->hw_cfg_info.ac_oqt_size;
|
|
break;
|
|
case HALMAC_HW_NON_AC_OQT_SIZE:
|
|
*(u8 *)value = adapter->hw_cfg_info.non_ac_oqt_size;
|
|
break;
|
|
case HALMAC_HW_AC_QUEUE_NUM:
|
|
*(u8 *)value = adapter->hw_cfg_info.acq_num;
|
|
break;
|
|
case HALMAC_HW_PWR_STATE:
|
|
pwr_state_88xx(adapter, (enum halmac_mac_power *)value);
|
|
break;
|
|
default:
|
|
return HALMAC_RET_PARA_NOT_SUPPORT;
|
|
}
|
|
|
|
PLTFM_MSG_TRACE("[TRACE]%s <===\n", __func__);
|
|
|
|
return HALMAC_RET_SUCCESS;
|
|
}
|
|
|
|
static void
|
|
get_pq_mapping_88xx(struct halmac_adapter *adapter,
|
|
struct halmac_rqpn_map *mapping)
|
|
{
|
|
mapping->dma_map_vo = adapter->pq_map[HALMAC_PQ_MAP_VO];
|
|
mapping->dma_map_vi = adapter->pq_map[HALMAC_PQ_MAP_VI];
|
|
mapping->dma_map_be = adapter->pq_map[HALMAC_PQ_MAP_BE];
|
|
mapping->dma_map_bk = adapter->pq_map[HALMAC_PQ_MAP_BK];
|
|
mapping->dma_map_mg = adapter->pq_map[HALMAC_PQ_MAP_MG];
|
|
mapping->dma_map_hi = adapter->pq_map[HALMAC_PQ_MAP_HI];
|
|
}
|
|
|
|
/**
|
|
* set_hw_value_88xx() -set hw config value
|
|
* @adapter : the adapter of halmac
|
|
* @hw_id : hw id for driver to config
|
|
* @value : hw value, reference table to get data type
|
|
* Author : KaiYuan Chang / Ivan Lin
|
|
* Return : enum halmac_ret_status
|
|
* More details of status code can be found in prototype document
|
|
*/
|
|
enum halmac_ret_status
|
|
set_hw_value_88xx(struct halmac_adapter *adapter, enum halmac_hw_id hw_id,
|
|
void *value)
|
|
{
|
|
enum halmac_ret_status status = HALMAC_RET_SUCCESS;
|
|
#if HALMAC_SDIO_SUPPORT
|
|
struct halmac_tx_page_threshold_info *th_info;
|
|
#endif
|
|
struct halmac_api *api = (struct halmac_api *)adapter->halmac_api;
|
|
|
|
PLTFM_MSG_TRACE("[TRACE]%s ===>\n", __func__);
|
|
|
|
if (!value) {
|
|
PLTFM_MSG_ERR("[ERR]null ptr-set hw value\n");
|
|
return HALMAC_RET_NULL_POINTER;
|
|
}
|
|
|
|
switch (hw_id) {
|
|
#if HALMAC_USB_SUPPORT
|
|
case HALMAC_HW_USB_MODE:
|
|
status = set_usb_mode_88xx(adapter,
|
|
*(enum halmac_usb_mode *)value);
|
|
if (status != HALMAC_RET_SUCCESS)
|
|
return status;
|
|
break;
|
|
#endif
|
|
case HALMAC_HW_BANDWIDTH:
|
|
cfg_bw_88xx(adapter, *(enum halmac_bw *)value);
|
|
break;
|
|
case HALMAC_HW_CHANNEL:
|
|
cfg_ch_88xx(adapter, *(u8 *)value);
|
|
break;
|
|
case HALMAC_HW_PRI_CHANNEL_IDX:
|
|
cfg_pri_ch_idx_88xx(adapter, *(enum halmac_pri_ch_idx *)value);
|
|
break;
|
|
case HALMAC_HW_EN_BB_RF:
|
|
status = enable_bb_rf_88xx(adapter, *(u8 *)value);
|
|
if (status != HALMAC_RET_SUCCESS)
|
|
return status;
|
|
break;
|
|
#if HALMAC_SDIO_SUPPORT
|
|
case HALMAC_HW_SDIO_TX_PAGE_THRESHOLD:
|
|
if (adapter->intf == HALMAC_INTERFACE_SDIO) {
|
|
th_info = (struct halmac_tx_page_threshold_info *)value;
|
|
cfg_sdio_tx_page_threshold_88xx(adapter, th_info);
|
|
} else {
|
|
return HALMAC_RET_FAIL;
|
|
}
|
|
break;
|
|
#endif
|
|
case HALMAC_HW_RX_SHIFT:
|
|
rx_shift_88xx(adapter, *(u8 *)value);
|
|
break;
|
|
case HALMAC_HW_TXDESC_CHECKSUM:
|
|
tx_desc_chksum_88xx(adapter, *(u8 *)value);
|
|
break;
|
|
case HALMAC_HW_RX_CLK_GATE:
|
|
rx_clk_gate_88xx(adapter, *(u8 *)value);
|
|
break;
|
|
case HALMAC_HW_FAST_EDCA:
|
|
fast_edca_cfg_88xx(adapter,
|
|
(struct halmac_fast_edca_cfg *)value);
|
|
break;
|
|
case HALMAC_HW_RTS_FULL_BW:
|
|
rts_full_bw_88xx(adapter, *(u8 *)value);
|
|
break;
|
|
case HALMAC_HW_FREE_CNT_EN:
|
|
HALMAC_REG_W8_SET(REG_MISC_CTRL, BIT_EN_FREECNT);
|
|
break;
|
|
case HALMAC_HW_TXFIFO_LIFETIME:
|
|
cfg_txfifo_lt_88xx(adapter,
|
|
(struct halmac_txfifo_lifetime_cfg *)value);
|
|
break;
|
|
default:
|
|
return HALMAC_RET_PARA_NOT_SUPPORT;
|
|
}
|
|
|
|
PLTFM_MSG_TRACE("[TRACE]%s <===\n", __func__);
|
|
|
|
return HALMAC_RET_SUCCESS;
|
|
}
|
|
|
|
/**
|
|
* get_watcher_88xx() -get watcher value
|
|
* @adapter : the adapter of halmac
|
|
* @sel : id for driver to config
|
|
* @value : value, reference table to get data type
|
|
* Author :
|
|
* Return : enum halmac_ret_status
|
|
* More details of status code can be found in prototype document
|
|
*/
|
|
enum halmac_ret_status
|
|
get_watcher_88xx(struct halmac_adapter *adapter, enum halmac_watcher_sel sel,
|
|
void *value)
|
|
{
|
|
PLTFM_MSG_TRACE("[TRACE]%s ===>\n", __func__);
|
|
|
|
if (!value) {
|
|
PLTFM_MSG_ERR("[ERR]null ptr-set hw value\n");
|
|
return HALMAC_RET_NULL_POINTER;
|
|
}
|
|
|
|
switch (sel) {
|
|
case HALMAC_WATCHER_SDIO_RN_FOOL_PROOFING:
|
|
*(u32 *)value = adapter->watcher.get_watcher.sdio_rn_not_align;
|
|
break;
|
|
default:
|
|
return HALMAC_RET_PARA_NOT_SUPPORT;
|
|
}
|
|
|
|
PLTFM_MSG_TRACE("[TRACE]%s <===\n", __func__);
|
|
|
|
return HALMAC_RET_SUCCESS;
|
|
}
|
|
|
|
enum halmac_ret_status
|
|
set_h2c_pkt_hdr_88xx(struct halmac_adapter *adapter, u8 *hdr,
|
|
struct halmac_h2c_header_info *info, u16 *seq_num)
|
|
{
|
|
u16 total_size;
|
|
|
|
PLTFM_MSG_TRACE("[TRACE]%s!!\n", __func__);
|
|
|
|
total_size = H2C_PKT_HDR_SIZE_88XX + info->content_size;
|
|
FW_OFFLOAD_H2C_SET_TOTAL_LEN(hdr, total_size);
|
|
FW_OFFLOAD_H2C_SET_SUB_CMD_ID(hdr, info->sub_cmd_id);
|
|
|
|
FW_OFFLOAD_H2C_SET_CATEGORY(hdr, 0x01);
|
|
FW_OFFLOAD_H2C_SET_CMD_ID(hdr, 0xFF);
|
|
|
|
PLTFM_MUTEX_LOCK(&adapter->h2c_seq_mutex);
|
|
FW_OFFLOAD_H2C_SET_SEQ_NUM(hdr, adapter->h2c_info.seq_num);
|
|
*seq_num = adapter->h2c_info.seq_num;
|
|
(adapter->h2c_info.seq_num)++;
|
|
PLTFM_MUTEX_UNLOCK(&adapter->h2c_seq_mutex);
|
|
|
|
if (info->ack == 1)
|
|
FW_OFFLOAD_H2C_SET_ACK(hdr, 1);
|
|
|
|
return HALMAC_RET_SUCCESS;
|
|
}
|
|
|
|
enum halmac_ret_status
|
|
send_h2c_pkt_88xx(struct halmac_adapter *adapter, u8 *pkt)
|
|
{
|
|
u32 cnt = 100;
|
|
enum halmac_ret_status status = HALMAC_RET_SUCCESS;
|
|
|
|
while (adapter->h2c_info.buf_fs <= H2C_PKT_SIZE_88XX) {
|
|
get_h2c_buf_free_space_88xx(adapter);
|
|
cnt--;
|
|
if (cnt == 0) {
|
|
PLTFM_MSG_ERR("[ERR]h2c free space!!\n");
|
|
return HALMAC_RET_H2C_SPACE_FULL;
|
|
}
|
|
}
|
|
|
|
cnt = 100;
|
|
do {
|
|
if (PLTFM_SEND_H2C_PKT(pkt, H2C_PKT_SIZE_88XX) == 1)
|
|
break;
|
|
cnt--;
|
|
if (cnt == 0) {
|
|
PLTFM_MSG_ERR("[ERR]pltfm - sned h2c pkt!!\n");
|
|
return HALMAC_RET_SEND_H2C_FAIL;
|
|
}
|
|
PLTFM_DELAY_US(5);
|
|
|
|
} while (1);
|
|
|
|
adapter->h2c_info.buf_fs -= H2C_PKT_SIZE_88XX;
|
|
|
|
return status;
|
|
}
|
|
|
|
enum halmac_ret_status
|
|
get_h2c_buf_free_space_88xx(struct halmac_adapter *adapter)
|
|
{
|
|
u32 hw_wptr;
|
|
u32 fw_rptr;
|
|
struct halmac_h2c_info *info = &adapter->h2c_info;
|
|
struct halmac_api *api = (struct halmac_api *)adapter->halmac_api;
|
|
|
|
hw_wptr = HALMAC_REG_R32(REG_H2C_PKT_WRITEADDR) & 0x3FFFF;
|
|
fw_rptr = HALMAC_REG_R32(REG_H2C_PKT_READADDR) & 0x3FFFF;
|
|
|
|
if (hw_wptr >= fw_rptr)
|
|
info->buf_fs = info->buf_size - (hw_wptr - fw_rptr);
|
|
else
|
|
info->buf_fs = fw_rptr - hw_wptr;
|
|
|
|
return HALMAC_RET_SUCCESS;
|
|
}
|
|
|
|
/**
|
|
* get_c2h_info_88xx() - process halmac C2H packet
|
|
* @adapter : the adapter of halmac
|
|
* @buf : RX Packet pointer
|
|
* @size : RX Packet size
|
|
*
|
|
* Note : Don't use any IO or DELAY in this API
|
|
*
|
|
* Author : KaiYuan Chang/Ivan Lin
|
|
*
|
|
* Used to process c2h packet info from RX path. After receiving the packet,
|
|
* user need to call this api and pass the packet pointer.
|
|
*
|
|
* Return : enum halmac_ret_status
|
|
* More details of status code can be found in prototype document
|
|
*/
|
|
enum halmac_ret_status
|
|
get_c2h_info_88xx(struct halmac_adapter *adapter, u8 *buf, u32 size)
|
|
{
|
|
enum halmac_ret_status status = HALMAC_RET_SUCCESS;
|
|
|
|
if (GET_RX_DESC_C2H(buf) == 1) {
|
|
PLTFM_MSG_TRACE("[TRACE]Parse c2h pkt\n");
|
|
|
|
status = parse_c2h_pkt_88xx(adapter, buf, size);
|
|
if (status != HALMAC_RET_SUCCESS) {
|
|
PLTFM_MSG_ERR("[ERR]Parse c2h pkt\n");
|
|
return status;
|
|
}
|
|
}
|
|
|
|
return HALMAC_RET_SUCCESS;
|
|
}
|
|
|
|
static enum halmac_ret_status
|
|
parse_c2h_pkt_88xx(struct halmac_adapter *adapter, u8 *buf, u32 size)
|
|
{
|
|
u8 cmd_id;
|
|
u8 sub_cmd_id;
|
|
u8 *c2h_pkt = buf + adapter->hw_cfg_info.rxdesc_size;
|
|
u32 c2h_size = size - adapter->hw_cfg_info.rxdesc_size;
|
|
enum halmac_ret_status status = HALMAC_RET_SUCCESS;
|
|
|
|
cmd_id = (u8)C2H_HDR_GET_CMD_ID(c2h_pkt);
|
|
|
|
if (cmd_id != 0xFF) {
|
|
PLTFM_MSG_TRACE("[TRACE]Not 0xFF cmd!!\n");
|
|
return HALMAC_RET_C2H_NOT_HANDLED;
|
|
}
|
|
|
|
sub_cmd_id = (u8)C2H_HDR_GET_C2H_SUB_CMD_ID(c2h_pkt);
|
|
|
|
switch (sub_cmd_id) {
|
|
case C2H_SUB_CMD_ID_C2H_DBG:
|
|
status = get_c2h_dbg_88xx(adapter, c2h_pkt, c2h_size);
|
|
break;
|
|
case C2H_SUB_CMD_ID_H2C_ACK_HDR:
|
|
status = get_h2c_ack_88xx(adapter, c2h_pkt, c2h_size);
|
|
break;
|
|
case C2H_SUB_CMD_ID_BT_COEX_INFO:
|
|
status = HALMAC_RET_C2H_NOT_HANDLED;
|
|
break;
|
|
case C2H_SUB_CMD_ID_SCAN_STATUS_RPT:
|
|
status = get_scan_rpt_88xx(adapter, c2h_pkt, c2h_size);
|
|
break;
|
|
case C2H_SUB_CMD_ID_PSD_DATA:
|
|
status = get_psd_data_88xx(adapter, c2h_pkt, c2h_size);
|
|
break;
|
|
case C2H_SUB_CMD_ID_EFUSE_DATA:
|
|
status = get_efuse_data_88xx(adapter, c2h_pkt, c2h_size);
|
|
break;
|
|
case C2H_SUB_CMD_ID_SCAN_CH_NOTIFY:
|
|
status = get_scan_ch_notify_88xx(adapter, c2h_pkt, c2h_size);
|
|
break;
|
|
case C2H_SUB_CMD_ID_DPK_DATA:
|
|
status = get_dpk_data_88xx(adapter, c2h_pkt, c2h_size);
|
|
break;
|
|
default:
|
|
PLTFM_MSG_WARN("[WARN]Sub cmd id!!\n");
|
|
status = HALMAC_RET_C2H_NOT_HANDLED;
|
|
break;
|
|
}
|
|
|
|
return status;
|
|
}
|
|
|
|
static enum halmac_ret_status
|
|
get_c2h_dbg_88xx(struct halmac_adapter *adapter, u8 *buf, u32 size)
|
|
{
|
|
u8 i;
|
|
u8 next_msg = 0;
|
|
u8 cur_msg = 0;
|
|
u8 msg_len = 0;
|
|
char *c2h_buf = (char *)NULL;
|
|
u8 content_len = 0;
|
|
u8 seq_num = 0;
|
|
|
|
content_len = (u8)C2H_HDR_GET_LEN((u8 *)buf);
|
|
|
|
if (content_len > C2H_DBG_CONTENT_MAX_LENGTH) {
|
|
PLTFM_MSG_ERR("[ERR]c2h size > max len!\n");
|
|
return HALMAC_RET_C2H_NOT_HANDLED;
|
|
}
|
|
|
|
for (i = 0; i < content_len; i++) {
|
|
if (*(buf + C2H_DBG_HDR_LEN + i) == '\n') {
|
|
if ((*(buf + C2H_DBG_HDR_LEN + i + 1) == '\0') ||
|
|
(*(buf + C2H_DBG_HDR_LEN + i + 1) == 0xff)) {
|
|
next_msg = C2H_DBG_HDR_LEN + i + 1;
|
|
goto _ENDFOUND;
|
|
}
|
|
}
|
|
}
|
|
|
|
_ENDFOUND:
|
|
msg_len = next_msg - C2H_DBG_HDR_LEN;
|
|
|
|
c2h_buf = (char *)PLTFM_MALLOC(msg_len);
|
|
if (!c2h_buf)
|
|
return HALMAC_RET_MALLOC_FAIL;
|
|
|
|
PLTFM_MEMCPY(c2h_buf, buf + C2H_DBG_HDR_LEN, msg_len);
|
|
|
|
seq_num = (u8)(*(c2h_buf));
|
|
*(c2h_buf + msg_len - 1) = '\0';
|
|
PLTFM_MSG_ALWAYS("[RTKFW, SEQ=%d]: %s\n",
|
|
seq_num, (char *)(c2h_buf + 1));
|
|
PLTFM_FREE(c2h_buf, msg_len);
|
|
|
|
while (*(buf + next_msg) != '\0') {
|
|
cur_msg = next_msg;
|
|
|
|
msg_len = (u8)(*(buf + cur_msg + 3)) - 1;
|
|
next_msg += C2H_DBG_HDR_LEN + msg_len;
|
|
|
|
c2h_buf = (char *)PLTFM_MALLOC(msg_len);
|
|
if (!c2h_buf)
|
|
return HALMAC_RET_MALLOC_FAIL;
|
|
|
|
PLTFM_MEMCPY(c2h_buf, buf + cur_msg + C2H_DBG_HDR_LEN, msg_len);
|
|
*(c2h_buf + msg_len - 1) = '\0';
|
|
seq_num = (u8)(*(c2h_buf));
|
|
PLTFM_MSG_ALWAYS("[RTKFW, SEQ=%d]: %s\n",
|
|
seq_num, (char *)(c2h_buf + 1));
|
|
PLTFM_FREE(c2h_buf, msg_len);
|
|
}
|
|
|
|
return HALMAC_RET_SUCCESS;
|
|
}
|
|
|
|
static enum halmac_ret_status
|
|
get_h2c_ack_88xx(struct halmac_adapter *adapter, u8 *buf, u32 size)
|
|
{
|
|
u8 cmd_id;
|
|
u8 sub_cmd_id;
|
|
u8 fw_rc;
|
|
enum halmac_ret_status status = HALMAC_RET_SUCCESS;
|
|
|
|
PLTFM_MSG_TRACE("[TRACE]Ack for C2H!!\n");
|
|
|
|
fw_rc = (u8)H2C_ACK_HDR_GET_H2C_RETURN_CODE(buf);
|
|
if (HALMAC_H2C_RETURN_SUCCESS != (enum halmac_h2c_return_code)fw_rc)
|
|
PLTFM_MSG_TRACE("[TRACE]fw rc = %d\n", fw_rc);
|
|
|
|
cmd_id = (u8)H2C_ACK_HDR_GET_H2C_CMD_ID(buf);
|
|
|
|
if (cmd_id != 0xFF) {
|
|
PLTFM_MSG_ERR("[ERR]h2c ack cmd id!!\n");
|
|
return HALMAC_RET_C2H_NOT_HANDLED;
|
|
}
|
|
|
|
sub_cmd_id = (u8)H2C_ACK_HDR_GET_H2C_SUB_CMD_ID(buf);
|
|
|
|
switch (sub_cmd_id) {
|
|
case H2C_SUB_CMD_ID_DUMP_PHYSICAL_EFUSE_ACK:
|
|
status = get_h2c_ack_phy_efuse_88xx(adapter, buf, size);
|
|
break;
|
|
case H2C_SUB_CMD_ID_CFG_PARAM_ACK:
|
|
status = get_h2c_ack_cfg_param_88xx(adapter, buf, size);
|
|
break;
|
|
case H2C_SUB_CMD_ID_UPDATE_PKT_ACK:
|
|
status = get_h2c_ack_update_pkt_88xx(adapter, buf, size);
|
|
break;
|
|
case H2C_SUB_CMD_ID_SEND_SCAN_PKT_ACK:
|
|
status = get_h2c_ack_send_scan_pkt_88xx(adapter, buf, size);
|
|
break;
|
|
case H2C_SUB_CMD_ID_DROP_SCAN_PKT_ACK:
|
|
status = get_h2c_ack_drop_scan_pkt_88xx(adapter, buf, size);
|
|
break;
|
|
case H2C_SUB_CMD_ID_UPDATE_DATAPACK_ACK:
|
|
status = get_h2c_ack_update_datapkt_88xx(adapter, buf, size);
|
|
break;
|
|
case H2C_SUB_CMD_ID_RUN_DATAPACK_ACK:
|
|
status = get_h2c_ack_run_datapkt_88xx(adapter, buf, size);
|
|
break;
|
|
case H2C_SUB_CMD_ID_CH_SWITCH_ACK:
|
|
status = get_h2c_ack_ch_switch_88xx(adapter, buf, size);
|
|
break;
|
|
case H2C_SUB_CMD_ID_IQK_ACK:
|
|
status = get_h2c_ack_iqk_88xx(adapter, buf, size);
|
|
break;
|
|
case H2C_SUB_CMD_ID_PWR_TRK_ACK:
|
|
status = get_h2c_ack_pwr_trk_88xx(adapter, buf, size);
|
|
break;
|
|
case H2C_SUB_CMD_ID_PSD_ACK:
|
|
break;
|
|
case H2C_SUB_CMD_ID_FW_SNDING_ACK:
|
|
status = get_h2c_ack_fw_snding_88xx(adapter, buf, size);
|
|
break;
|
|
case H2C_SUB_CMD_ID_DPK_ACK:
|
|
status = get_h2c_ack_dpk_88xx(adapter, buf, size);
|
|
break;
|
|
default:
|
|
status = HALMAC_RET_C2H_NOT_HANDLED;
|
|
break;
|
|
}
|
|
|
|
return status;
|
|
}
|
|
|
|
static enum halmac_ret_status
|
|
get_scan_ch_notify_88xx(struct halmac_adapter *adapter, u8 *buf, u32 size)
|
|
{
|
|
struct halmac_scan_rpt_info *scan_rpt_info = &adapter->scan_rpt_info;
|
|
|
|
PLTFM_MSG_TRACE("[TRACE]scan mode:%d\n", adapter->ch_sw_info.scan_mode);
|
|
|
|
if (adapter->ch_sw_info.scan_mode == 1) {
|
|
if (scan_rpt_info->avl_buf_size < 12) {
|
|
PLTFM_MSG_ERR("[ERR]ch_notify buffer full!!\n");
|
|
return HALMAC_RET_CH_SW_NO_BUF;
|
|
}
|
|
|
|
SCAN_CH_NOTIFY_SET_CH_NUM(scan_rpt_info->buf_wptr,
|
|
(u8)SCAN_CH_NOTIFY_GET_CH_NUM(buf));
|
|
SCAN_CH_NOTIFY_SET_NOTIFY_ID(scan_rpt_info->buf_wptr,
|
|
SCAN_CH_NOTIFY_GET_NOTIFY_ID(buf));
|
|
SCAN_CH_NOTIFY_SET_STATUS(scan_rpt_info->buf_wptr,
|
|
(u8)SCAN_CH_NOTIFY_GET_STATUS(buf));
|
|
SCAN_CH_NOTIFY_SET_TSF_0(scan_rpt_info->buf_wptr,
|
|
(u8)SCAN_CH_NOTIFY_GET_TSF_0(buf));
|
|
SCAN_CH_NOTIFY_SET_TSF_1(scan_rpt_info->buf_wptr,
|
|
(u8)SCAN_CH_NOTIFY_GET_TSF_1(buf));
|
|
SCAN_CH_NOTIFY_SET_TSF_2(scan_rpt_info->buf_wptr,
|
|
(u8)SCAN_CH_NOTIFY_GET_TSF_2(buf));
|
|
SCAN_CH_NOTIFY_SET_TSF_3(scan_rpt_info->buf_wptr,
|
|
(u8)SCAN_CH_NOTIFY_GET_TSF_3(buf));
|
|
SCAN_CH_NOTIFY_SET_TSF_4(scan_rpt_info->buf_wptr,
|
|
(u8)SCAN_CH_NOTIFY_GET_TSF_4(buf));
|
|
SCAN_CH_NOTIFY_SET_TSF_5(scan_rpt_info->buf_wptr,
|
|
(u8)SCAN_CH_NOTIFY_GET_TSF_5(buf));
|
|
SCAN_CH_NOTIFY_SET_TSF_6(scan_rpt_info->buf_wptr,
|
|
(u8)SCAN_CH_NOTIFY_GET_TSF_6(buf));
|
|
SCAN_CH_NOTIFY_SET_TSF_7(scan_rpt_info->buf_wptr,
|
|
(u8)SCAN_CH_NOTIFY_GET_TSF_7(buf));
|
|
|
|
scan_rpt_info->avl_buf_size = scan_rpt_info->avl_buf_size - 12;
|
|
scan_rpt_info->total_size = scan_rpt_info->total_size + 12;
|
|
scan_rpt_info->buf_wptr = scan_rpt_info->buf_wptr + 12;
|
|
}
|
|
|
|
return HALMAC_RET_SUCCESS;
|
|
}
|
|
|
|
static enum halmac_ret_status
|
|
get_scan_rpt_88xx(struct halmac_adapter *adapter, u8 *buf, u32 size)
|
|
{
|
|
u8 fw_rc;
|
|
enum halmac_cmd_process_status proc_status;
|
|
struct halmac_scan_rpt_info *scan_rpt_info = &adapter->scan_rpt_info;
|
|
|
|
fw_rc = (u8)SCAN_STATUS_RPT_GET_H2C_RETURN_CODE(buf);
|
|
proc_status = (HALMAC_H2C_RETURN_SUCCESS ==
|
|
(enum halmac_h2c_return_code)fw_rc) ?
|
|
HALMAC_CMD_PROCESS_DONE : HALMAC_CMD_PROCESS_ERROR;
|
|
|
|
PLTFM_EVENT_SIG(HALMAC_FEATURE_CHANNEL_SWITCH, proc_status, NULL, 0);
|
|
|
|
adapter->halmac_state.scan_state.proc_status = proc_status;
|
|
|
|
if (adapter->ch_sw_info.scan_mode == 1) {
|
|
scan_rpt_info->rpt_tsf_low =
|
|
((SCAN_STATUS_RPT_GET_TSF_3(buf) << 24) |
|
|
(SCAN_STATUS_RPT_GET_TSF_2(buf) << 16) |
|
|
(SCAN_STATUS_RPT_GET_TSF_1(buf) << 8) |
|
|
(SCAN_STATUS_RPT_GET_TSF_0(buf)));
|
|
scan_rpt_info->rpt_tsf_high =
|
|
((SCAN_STATUS_RPT_GET_TSF_7(buf) << 24) |
|
|
(SCAN_STATUS_RPT_GET_TSF_6(buf) << 16) |
|
|
(SCAN_STATUS_RPT_GET_TSF_5(buf) << 8) |
|
|
(SCAN_STATUS_RPT_GET_TSF_4(buf)));
|
|
}
|
|
|
|
PLTFM_MSG_TRACE("[TRACE]scan : %X\n", proc_status);
|
|
|
|
return HALMAC_RET_SUCCESS;
|
|
}
|
|
|
|
static enum halmac_ret_status
|
|
get_h2c_ack_cfg_param_88xx(struct halmac_adapter *adapter, u8 *buf, u32 size)
|
|
{
|
|
u8 seq_num;
|
|
u8 fw_rc;
|
|
u32 offset_accum;
|
|
u32 value_accum;
|
|
struct halmac_cfg_param_state *state =
|
|
&adapter->halmac_state.cfg_param_state;
|
|
enum halmac_cmd_process_status proc_status =
|
|
HALMAC_CMD_PROCESS_UNDEFINE;
|
|
|
|
seq_num = (u8)H2C_ACK_HDR_GET_H2C_SEQ(buf);
|
|
PLTFM_MSG_TRACE("[TRACE]Seq num : h2c->%d c2h->%d\n",
|
|
state->seq_num, seq_num);
|
|
if (seq_num != state->seq_num) {
|
|
PLTFM_MSG_ERR("[ERR]Seq num mismatch : h2c->%d c2h->%d\n",
|
|
state->seq_num, seq_num);
|
|
return HALMAC_RET_SUCCESS;
|
|
}
|
|
|
|
if (state->proc_status != HALMAC_CMD_PROCESS_SENDING) {
|
|
PLTFM_MSG_ERR("[ERR]not cmd sending\n");
|
|
return HALMAC_RET_SUCCESS;
|
|
}
|
|
|
|
fw_rc = (u8)H2C_ACK_HDR_GET_H2C_RETURN_CODE(buf);
|
|
state->fw_rc = fw_rc;
|
|
offset_accum = CFG_PARAM_ACK_GET_OFFSET_ACCUMULATION(buf);
|
|
value_accum = CFG_PARAM_ACK_GET_VALUE_ACCUMULATION(buf);
|
|
|
|
if (offset_accum != adapter->cfg_param_info.offset_accum ||
|
|
value_accum != adapter->cfg_param_info.value_accum) {
|
|
PLTFM_MSG_ERR("[ERR][C2H]offset_accu : %x, value_accu : %xn",
|
|
offset_accum, value_accum);
|
|
PLTFM_MSG_ERR("[ERR][Ada]offset_accu : %x, value_accu : %x\n",
|
|
adapter->cfg_param_info.offset_accum,
|
|
adapter->cfg_param_info.value_accum);
|
|
proc_status = HALMAC_CMD_PROCESS_ERROR;
|
|
}
|
|
|
|
if ((enum halmac_h2c_return_code)fw_rc == HALMAC_H2C_RETURN_SUCCESS &&
|
|
proc_status != HALMAC_CMD_PROCESS_ERROR) {
|
|
proc_status = HALMAC_CMD_PROCESS_DONE;
|
|
state->proc_status = proc_status;
|
|
PLTFM_EVENT_SIG(HALMAC_FEATURE_CFG_PARA, proc_status, NULL, 0);
|
|
} else {
|
|
proc_status = HALMAC_CMD_PROCESS_ERROR;
|
|
state->proc_status = proc_status;
|
|
PLTFM_EVENT_SIG(HALMAC_FEATURE_CFG_PARA, proc_status,
|
|
&fw_rc, 1);
|
|
}
|
|
|
|
return HALMAC_RET_SUCCESS;
|
|
}
|
|
|
|
static enum halmac_ret_status
|
|
get_h2c_ack_update_pkt_88xx(struct halmac_adapter *adapter, u8 *buf, u32 size)
|
|
{
|
|
u8 seq_num;
|
|
u8 fw_rc;
|
|
struct halmac_update_pkt_state *state =
|
|
&adapter->halmac_state.update_pkt_state;
|
|
enum halmac_cmd_process_status proc_status;
|
|
|
|
seq_num = (u8)H2C_ACK_HDR_GET_H2C_SEQ(buf);
|
|
PLTFM_MSG_TRACE("[TRACE]Seq num : h2c->%d c2h->%d\n",
|
|
state->seq_num, seq_num);
|
|
if (seq_num != state->seq_num) {
|
|
PLTFM_MSG_ERR("[ERR]Seq num mismatch : h2c->%d c2h->%d\n",
|
|
state->seq_num, seq_num);
|
|
return HALMAC_RET_SUCCESS;
|
|
}
|
|
|
|
if (state->proc_status != HALMAC_CMD_PROCESS_SENDING) {
|
|
PLTFM_MSG_ERR("[ERR]not cmd sending\n");
|
|
return HALMAC_RET_SUCCESS;
|
|
}
|
|
|
|
fw_rc = (u8)H2C_ACK_HDR_GET_H2C_RETURN_CODE(buf);
|
|
state->fw_rc = fw_rc;
|
|
|
|
if (HALMAC_H2C_RETURN_SUCCESS == (enum halmac_h2c_return_code)fw_rc) {
|
|
proc_status = HALMAC_CMD_PROCESS_DONE;
|
|
state->proc_status = proc_status;
|
|
PLTFM_EVENT_SIG(HALMAC_FEATURE_UPDATE_PACKET, proc_status,
|
|
NULL, 0);
|
|
} else {
|
|
proc_status = HALMAC_CMD_PROCESS_ERROR;
|
|
state->proc_status = proc_status;
|
|
PLTFM_EVENT_SIG(HALMAC_FEATURE_UPDATE_PACKET, proc_status,
|
|
&state->fw_rc, 1);
|
|
}
|
|
|
|
return HALMAC_RET_SUCCESS;
|
|
}
|
|
|
|
static enum halmac_ret_status
|
|
get_h2c_ack_send_scan_pkt_88xx(struct halmac_adapter *adapter,
|
|
u8 *buf, u32 size)
|
|
{
|
|
u8 seq_num;
|
|
u8 fw_rc;
|
|
struct halmac_scan_pkt_state *state =
|
|
&adapter->halmac_state.scan_pkt_state;
|
|
enum halmac_cmd_process_status proc_status;
|
|
|
|
seq_num = (u8)H2C_ACK_HDR_GET_H2C_SEQ(buf);
|
|
PLTFM_MSG_TRACE("[TRACE]Seq num : h2c->%d c2h->%d\n",
|
|
state->seq_num, seq_num);
|
|
if (seq_num != state->seq_num) {
|
|
PLTFM_MSG_ERR("[ERR]Seq num mismatch : h2c->%d c2h->%d\n",
|
|
state->seq_num, seq_num);
|
|
return HALMAC_RET_SUCCESS;
|
|
}
|
|
|
|
if (state->proc_status != HALMAC_CMD_PROCESS_SENDING) {
|
|
PLTFM_MSG_ERR("[ERR]not cmd sending\n");
|
|
return HALMAC_RET_SUCCESS;
|
|
}
|
|
|
|
fw_rc = (u8)H2C_ACK_HDR_GET_H2C_RETURN_CODE(buf);
|
|
state->fw_rc = fw_rc;
|
|
|
|
if (HALMAC_H2C_RETURN_SUCCESS == (enum halmac_h2c_return_code)fw_rc) {
|
|
proc_status = HALMAC_CMD_PROCESS_DONE;
|
|
state->proc_status = proc_status;
|
|
PLTFM_EVENT_SIG(HALMAC_FEATURE_SEND_SCAN_PACKET, proc_status,
|
|
NULL, 0);
|
|
} else {
|
|
proc_status = HALMAC_CMD_PROCESS_ERROR;
|
|
state->proc_status = proc_status;
|
|
PLTFM_EVENT_SIG(HALMAC_FEATURE_SEND_SCAN_PACKET, proc_status,
|
|
&state->fw_rc, 1);
|
|
}
|
|
|
|
return HALMAC_RET_SUCCESS;
|
|
}
|
|
|
|
static enum halmac_ret_status
|
|
get_h2c_ack_drop_scan_pkt_88xx(struct halmac_adapter *adapter,
|
|
u8 *buf, u32 size)
|
|
{
|
|
u8 seq_num;
|
|
u8 fw_rc;
|
|
struct halmac_drop_pkt_state *state =
|
|
&adapter->halmac_state.drop_pkt_state;
|
|
enum halmac_cmd_process_status proc_status;
|
|
|
|
seq_num = (u8)H2C_ACK_HDR_GET_H2C_SEQ(buf);
|
|
PLTFM_MSG_TRACE("[TRACE]Seq num : h2c->%d c2h->%d\n",
|
|
state->seq_num, seq_num);
|
|
if (seq_num != state->seq_num) {
|
|
PLTFM_MSG_ERR("[ERR]Seq num mismatch : h2c->%d c2h->%d\n",
|
|
state->seq_num, seq_num);
|
|
return HALMAC_RET_SUCCESS;
|
|
}
|
|
|
|
if (state->proc_status != HALMAC_CMD_PROCESS_SENDING) {
|
|
PLTFM_MSG_ERR("[ERR]not cmd sending\n");
|
|
return HALMAC_RET_SUCCESS;
|
|
}
|
|
|
|
fw_rc = (u8)H2C_ACK_HDR_GET_H2C_RETURN_CODE(buf);
|
|
state->fw_rc = fw_rc;
|
|
|
|
if (HALMAC_H2C_RETURN_SUCCESS == (enum halmac_h2c_return_code)fw_rc) {
|
|
proc_status = HALMAC_CMD_PROCESS_DONE;
|
|
state->proc_status = proc_status;
|
|
PLTFM_EVENT_SIG(HALMAC_FEATURE_DROP_SCAN_PACKET, proc_status,
|
|
NULL, 0);
|
|
} else {
|
|
proc_status = HALMAC_CMD_PROCESS_ERROR;
|
|
state->proc_status = proc_status;
|
|
PLTFM_EVENT_SIG(HALMAC_FEATURE_DROP_SCAN_PACKET, proc_status,
|
|
&state->fw_rc, 1);
|
|
}
|
|
|
|
return HALMAC_RET_SUCCESS;
|
|
}
|
|
|
|
static enum halmac_ret_status
|
|
get_h2c_ack_update_datapkt_88xx(struct halmac_adapter *adapter, u8 *buf,
|
|
u32 size)
|
|
{
|
|
return HALMAC_RET_NOT_SUPPORT;
|
|
}
|
|
|
|
static enum halmac_ret_status
|
|
get_h2c_ack_run_datapkt_88xx(struct halmac_adapter *adapter, u8 *buf, u32 size)
|
|
{
|
|
return HALMAC_RET_NOT_SUPPORT;
|
|
}
|
|
|
|
static enum halmac_ret_status
|
|
get_h2c_ack_ch_switch_88xx(struct halmac_adapter *adapter, u8 *buf, u32 size)
|
|
{
|
|
u8 seq_num;
|
|
u8 fw_rc;
|
|
struct halmac_scan_state *state = &adapter->halmac_state.scan_state;
|
|
struct halmac_scan_rpt_info *scan_rpt_info = &adapter->scan_rpt_info;
|
|
enum halmac_cmd_process_status proc_status;
|
|
|
|
seq_num = (u8)H2C_ACK_HDR_GET_H2C_SEQ(buf);
|
|
PLTFM_MSG_TRACE("[TRACE]Seq num : h2c->%d c2h->%d\n",
|
|
state->seq_num, seq_num);
|
|
if (seq_num != state->seq_num) {
|
|
PLTFM_MSG_ERR("[ERR]Seq num mismatch : h2c->%d c2h->%d\n",
|
|
state->seq_num, seq_num);
|
|
return HALMAC_RET_SUCCESS;
|
|
}
|
|
|
|
if (state->proc_status != HALMAC_CMD_PROCESS_SENDING) {
|
|
PLTFM_MSG_ERR("[ERR]not cmd sending\n");
|
|
return HALMAC_RET_SUCCESS;
|
|
}
|
|
|
|
fw_rc = (u8)H2C_ACK_HDR_GET_H2C_RETURN_CODE(buf);
|
|
state->fw_rc = fw_rc;
|
|
|
|
if (adapter->ch_sw_info.scan_mode == 1) {
|
|
scan_rpt_info->ack_tsf_low =
|
|
((CH_SWITCH_ACK_GET_TSF_3(buf) << 24) |
|
|
(CH_SWITCH_ACK_GET_TSF_2(buf) << 16) |
|
|
(CH_SWITCH_ACK_GET_TSF_1(buf) << 8) |
|
|
(CH_SWITCH_ACK_GET_TSF_0(buf)));
|
|
scan_rpt_info->ack_tsf_high =
|
|
((CH_SWITCH_ACK_GET_TSF_7(buf) << 24) |
|
|
(CH_SWITCH_ACK_GET_TSF_6(buf) << 16) |
|
|
(CH_SWITCH_ACK_GET_TSF_5(buf) << 8) |
|
|
(CH_SWITCH_ACK_GET_TSF_4(buf)));
|
|
}
|
|
|
|
if ((enum halmac_h2c_return_code)fw_rc == HALMAC_H2C_RETURN_SUCCESS) {
|
|
proc_status = HALMAC_CMD_PROCESS_RCVD;
|
|
state->proc_status = proc_status;
|
|
PLTFM_EVENT_SIG(HALMAC_FEATURE_CHANNEL_SWITCH, proc_status,
|
|
NULL, 0);
|
|
} else {
|
|
proc_status = HALMAC_CMD_PROCESS_ERROR;
|
|
state->proc_status = proc_status;
|
|
PLTFM_EVENT_SIG(HALMAC_FEATURE_CHANNEL_SWITCH, proc_status,
|
|
&fw_rc, 1);
|
|
}
|
|
|
|
return HALMAC_RET_SUCCESS;
|
|
}
|
|
|
|
/**
|
|
* mac_debug_88xx_v1() - read some registers for debug
|
|
* @adapter
|
|
* Author : KaiYuan Chang/Ivan Lin
|
|
* Return : enum halmac_ret_status
|
|
*/
|
|
enum halmac_ret_status
|
|
mac_debug_88xx(struct halmac_adapter *adapter)
|
|
{
|
|
PLTFM_MSG_TRACE("[TRACE]%s ===>\n", __func__);
|
|
|
|
if (adapter->intf == HALMAC_INTERFACE_SDIO)
|
|
dump_reg_sdio_88xx(adapter);
|
|
else
|
|
dump_reg_88xx(adapter);
|
|
|
|
PLTFM_MSG_TRACE("[TRACE]%s <===\n", __func__);
|
|
|
|
return HALMAC_RET_SUCCESS;
|
|
}
|
|
|
|
static void
|
|
dump_reg_sdio_88xx(struct halmac_adapter *adapter)
|
|
{
|
|
u8 tmp8;
|
|
u32 i;
|
|
|
|
/* Dump CCCR, it needs new platform api */
|
|
|
|
/*Dump SDIO Local Register, use CMD52*/
|
|
for (i = 0x10250000; i < 0x102500ff; i++) {
|
|
tmp8 = PLTFM_SDIO_CMD52_R(i);
|
|
PLTFM_MSG_TRACE("[TRACE]dbg-sdio[%x]=%x\n", i, tmp8);
|
|
}
|
|
|
|
/*Dump MAC Register*/
|
|
for (i = 0x0000; i < 0x17ff; i++) {
|
|
tmp8 = PLTFM_SDIO_CMD52_R(i);
|
|
PLTFM_MSG_TRACE("[TRACE]dbg-mac[%x]=%x\n", i, tmp8);
|
|
}
|
|
|
|
tmp8 = PLTFM_SDIO_CMD52_R(REG_SDIO_CRC_ERR_IDX);
|
|
if (tmp8)
|
|
PLTFM_MSG_ERR("[ERR]sdio crc=%x\n", tmp8);
|
|
|
|
/*Check RX Fifo status*/
|
|
i = REG_RXFF_PTR_V1;
|
|
tmp8 = PLTFM_SDIO_CMD52_R(i);
|
|
PLTFM_MSG_TRACE("[TRACE]dbg-mac[%x]=%x\n", i, tmp8);
|
|
i = REG_RXFF_WTR_V1;
|
|
tmp8 = PLTFM_SDIO_CMD52_R(i);
|
|
PLTFM_MSG_TRACE("[TRACE]dbg-mac[%x]=%x\n", i, tmp8);
|
|
i = REG_RXFF_PTR_V1;
|
|
tmp8 = PLTFM_SDIO_CMD52_R(i);
|
|
PLTFM_MSG_TRACE("[TRACE]dbg-mac[%x]=%x\n", i, tmp8);
|
|
i = REG_RXFF_WTR_V1;
|
|
tmp8 = PLTFM_SDIO_CMD52_R(i);
|
|
PLTFM_MSG_TRACE("[TRACE]dbg-mac[%x]=%x\n", i, tmp8);
|
|
}
|
|
|
|
static void
|
|
dump_reg_88xx(struct halmac_adapter *adapter)
|
|
{
|
|
u32 tmp32;
|
|
u32 i;
|
|
struct halmac_api *api = (struct halmac_api *)adapter->halmac_api;
|
|
|
|
/*Dump MAC Register*/
|
|
for (i = 0x0000; i < 0x17fc; i += 4) {
|
|
tmp32 = HALMAC_REG_R32(i);
|
|
PLTFM_MSG_TRACE("[TRACE]dbg-mac[%x]=%x\n", i, tmp32);
|
|
}
|
|
|
|
/*Check RX Fifo status*/
|
|
i = REG_RXFF_PTR_V1;
|
|
tmp32 = HALMAC_REG_R32(i);
|
|
PLTFM_MSG_TRACE("[TRACE]dbg-mac[%x]=%x\n", i, tmp32);
|
|
i = REG_RXFF_WTR_V1;
|
|
tmp32 = HALMAC_REG_R32(i);
|
|
PLTFM_MSG_TRACE("[TRACE]dbg-mac[%x]=%x\n", i, tmp32);
|
|
i = REG_RXFF_PTR_V1;
|
|
tmp32 = HALMAC_REG_R32(i);
|
|
PLTFM_MSG_TRACE("[TRACE]dbg-mac[%x]=%x\n", i, tmp32);
|
|
i = REG_RXFF_WTR_V1;
|
|
tmp32 = HALMAC_REG_R32(i);
|
|
PLTFM_MSG_TRACE("[TRACE]dbg-mac[%x]=%x\n", i, tmp32);
|
|
}
|
|
|
|
/**
|
|
* cfg_parameter_88xx() - config parameter by FW
|
|
* @adapter : the adapter of halmac
|
|
* @info : cmd id, content
|
|
* @full_fifo : parameter information
|
|
*
|
|
* If msk_en = 1, the format of array is {reg_info, mask, value}.
|
|
* If msk_en =_FAUSE, the format of array is {reg_info, value}
|
|
* The format of reg_info is
|
|
* reg_info[31]=rf_reg, 0: MAC_BB reg, 1: RF reg
|
|
* reg_info[27:24]=rf_path, 0: path_A, 1: path_B
|
|
* if rf_reg=0(MAC_BB reg), rf_path is meaningless.
|
|
* ref_info[15:0]=offset
|
|
*
|
|
* Example: msk_en = 0
|
|
* {0x8100000a, 0x00001122}
|
|
* =>Set RF register, path_B, offset 0xA to 0x00001122
|
|
* {0x00000824, 0x11224433}
|
|
* =>Set MAC_BB register, offset 0x800 to 0x11224433
|
|
*
|
|
* Note : full fifo mode only for init flow
|
|
*
|
|
* Author : KaiYuan Chang/Ivan Lin
|
|
* Return : enum halmac_ret_status
|
|
* More details of status code can be found in prototype document
|
|
*/
|
|
enum halmac_ret_status
|
|
cfg_parameter_88xx(struct halmac_adapter *adapter,
|
|
struct halmac_phy_parameter_info *info, u8 full_fifo)
|
|
{
|
|
enum halmac_ret_status status = HALMAC_RET_SUCCESS;
|
|
enum halmac_cmd_process_status *proc_status;
|
|
enum halmac_cmd_construct_state cmd_state;
|
|
|
|
proc_status = &adapter->halmac_state.cfg_param_state.proc_status;
|
|
|
|
if (halmac_fw_validate(adapter) != HALMAC_RET_SUCCESS)
|
|
return HALMAC_RET_NO_DLFW;
|
|
|
|
if (adapter->fw_ver.h2c_version < 4)
|
|
return HALMAC_RET_FW_NO_SUPPORT;
|
|
|
|
if (*proc_status == HALMAC_CMD_PROCESS_SENDING) {
|
|
PLTFM_MSG_TRACE("[TRACE]Wait event(para)\n");
|
|
return HALMAC_RET_BUSY_STATE;
|
|
}
|
|
|
|
cmd_state = cfg_param_cmd_cnstr_state_88xx(adapter);
|
|
if (cmd_state != HALMAC_CMD_CNSTR_IDLE &&
|
|
cmd_state != HALMAC_CMD_CNSTR_CNSTR) {
|
|
PLTFM_MSG_TRACE("[TRACE]Not idle(para)\n");
|
|
return HALMAC_RET_BUSY_STATE;
|
|
}
|
|
|
|
*proc_status = HALMAC_CMD_PROCESS_IDLE;
|
|
|
|
status = proc_cfg_param_88xx(adapter, info, full_fifo);
|
|
|
|
if (status != HALMAC_RET_SUCCESS && status != HALMAC_RET_PARA_SENDING) {
|
|
PLTFM_MSG_ERR("[ERR]send param h2c\n");
|
|
return status;
|
|
}
|
|
|
|
return status;
|
|
}
|
|
|
|
static enum halmac_cmd_construct_state
|
|
cfg_param_cmd_cnstr_state_88xx(struct halmac_adapter *adapter)
|
|
{
|
|
return adapter->halmac_state.cfg_param_state.cmd_cnstr_state;
|
|
}
|
|
|
|
static enum halmac_ret_status
|
|
proc_cfg_param_88xx(struct halmac_adapter *adapter,
|
|
struct halmac_phy_parameter_info *param, u8 full_fifo)
|
|
{
|
|
u8 end_cmd = 0;
|
|
u32 rsvd_size;
|
|
enum halmac_ret_status status = HALMAC_RET_SUCCESS;
|
|
struct halmac_cfg_param_info *info = &adapter->cfg_param_info;
|
|
enum halmac_cmd_process_status *proc_status;
|
|
|
|
proc_status = &adapter->halmac_state.cfg_param_state.proc_status;
|
|
|
|
status = malloc_cfg_param_buf_88xx(adapter, full_fifo);
|
|
if (status != HALMAC_RET_SUCCESS)
|
|
return status;
|
|
|
|
if (cnv_cfg_param_state_88xx(adapter, HALMAC_CMD_CNSTR_CNSTR) !=
|
|
HALMAC_RET_SUCCESS) {
|
|
PLTFM_FREE(info->buf, info->buf_size);
|
|
info->buf = NULL;
|
|
info->buf_wptr = NULL;
|
|
return HALMAC_RET_ERROR_STATE;
|
|
}
|
|
|
|
add_param_buf_88xx(adapter, param, info->buf_wptr, &end_cmd);
|
|
if (param->cmd_id != HALMAC_PARAMETER_CMD_END) {
|
|
info->num++;
|
|
info->buf_wptr += CFG_PARAM_H2C_INFO_SIZE;
|
|
info->avl_buf_size -= CFG_PARAM_H2C_INFO_SIZE;
|
|
}
|
|
|
|
rsvd_size = info->avl_buf_size - adapter->hw_cfg_info.txdesc_size;
|
|
if (rsvd_size > CFG_PARAM_H2C_INFO_SIZE && end_cmd == 0)
|
|
return HALMAC_RET_SUCCESS;
|
|
|
|
if (info->num == 0) {
|
|
PLTFM_FREE(info->buf, info->buf_size);
|
|
info->buf = NULL;
|
|
info->buf_wptr = NULL;
|
|
PLTFM_MSG_TRACE("[TRACE]param num = 0!!\n");
|
|
|
|
*proc_status = HALMAC_CMD_PROCESS_DONE;
|
|
PLTFM_EVENT_SIG(HALMAC_FEATURE_CFG_PARA, *proc_status, NULL, 0);
|
|
|
|
reset_ofld_feature_88xx(adapter, HALMAC_FEATURE_CFG_PARA);
|
|
|
|
return HALMAC_RET_SUCCESS;
|
|
}
|
|
|
|
status = send_cfg_param_h2c_88xx(adapter);
|
|
if (status != HALMAC_RET_SUCCESS) {
|
|
if (info->buf) {
|
|
PLTFM_FREE(info->buf, info->buf_size);
|
|
info->buf = NULL;
|
|
info->buf_wptr = NULL;
|
|
}
|
|
return status;
|
|
}
|
|
|
|
if (end_cmd == 0) {
|
|
PLTFM_MSG_TRACE("[TRACE]send h2c-buf full\n");
|
|
return HALMAC_RET_PARA_SENDING;
|
|
}
|
|
|
|
return status;
|
|
}
|
|
|
|
static enum halmac_ret_status
|
|
send_cfg_param_h2c_88xx(struct halmac_adapter *adapter)
|
|
{
|
|
u8 h2c_buf[H2C_PKT_SIZE_88XX] = { 0 };
|
|
u16 pg_addr;
|
|
u16 seq_num = 0;
|
|
u32 info_size;
|
|
struct halmac_h2c_header_info hdr_info;
|
|
enum halmac_ret_status status = HALMAC_RET_SUCCESS;
|
|
struct halmac_cfg_param_info *info = &adapter->cfg_param_info;
|
|
enum halmac_cmd_process_status *proc_status;
|
|
|
|
proc_status = &adapter->halmac_state.cfg_param_state.proc_status;
|
|
|
|
if (cnv_cfg_param_state_88xx(adapter, HALMAC_CMD_CNSTR_H2C_SENT) !=
|
|
HALMAC_RET_SUCCESS)
|
|
return HALMAC_RET_ERROR_STATE;
|
|
|
|
*proc_status = HALMAC_CMD_PROCESS_SENDING;
|
|
|
|
if (info->full_fifo_mode == 1)
|
|
pg_addr = 0;
|
|
else
|
|
pg_addr = adapter->txff_alloc.rsvd_h2c_info_addr;
|
|
|
|
info_size = info->num * CFG_PARAM_H2C_INFO_SIZE;
|
|
|
|
status = dl_rsvd_page_88xx(adapter, pg_addr, info->buf, info_size);
|
|
if (status != HALMAC_RET_SUCCESS) {
|
|
PLTFM_MSG_ERR("[ERR]dl rsvd pg!!\n");
|
|
goto CFG_PARAM_H2C_FAIL;
|
|
}
|
|
|
|
gen_cfg_param_h2c_88xx(adapter, h2c_buf);
|
|
|
|
hdr_info.sub_cmd_id = SUB_CMD_ID_CFG_PARAM;
|
|
hdr_info.content_size = 4;
|
|
hdr_info.ack = 1;
|
|
set_h2c_pkt_hdr_88xx(adapter, h2c_buf, &hdr_info, &seq_num);
|
|
|
|
adapter->halmac_state.cfg_param_state.seq_num = seq_num;
|
|
|
|
status = send_h2c_pkt_88xx(adapter, h2c_buf);
|
|
|
|
if (status != HALMAC_RET_SUCCESS) {
|
|
PLTFM_MSG_ERR("[ERR]send h2c!!\n");
|
|
reset_ofld_feature_88xx(adapter, HALMAC_FEATURE_CFG_PARA);
|
|
}
|
|
|
|
CFG_PARAM_H2C_FAIL:
|
|
PLTFM_FREE(info->buf, info->buf_size);
|
|
info->buf = NULL;
|
|
info->buf_wptr = NULL;
|
|
|
|
if (cnv_cfg_param_state_88xx(adapter, HALMAC_CMD_CNSTR_IDLE) !=
|
|
HALMAC_RET_SUCCESS)
|
|
return HALMAC_RET_ERROR_STATE;
|
|
|
|
return status;
|
|
}
|
|
|
|
static enum halmac_ret_status
|
|
cnv_cfg_param_state_88xx(struct halmac_adapter *adapter,
|
|
enum halmac_cmd_construct_state dest_state)
|
|
{
|
|
enum halmac_cmd_construct_state *state;
|
|
|
|
state = &adapter->halmac_state.cfg_param_state.cmd_cnstr_state;
|
|
|
|
if ((*state != HALMAC_CMD_CNSTR_IDLE) &&
|
|
(*state != HALMAC_CMD_CNSTR_CNSTR) &&
|
|
(*state != HALMAC_CMD_CNSTR_H2C_SENT))
|
|
return HALMAC_RET_ERROR_STATE;
|
|
|
|
if (dest_state == HALMAC_CMD_CNSTR_IDLE) {
|
|
if (*state == HALMAC_CMD_CNSTR_CNSTR)
|
|
return HALMAC_RET_ERROR_STATE;
|
|
} else if (dest_state == HALMAC_CMD_CNSTR_CNSTR) {
|
|
if (*state == HALMAC_CMD_CNSTR_H2C_SENT)
|
|
return HALMAC_RET_ERROR_STATE;
|
|
} else if (dest_state == HALMAC_CMD_CNSTR_H2C_SENT) {
|
|
if ((*state == HALMAC_CMD_CNSTR_IDLE) ||
|
|
(*state == HALMAC_CMD_CNSTR_H2C_SENT))
|
|
return HALMAC_RET_ERROR_STATE;
|
|
}
|
|
|
|
*state = dest_state;
|
|
|
|
return HALMAC_RET_SUCCESS;
|
|
}
|
|
|
|
static enum halmac_ret_status
|
|
add_param_buf_88xx(struct halmac_adapter *adapter,
|
|
struct halmac_phy_parameter_info *param, u8 *buf,
|
|
u8 *end_cmd)
|
|
{
|
|
struct halmac_cfg_param_info *info = &adapter->cfg_param_info;
|
|
union halmac_parameter_content *content = ¶m->content;
|
|
|
|
*end_cmd = 0;
|
|
|
|
PARAM_INFO_SET_LEN(buf, CFG_PARAM_H2C_INFO_SIZE);
|
|
PARAM_INFO_SET_IO_CMD(buf, param->cmd_id);
|
|
|
|
switch (param->cmd_id) {
|
|
case HALMAC_PARAMETER_CMD_BB_W8:
|
|
case HALMAC_PARAMETER_CMD_BB_W16:
|
|
case HALMAC_PARAMETER_CMD_BB_W32:
|
|
case HALMAC_PARAMETER_CMD_MAC_W8:
|
|
case HALMAC_PARAMETER_CMD_MAC_W16:
|
|
case HALMAC_PARAMETER_CMD_MAC_W32:
|
|
PARAM_INFO_SET_IO_ADDR(buf, content->MAC_REG_W.offset);
|
|
PARAM_INFO_SET_DATA(buf, content->MAC_REG_W.value);
|
|
PARAM_INFO_SET_MASK(buf, content->MAC_REG_W.msk);
|
|
PARAM_INFO_SET_MSK_EN(buf, content->MAC_REG_W.msk_en);
|
|
info->value_accum += content->MAC_REG_W.value;
|
|
info->offset_accum += content->MAC_REG_W.offset;
|
|
break;
|
|
case HALMAC_PARAMETER_CMD_RF_W:
|
|
/*In rf register, the address is only 1 byte*/
|
|
PARAM_INFO_SET_RF_ADDR(buf, content->RF_REG_W.offset);
|
|
PARAM_INFO_SET_RF_PATH(buf, content->RF_REG_W.rf_path);
|
|
PARAM_INFO_SET_DATA(buf, content->RF_REG_W.value);
|
|
PARAM_INFO_SET_MASK(buf, content->RF_REG_W.msk);
|
|
PARAM_INFO_SET_MSK_EN(buf, content->RF_REG_W.msk_en);
|
|
info->value_accum += content->RF_REG_W.value;
|
|
info->offset_accum += (content->RF_REG_W.offset +
|
|
(content->RF_REG_W.rf_path << 8));
|
|
break;
|
|
case HALMAC_PARAMETER_CMD_DELAY_US:
|
|
case HALMAC_PARAMETER_CMD_DELAY_MS:
|
|
PARAM_INFO_SET_DELAY_VAL(buf, content->DELAY_TIME.delay_time);
|
|
break;
|
|
case HALMAC_PARAMETER_CMD_END:
|
|
*end_cmd = 1;
|
|
break;
|
|
default:
|
|
PLTFM_MSG_ERR("[ERR]cmd id!!\n");
|
|
break;
|
|
}
|
|
|
|
return HALMAC_RET_SUCCESS;
|
|
}
|
|
|
|
static enum halmac_ret_status
|
|
gen_cfg_param_h2c_88xx(struct halmac_adapter *adapter, u8 *buff)
|
|
{
|
|
struct halmac_cfg_param_info *info = &adapter->cfg_param_info;
|
|
u16 h2c_info_addr = adapter->txff_alloc.rsvd_h2c_info_addr;
|
|
u16 rsvd_pg_addr = adapter->txff_alloc.rsvd_boundary;
|
|
|
|
CFG_PARAM_SET_NUM(buff, info->num);
|
|
|
|
if (info->full_fifo_mode == 1) {
|
|
CFG_PARAM_SET_INIT_CASE(buff, 0x1);
|
|
CFG_PARAM_SET_LOC(buff, 0);
|
|
} else {
|
|
CFG_PARAM_SET_INIT_CASE(buff, 0x0);
|
|
CFG_PARAM_SET_LOC(buff, h2c_info_addr - rsvd_pg_addr);
|
|
}
|
|
|
|
return HALMAC_RET_SUCCESS;
|
|
}
|
|
|
|
static enum halmac_ret_status
|
|
malloc_cfg_param_buf_88xx(struct halmac_adapter *adapter, u8 full_fifo)
|
|
{
|
|
struct halmac_cfg_param_info *info = &adapter->cfg_param_info;
|
|
struct halmac_pltfm_cfg_info *pltfm_info = &adapter->pltfm_info;
|
|
|
|
if (info->buf)
|
|
return HALMAC_RET_SUCCESS;
|
|
|
|
if (full_fifo == 1)
|
|
info->buf_size = pltfm_info->malloc_size;
|
|
else
|
|
info->buf_size = CFG_PARAM_RSVDPG_SIZE;
|
|
|
|
if (info->buf_size > pltfm_info->rsvd_pg_size)
|
|
info->buf_size = pltfm_info->rsvd_pg_size;
|
|
|
|
info->buf = smart_malloc_88xx(adapter, info->buf_size, &info->buf_size);
|
|
if (info->buf) {
|
|
PLTFM_MEMSET(info->buf, 0x00, info->buf_size);
|
|
info->full_fifo_mode = full_fifo;
|
|
info->buf_wptr = info->buf;
|
|
info->num = 0;
|
|
info->avl_buf_size = info->buf_size;
|
|
info->value_accum = 0;
|
|
info->offset_accum = 0;
|
|
} else {
|
|
return HALMAC_RET_MALLOC_FAIL;
|
|
}
|
|
|
|
return HALMAC_RET_SUCCESS;
|
|
}
|
|
|
|
/**
|
|
* update_packet_88xx() - send specific packet to FW
|
|
* @adapter : the adapter of halmac
|
|
* @pkt_id : packet id, to know the purpose of this packet
|
|
* @pkt : packet
|
|
* @size : packet size
|
|
*
|
|
* Note : TX_DESC is not included in the pkt
|
|
*
|
|
* Author : KaiYuan Chang/Ivan Lin
|
|
* Return : enum halmac_ret_status
|
|
* More details of status code can be found in prototype document
|
|
*/
|
|
enum halmac_ret_status
|
|
update_packet_88xx(struct halmac_adapter *adapter, enum halmac_packet_id pkt_id,
|
|
u8 *pkt, u32 size)
|
|
{
|
|
enum halmac_ret_status status = HALMAC_RET_SUCCESS;
|
|
enum halmac_cmd_process_status *proc_status =
|
|
&adapter->halmac_state.update_pkt_state.proc_status;
|
|
u8 *used_page = &adapter->halmac_state.update_pkt_state.used_page;
|
|
|
|
if (halmac_fw_validate(adapter) != HALMAC_RET_SUCCESS)
|
|
return HALMAC_RET_NO_DLFW;
|
|
|
|
if (adapter->fw_ver.h2c_version < 4)
|
|
return HALMAC_RET_FW_NO_SUPPORT;
|
|
|
|
if (size > UPDATE_PKT_RSVDPG_SIZE)
|
|
return HALMAC_RET_RSVD_PG_OVERFLOW_FAIL;
|
|
|
|
PLTFM_MSG_TRACE("[TRACE]%s ===>\n", __func__);
|
|
|
|
if (*proc_status == HALMAC_CMD_PROCESS_SENDING) {
|
|
PLTFM_MSG_TRACE("[TRACE]Wait event(upd)\n");
|
|
return HALMAC_RET_BUSY_STATE;
|
|
}
|
|
|
|
*proc_status = HALMAC_CMD_PROCESS_SENDING;
|
|
|
|
status = send_h2c_update_packet_88xx(adapter, pkt_id, pkt, size);
|
|
if (status != HALMAC_RET_SUCCESS) {
|
|
PLTFM_MSG_ERR("[ERR]send h2c!!\n");
|
|
PLTFM_MSG_ERR("[ERR]pkt id : %X!!\n", pkt_id);
|
|
return status;
|
|
}
|
|
|
|
*used_page = (u8)get_update_packet_page_size(adapter, size);
|
|
|
|
if (packet_in_nlo_88xx(adapter, pkt_id)) {
|
|
*proc_status = HALMAC_CMD_PROCESS_DONE;
|
|
adapter->nlo_flag = 1;
|
|
}
|
|
|
|
PLTFM_MSG_TRACE("[TRACE]%s <===\n", __func__);
|
|
|
|
return HALMAC_RET_SUCCESS;
|
|
}
|
|
|
|
static enum halmac_ret_status
|
|
send_h2c_update_packet_88xx(struct halmac_adapter *adapter,
|
|
enum halmac_packet_id pkt_id, u8 *pkt, u32 size)
|
|
{
|
|
u8 h2c_buf[H2C_PKT_SIZE_88XX] = { 0 };
|
|
u16 seq_num = 0;
|
|
u16 pg_addr = adapter->txff_alloc.rsvd_h2c_info_addr;
|
|
u16 pg_offset;
|
|
struct halmac_h2c_header_info hdr_info;
|
|
enum halmac_ret_status status = HALMAC_RET_SUCCESS;
|
|
enum halmac_packet_id real_pkt_id;
|
|
|
|
status = dl_rsvd_page_88xx(adapter, pg_addr, pkt, size);
|
|
if (status != HALMAC_RET_SUCCESS) {
|
|
PLTFM_MSG_ERR("[ERR]dl rsvd pg!!\n");
|
|
return status;
|
|
}
|
|
|
|
real_pkt_id = get_real_pkt_id_88xx(adapter, pkt_id);
|
|
pg_offset = pg_addr - adapter->txff_alloc.rsvd_boundary;
|
|
UPDATE_PKT_SET_SIZE(h2c_buf, size + adapter->hw_cfg_info.txdesc_size);
|
|
UPDATE_PKT_SET_ID(h2c_buf, real_pkt_id);
|
|
UPDATE_PKT_SET_LOC(h2c_buf, pg_offset);
|
|
|
|
hdr_info.sub_cmd_id = SUB_CMD_ID_UPDATE_PKT;
|
|
hdr_info.content_size = 4;
|
|
if (packet_in_nlo_88xx(adapter, pkt_id))
|
|
hdr_info.ack = 0;
|
|
else
|
|
hdr_info.ack = 1;
|
|
set_h2c_pkt_hdr_88xx(adapter, h2c_buf, &hdr_info, &seq_num);
|
|
adapter->halmac_state.update_pkt_state.seq_num = seq_num;
|
|
|
|
status = send_h2c_pkt_88xx(adapter, h2c_buf);
|
|
|
|
if (status != HALMAC_RET_SUCCESS) {
|
|
PLTFM_MSG_ERR("[ERR]send h2c!!\n");
|
|
reset_ofld_feature_88xx(adapter, HALMAC_FEATURE_UPDATE_PACKET);
|
|
return status;
|
|
}
|
|
|
|
return status;
|
|
}
|
|
|
|
enum halmac_ret_status
|
|
send_scan_packet_88xx(struct halmac_adapter *adapter, u8 index,
|
|
u8 *pkt, u32 size)
|
|
{
|
|
enum halmac_ret_status status = HALMAC_RET_SUCCESS;
|
|
enum halmac_cmd_process_status *proc_status =
|
|
&adapter->halmac_state.scan_pkt_state.proc_status;
|
|
|
|
if (halmac_fw_validate(adapter) != HALMAC_RET_SUCCESS)
|
|
return HALMAC_RET_NO_DLFW;
|
|
|
|
if (adapter->fw_ver.h2c_version < 13)
|
|
return HALMAC_RET_FW_NO_SUPPORT;
|
|
|
|
if (size > UPDATE_PKT_RSVDPG_SIZE)
|
|
return HALMAC_RET_RSVD_PG_OVERFLOW_FAIL;
|
|
|
|
PLTFM_MSG_TRACE("[TRACE]%s ===>\n", __func__);
|
|
|
|
if (*proc_status == HALMAC_CMD_PROCESS_SENDING) {
|
|
PLTFM_MSG_TRACE("[TRACE]Wait event(send_scan)\n");
|
|
return HALMAC_RET_BUSY_STATE;
|
|
}
|
|
|
|
*proc_status = HALMAC_CMD_PROCESS_SENDING;
|
|
|
|
status = send_h2c_send_scan_packet_88xx(adapter, index, pkt, size);
|
|
if (status != HALMAC_RET_SUCCESS)
|
|
return status;
|
|
|
|
PLTFM_MSG_TRACE("[TRACE]%s <===\n", __func__);
|
|
|
|
return HALMAC_RET_SUCCESS;
|
|
}
|
|
|
|
static enum halmac_ret_status
|
|
send_h2c_send_scan_packet_88xx(struct halmac_adapter *adapter,
|
|
u8 index, u8 *pkt, u32 size)
|
|
{
|
|
u8 h2c_buf[H2C_PKT_SIZE_88XX] = { 0 };
|
|
u16 seq_num = 0;
|
|
u16 pg_addr = adapter->txff_alloc.rsvd_h2c_info_addr;
|
|
u16 pg_offset;
|
|
struct halmac_h2c_header_info hdr_info;
|
|
enum halmac_ret_status status = HALMAC_RET_SUCCESS;
|
|
|
|
status = dl_rsvd_page_88xx(adapter, pg_addr, pkt, size);
|
|
if (status != HALMAC_RET_SUCCESS) {
|
|
PLTFM_MSG_ERR("[ERR]dl rsvd pg!!\n");
|
|
return status;
|
|
}
|
|
|
|
pg_offset = pg_addr - adapter->txff_alloc.rsvd_boundary;
|
|
SEND_SCAN_PKT_SET_SIZE(h2c_buf, size +
|
|
adapter->hw_cfg_info.txdesc_size);
|
|
SEND_SCAN_PKT_SET_INDEX(h2c_buf, index);
|
|
SEND_SCAN_PKT_SET_LOC(h2c_buf, pg_offset);
|
|
|
|
hdr_info.sub_cmd_id = SUB_CMD_ID_SEND_SCAN_PKT;
|
|
hdr_info.content_size = 8;
|
|
hdr_info.ack = 1;
|
|
set_h2c_pkt_hdr_88xx(adapter, h2c_buf, &hdr_info, &seq_num);
|
|
adapter->halmac_state.scan_pkt_state.seq_num = seq_num;
|
|
|
|
status = send_h2c_pkt_88xx(adapter, h2c_buf);
|
|
|
|
if (status != HALMAC_RET_SUCCESS) {
|
|
PLTFM_MSG_ERR("[ERR]send h2c!!\n");
|
|
reset_ofld_feature_88xx(adapter,
|
|
HALMAC_FEATURE_SEND_SCAN_PACKET);
|
|
return status;
|
|
}
|
|
|
|
return status;
|
|
}
|
|
|
|
enum halmac_ret_status
|
|
drop_scan_packet_88xx(struct halmac_adapter *adapter,
|
|
struct halmac_drop_pkt_option *option)
|
|
{
|
|
enum halmac_ret_status status = HALMAC_RET_SUCCESS;
|
|
enum halmac_cmd_process_status *proc_status =
|
|
&adapter->halmac_state.drop_pkt_state.proc_status;
|
|
|
|
if (halmac_fw_validate(adapter) != HALMAC_RET_SUCCESS)
|
|
return HALMAC_RET_NO_DLFW;
|
|
|
|
if (adapter->fw_ver.h2c_version < 13)
|
|
return HALMAC_RET_FW_NO_SUPPORT;
|
|
|
|
PLTFM_MSG_TRACE("[TRACE]%s ===>\n", __func__);
|
|
|
|
if (*proc_status == HALMAC_CMD_PROCESS_SENDING) {
|
|
PLTFM_MSG_TRACE("[TRACE]Wait event(drop_scan)\n");
|
|
return HALMAC_RET_BUSY_STATE;
|
|
}
|
|
|
|
*proc_status = HALMAC_CMD_PROCESS_SENDING;
|
|
|
|
status = send_h2c_drop_scan_packet_88xx(adapter, option);
|
|
if (status != HALMAC_RET_SUCCESS)
|
|
return status;
|
|
|
|
PLTFM_MSG_TRACE("[TRACE]%s <===\n", __func__);
|
|
|
|
return HALMAC_RET_SUCCESS;
|
|
}
|
|
|
|
static enum halmac_ret_status
|
|
send_h2c_drop_scan_packet_88xx(struct halmac_adapter *adapter,
|
|
struct halmac_drop_pkt_option *option)
|
|
{
|
|
u8 h2c_buf[H2C_PKT_SIZE_88XX] = { 0 };
|
|
u16 seq_num = 0;
|
|
struct halmac_h2c_header_info hdr_info;
|
|
enum halmac_ret_status status = HALMAC_RET_SUCCESS;
|
|
|
|
PLTFM_MSG_TRACE("[TRACE]%s\n", __func__);
|
|
|
|
DROP_SCAN_PKT_SET_DROP_ALL(h2c_buf, option->drop_all);
|
|
DROP_SCAN_PKT_SET_DROP_SINGLE(h2c_buf, option->drop_single);
|
|
DROP_SCAN_PKT_SET_DROP_IDX(h2c_buf, option->drop_index);
|
|
|
|
hdr_info.sub_cmd_id = SUB_CMD_ID_DROP_SCAN_PKT;
|
|
hdr_info.content_size = 8;
|
|
hdr_info.ack = 1;
|
|
set_h2c_pkt_hdr_88xx(adapter, h2c_buf, &hdr_info, &seq_num);
|
|
adapter->halmac_state.drop_pkt_state.seq_num = seq_num;
|
|
|
|
status = send_h2c_pkt_88xx(adapter, h2c_buf);
|
|
|
|
if (status != HALMAC_RET_SUCCESS) {
|
|
PLTFM_MSG_ERR("[ERR]send h2c!!\n");
|
|
reset_ofld_feature_88xx(adapter,
|
|
HALMAC_FEATURE_DROP_SCAN_PACKET);
|
|
return status;
|
|
}
|
|
|
|
return status;
|
|
}
|
|
|
|
enum halmac_ret_status
|
|
bcn_ie_filter_88xx(struct halmac_adapter *adapter,
|
|
struct halmac_bcn_ie_info *info)
|
|
{
|
|
return HALMAC_RET_NOT_SUPPORT;
|
|
}
|
|
|
|
enum halmac_ret_status
|
|
update_datapack_88xx(struct halmac_adapter *adapter,
|
|
enum halmac_data_type data_type,
|
|
struct halmac_phy_parameter_info *info)
|
|
{
|
|
return HALMAC_RET_NOT_SUPPORT;
|
|
}
|
|
|
|
enum halmac_ret_status
|
|
run_datapack_88xx(struct halmac_adapter *adapter,
|
|
enum halmac_data_type data_type)
|
|
{
|
|
return HALMAC_RET_NOT_SUPPORT;
|
|
}
|
|
|
|
enum halmac_ret_status
|
|
send_bt_coex_88xx(struct halmac_adapter *adapter, u8 *buf, u32 size, u8 ack)
|
|
{
|
|
enum halmac_ret_status status = HALMAC_RET_SUCCESS;
|
|
|
|
if (halmac_fw_validate(adapter) != HALMAC_RET_SUCCESS)
|
|
return HALMAC_RET_NO_DLFW;
|
|
|
|
PLTFM_MSG_TRACE("[TRACE]%s ===>\n", __func__);
|
|
|
|
status = send_bt_coex_cmd_88xx(adapter, buf, size, ack);
|
|
|
|
if (status != HALMAC_RET_SUCCESS) {
|
|
PLTFM_MSG_ERR("[ERR]bt coex cmd!!\n");
|
|
return status;
|
|
}
|
|
|
|
PLTFM_MSG_TRACE("[TRACE]%s <===\n", __func__);
|
|
|
|
return HALMAC_RET_SUCCESS;
|
|
}
|
|
|
|
static enum halmac_ret_status
|
|
send_bt_coex_cmd_88xx(struct halmac_adapter *adapter, u8 *buf, u32 size,
|
|
u8 ack)
|
|
{
|
|
u8 h2c_buf[H2C_PKT_SIZE_88XX] = { 0 };
|
|
u16 seq_num = 0;
|
|
struct halmac_h2c_header_info hdr_info;
|
|
enum halmac_ret_status status = HALMAC_RET_SUCCESS;
|
|
|
|
PLTFM_MSG_TRACE("[TRACE]%s ===>\n", __func__);
|
|
|
|
PLTFM_MEMCPY(h2c_buf + 8, buf, size);
|
|
|
|
hdr_info.sub_cmd_id = SUB_CMD_ID_BT_COEX;
|
|
hdr_info.content_size = (u16)size;
|
|
hdr_info.ack = ack;
|
|
set_h2c_pkt_hdr_88xx(adapter, h2c_buf, &hdr_info, &seq_num);
|
|
|
|
status = send_h2c_pkt_88xx(adapter, h2c_buf);
|
|
|
|
if (status != HALMAC_RET_SUCCESS) {
|
|
PLTFM_MSG_ERR("[ERR]send h2c!!\n");
|
|
return status;
|
|
}
|
|
|
|
return HALMAC_RET_SUCCESS;
|
|
}
|
|
|
|
/**
|
|
* dump_fifo_88xx() - dump fifo data
|
|
* @adapter : the adapter of halmac
|
|
* @sel : FIFO selection
|
|
* @start_addr : start address of selected FIFO
|
|
* @size : dump size of selected FIFO
|
|
* @data : FIFO data
|
|
*
|
|
* Note : before dump fifo, user need to call halmac_get_fifo_size to
|
|
* get fifo size. Then input this size to halmac_dump_fifo.
|
|
*
|
|
* Author : Ivan Lin/KaiYuan Chang
|
|
* Return : enum halmac_ret_status
|
|
* More details of status code can be found in prototype document
|
|
*/
|
|
enum halmac_ret_status
|
|
dump_fifo_88xx(struct halmac_adapter *adapter, enum hal_fifo_sel sel,
|
|
u32 start_addr, u32 size, u8 *data)
|
|
{
|
|
enum halmac_ret_status status = HALMAC_RET_SUCCESS;
|
|
u8 tmp8;
|
|
u8 enable;
|
|
struct halmac_api *api = (struct halmac_api *)adapter->halmac_api;
|
|
|
|
PLTFM_MSG_TRACE("[TRACE]%s ===>\n", __func__);
|
|
|
|
if (sel == HAL_FIFO_SEL_TX &&
|
|
(start_addr + size) > adapter->hw_cfg_info.tx_fifo_size) {
|
|
PLTFM_MSG_ERR("[ERR]size overflow!!\n");
|
|
return HALMAC_RET_DUMP_FIFOSIZE_INCORRECT;
|
|
}
|
|
|
|
if (sel == HAL_FIFO_SEL_RX &&
|
|
(start_addr + size) > adapter->hw_cfg_info.rx_fifo_size) {
|
|
PLTFM_MSG_ERR("[ERR]size overflow!!\n");
|
|
return HALMAC_RET_DUMP_FIFOSIZE_INCORRECT;
|
|
}
|
|
|
|
if ((size & (4 - 1)) != 0) {
|
|
PLTFM_MSG_ERR("[ERR]not 4byte alignment!!\n");
|
|
return HALMAC_RET_DUMP_FIFOSIZE_INCORRECT;
|
|
}
|
|
|
|
if (!data)
|
|
return HALMAC_RET_NULL_POINTER;
|
|
|
|
tmp8 = HALMAC_REG_R8(REG_RCR + 2);
|
|
enable = 0;
|
|
status = api->halmac_set_hw_value(adapter, HALMAC_HW_RX_CLK_GATE,
|
|
&enable);
|
|
if (status != HALMAC_RET_SUCCESS)
|
|
return status;
|
|
status = read_buf_88xx(adapter, start_addr, size, sel, data);
|
|
|
|
HALMAC_REG_W8(REG_RCR + 2, tmp8);
|
|
|
|
if (status != HALMAC_RET_SUCCESS) {
|
|
PLTFM_MSG_ERR("[ERR]read buf!!\n");
|
|
return status;
|
|
}
|
|
|
|
PLTFM_MSG_TRACE("[TRACE]%s <===\n", __func__);
|
|
|
|
return HALMAC_RET_SUCCESS;
|
|
}
|
|
|
|
static enum halmac_ret_status
|
|
read_buf_88xx(struct halmac_adapter *adapter, u32 offset, u32 size,
|
|
enum hal_fifo_sel sel, u8 *data)
|
|
{
|
|
u32 start_pg;
|
|
u32 value32;
|
|
u32 i;
|
|
u32 residue;
|
|
u32 cnt = 0;
|
|
struct halmac_api *api = (struct halmac_api *)adapter->halmac_api;
|
|
|
|
if (sel == HAL_FIFO_SEL_RSVD_PAGE)
|
|
offset += (adapter->txff_alloc.rsvd_boundary <<
|
|
TX_PAGE_SIZE_SHIFT_88XX);
|
|
|
|
start_pg = offset >> 12;
|
|
residue = offset & (4096 - 1);
|
|
|
|
if (sel == HAL_FIFO_SEL_TX || sel == HAL_FIFO_SEL_RSVD_PAGE)
|
|
start_pg += 0x780;
|
|
else if (sel == HAL_FIFO_SEL_RX)
|
|
start_pg += 0x700;
|
|
else if (sel == HAL_FIFO_SEL_REPORT)
|
|
start_pg += 0x660;
|
|
else if (sel == HAL_FIFO_SEL_LLT)
|
|
start_pg += 0x650;
|
|
else if (sel == HAL_FIFO_SEL_RXBUF_FW)
|
|
start_pg += 0x680;
|
|
else
|
|
return HALMAC_RET_NOT_SUPPORT;
|
|
|
|
value32 = HALMAC_REG_R16(REG_PKTBUF_DBG_CTRL) & 0xF000;
|
|
|
|
do {
|
|
HALMAC_REG_W16(REG_PKTBUF_DBG_CTRL, (u16)(start_pg | value32));
|
|
|
|
for (i = 0x8000 + residue; i <= 0x8FFF; i += 4) {
|
|
*(u32 *)(data + cnt) = HALMAC_REG_R32(i);
|
|
*(u32 *)(data + cnt) =
|
|
rtk_le32_to_cpu(*(u32 *)(data + cnt));
|
|
cnt += 4;
|
|
if (size == cnt)
|
|
goto HALMAC_BUF_READ_OK;
|
|
}
|
|
|
|
residue = 0;
|
|
start_pg++;
|
|
} while (1);
|
|
|
|
HALMAC_BUF_READ_OK:
|
|
HALMAC_REG_W16(REG_PKTBUF_DBG_CTRL, (u16)value32);
|
|
|
|
return HALMAC_RET_SUCCESS;
|
|
}
|
|
|
|
/**
|
|
* get_fifo_size_88xx() - get fifo size
|
|
* @adapter : the adapter of halmac
|
|
* @sel : FIFO selection
|
|
* Author : Ivan Lin/KaiYuan Chang
|
|
* Return : u32
|
|
* More details of status code can be found in prototype document
|
|
*/
|
|
u32
|
|
get_fifo_size_88xx(struct halmac_adapter *adapter, enum hal_fifo_sel sel)
|
|
{
|
|
u32 size = 0;
|
|
|
|
if (sel == HAL_FIFO_SEL_TX)
|
|
size = adapter->hw_cfg_info.tx_fifo_size;
|
|
else if (sel == HAL_FIFO_SEL_RX)
|
|
size = adapter->hw_cfg_info.rx_fifo_size;
|
|
else if (sel == HAL_FIFO_SEL_RSVD_PAGE)
|
|
size = adapter->hw_cfg_info.tx_fifo_size -
|
|
(adapter->txff_alloc.rsvd_boundary <<
|
|
TX_PAGE_SIZE_SHIFT_88XX);
|
|
else if (sel == HAL_FIFO_SEL_REPORT)
|
|
size = 65536;
|
|
else if (sel == HAL_FIFO_SEL_LLT)
|
|
size = 65536;
|
|
else if (sel == HAL_FIFO_SEL_RXBUF_FW)
|
|
size = RX_BUF_FW_88XX;
|
|
|
|
return size;
|
|
}
|
|
|
|
enum halmac_ret_status
|
|
set_h2c_header_88xx(struct halmac_adapter *adapter, u8 *hdr, u16 *seq, u8 ack)
|
|
{
|
|
PLTFM_MSG_TRACE("[TRACE]%s!!\n", __func__);
|
|
|
|
H2C_CMD_HEADER_SET_CATEGORY(hdr, 0x00);
|
|
H2C_CMD_HEADER_SET_TOTAL_LEN(hdr, 16);
|
|
|
|
PLTFM_MUTEX_LOCK(&adapter->h2c_seq_mutex);
|
|
H2C_CMD_HEADER_SET_SEQ_NUM(hdr, adapter->h2c_info.seq_num);
|
|
*seq = adapter->h2c_info.seq_num;
|
|
(adapter->h2c_info.seq_num)++;
|
|
PLTFM_MUTEX_UNLOCK(&adapter->h2c_seq_mutex);
|
|
|
|
if (ack == 1)
|
|
H2C_CMD_HEADER_SET_ACK(hdr, 1);
|
|
|
|
return HALMAC_RET_SUCCESS;
|
|
}
|
|
|
|
/**
|
|
* add_ch_info_88xx() -add channel information
|
|
* @adapter : the adapter of halmac
|
|
* @info : channel information
|
|
* Author : KaiYuan Chang/Ivan Lin
|
|
* Return : enum halmac_ret_status
|
|
* More details of status code can be found in prototype document
|
|
*/
|
|
enum halmac_ret_status
|
|
add_ch_info_88xx(struct halmac_adapter *adapter, struct halmac_ch_info *info)
|
|
{
|
|
struct halmac_ch_sw_info *ch_sw_info = &adapter->ch_sw_info;
|
|
enum halmac_cmd_construct_state state;
|
|
|
|
PLTFM_MSG_TRACE("[TRACE]%s ===>\n", __func__);
|
|
|
|
if (adapter->halmac_state.dlfw_state != HALMAC_GEN_INFO_SENT) {
|
|
PLTFM_MSG_ERR("[ERR]gen info\n");
|
|
return HALMAC_RET_GEN_INFO_NOT_SENT;
|
|
}
|
|
|
|
state = scan_cmd_cnstr_state_88xx(adapter);
|
|
if (state != HALMAC_CMD_CNSTR_BUF_CLR &&
|
|
state != HALMAC_CMD_CNSTR_CNSTR) {
|
|
PLTFM_MSG_WARN("[WARN]cmd state (scan)\n");
|
|
return HALMAC_RET_ERROR_STATE;
|
|
}
|
|
|
|
if (!ch_sw_info->buf) {
|
|
ch_sw_info->buf = (u8 *)PLTFM_MALLOC(SCAN_INFO_RSVDPG_SIZE);
|
|
if (!ch_sw_info->buf)
|
|
return HALMAC_RET_NULL_POINTER;
|
|
ch_sw_info->buf_wptr = ch_sw_info->buf;
|
|
ch_sw_info->buf_size = SCAN_INFO_RSVDPG_SIZE;
|
|
ch_sw_info->avl_buf_size = SCAN_INFO_RSVDPG_SIZE;
|
|
ch_sw_info->total_size = 0;
|
|
ch_sw_info->extra_info_en = 0;
|
|
ch_sw_info->ch_num = 0;
|
|
}
|
|
|
|
if (ch_sw_info->extra_info_en == 1) {
|
|
PLTFM_MSG_ERR("[ERR]extra info = 1!!\n");
|
|
return HALMAC_RET_CH_SW_SEQ_WRONG;
|
|
}
|
|
|
|
if (ch_sw_info->avl_buf_size < 4) {
|
|
PLTFM_MSG_ERR("[ERR]buf full!!\n");
|
|
return HALMAC_RET_CH_SW_NO_BUF;
|
|
}
|
|
|
|
if (cnv_scan_state_88xx(adapter, HALMAC_CMD_CNSTR_CNSTR) !=
|
|
HALMAC_RET_SUCCESS)
|
|
return HALMAC_RET_ERROR_STATE;
|
|
|
|
CH_INFO_SET_CH(ch_sw_info->buf_wptr, info->channel);
|
|
CH_INFO_SET_PRI_CH_IDX(ch_sw_info->buf_wptr, info->pri_ch_idx);
|
|
CH_INFO_SET_BW(ch_sw_info->buf_wptr, info->bw);
|
|
CH_INFO_SET_TIMEOUT(ch_sw_info->buf_wptr, info->timeout);
|
|
CH_INFO_SET_ACTION_ID(ch_sw_info->buf_wptr, info->action_id);
|
|
CH_INFO_SET_EXTRA_INFO(ch_sw_info->buf_wptr, info->extra_info);
|
|
|
|
ch_sw_info->avl_buf_size = ch_sw_info->avl_buf_size - 4;
|
|
ch_sw_info->total_size = ch_sw_info->total_size + 4;
|
|
ch_sw_info->ch_num++;
|
|
ch_sw_info->extra_info_en = info->extra_info;
|
|
ch_sw_info->buf_wptr = ch_sw_info->buf_wptr + 4;
|
|
|
|
PLTFM_MSG_TRACE("[TRACE]%s <===\n", __func__);
|
|
|
|
return HALMAC_RET_SUCCESS;
|
|
}
|
|
|
|
static enum halmac_cmd_construct_state
|
|
scan_cmd_cnstr_state_88xx(struct halmac_adapter *adapter)
|
|
{
|
|
return adapter->halmac_state.scan_state.cmd_cnstr_state;
|
|
}
|
|
|
|
static enum halmac_ret_status
|
|
cnv_scan_state_88xx(struct halmac_adapter *adapter,
|
|
enum halmac_cmd_construct_state dest_state)
|
|
{
|
|
enum halmac_cmd_construct_state *state;
|
|
|
|
state = &adapter->halmac_state.scan_state.cmd_cnstr_state;
|
|
|
|
if (dest_state == HALMAC_CMD_CNSTR_IDLE) {
|
|
if ((*state == HALMAC_CMD_CNSTR_BUF_CLR) ||
|
|
(*state == HALMAC_CMD_CNSTR_CNSTR))
|
|
return HALMAC_RET_ERROR_STATE;
|
|
} else if (dest_state == HALMAC_CMD_CNSTR_BUF_CLR) {
|
|
if (*state == HALMAC_CMD_CNSTR_H2C_SENT)
|
|
return HALMAC_RET_ERROR_STATE;
|
|
} else if (dest_state == HALMAC_CMD_CNSTR_CNSTR) {
|
|
if ((*state == HALMAC_CMD_CNSTR_IDLE) ||
|
|
(*state == HALMAC_CMD_CNSTR_H2C_SENT))
|
|
return HALMAC_RET_ERROR_STATE;
|
|
} else if (dest_state == HALMAC_CMD_CNSTR_H2C_SENT) {
|
|
if ((*state != HALMAC_CMD_CNSTR_CNSTR) &&
|
|
(*state != HALMAC_CMD_CNSTR_BUF_CLR))
|
|
return HALMAC_RET_ERROR_STATE;
|
|
}
|
|
|
|
*state = dest_state;
|
|
|
|
return HALMAC_RET_SUCCESS;
|
|
}
|
|
|
|
/**
|
|
* add_extra_ch_info_88xx() -add extra channel information
|
|
* @adapter : the adapter of halmac
|
|
* @info : extra channel information
|
|
* Author : KaiYuan Chang/Ivan Lin
|
|
* Return : enum halmac_ret_status
|
|
* More details of status code can be found in prototype document
|
|
*/
|
|
enum halmac_ret_status
|
|
add_extra_ch_info_88xx(struct halmac_adapter *adapter,
|
|
struct halmac_ch_extra_info *info)
|
|
{
|
|
struct halmac_ch_sw_info *ch_sw_info = &adapter->ch_sw_info;
|
|
|
|
PLTFM_MSG_TRACE("[TRACE]%s ===>\n", __func__);
|
|
|
|
if (!ch_sw_info->buf) {
|
|
PLTFM_MSG_ERR("[ERR]buf = null!!\n");
|
|
return HALMAC_RET_CH_SW_SEQ_WRONG;
|
|
}
|
|
|
|
if (ch_sw_info->extra_info_en == 0) {
|
|
PLTFM_MSG_ERR("[ERR]extra info = 0!!\n");
|
|
return HALMAC_RET_CH_SW_SEQ_WRONG;
|
|
}
|
|
|
|
if (ch_sw_info->avl_buf_size < (u32)(info->extra_info_size + 2)) {
|
|
PLTFM_MSG_ERR("[ERR]no available buffer!!\n");
|
|
return HALMAC_RET_CH_SW_NO_BUF;
|
|
}
|
|
|
|
if (scan_cmd_cnstr_state_88xx(adapter) != HALMAC_CMD_CNSTR_CNSTR) {
|
|
PLTFM_MSG_WARN("[WARN]cmd state (ex scan)\n");
|
|
return HALMAC_RET_ERROR_STATE;
|
|
}
|
|
|
|
if (cnv_scan_state_88xx(adapter, HALMAC_CMD_CNSTR_CNSTR) !=
|
|
HALMAC_RET_SUCCESS)
|
|
return HALMAC_RET_ERROR_STATE;
|
|
|
|
CH_EXTRA_INFO_SET_ID(ch_sw_info->buf_wptr, info->extra_action_id);
|
|
CH_EXTRA_INFO_SET_INFO(ch_sw_info->buf_wptr, info->extra_info);
|
|
CH_EXTRA_INFO_SET_SIZE(ch_sw_info->buf_wptr, info->extra_info_size);
|
|
PLTFM_MEMCPY(ch_sw_info->buf_wptr + 2, info->extra_info_data,
|
|
info->extra_info_size);
|
|
|
|
ch_sw_info->avl_buf_size -= (2 + info->extra_info_size);
|
|
ch_sw_info->total_size += (2 + info->extra_info_size);
|
|
ch_sw_info->extra_info_en = info->extra_info;
|
|
ch_sw_info->buf_wptr += (2 + info->extra_info_size);
|
|
|
|
PLTFM_MSG_TRACE("[TRACE]%s <===\n", __func__);
|
|
|
|
return HALMAC_RET_SUCCESS;
|
|
}
|
|
|
|
/**
|
|
* ctrl_ch_switch_88xx() -send channel switch cmd
|
|
* @adapter : the adapter of halmac
|
|
* @opt : channel switch config
|
|
* Author : KaiYuan Chang/Ivan Lin
|
|
* Return : enum halmac_ret_status
|
|
* More details of status code can be found in prototype document
|
|
*/
|
|
enum halmac_ret_status
|
|
ctrl_ch_switch_88xx(struct halmac_adapter *adapter,
|
|
struct halmac_ch_switch_option *opt)
|
|
{
|
|
enum halmac_ret_status status = HALMAC_RET_SUCCESS;
|
|
enum halmac_cmd_construct_state state;
|
|
enum halmac_cmd_process_status *proc_status;
|
|
|
|
proc_status = &adapter->halmac_state.scan_state.proc_status;
|
|
|
|
if (halmac_fw_validate(adapter) != HALMAC_RET_SUCCESS)
|
|
return HALMAC_RET_NO_DLFW;
|
|
|
|
if (adapter->fw_ver.h2c_version < 4)
|
|
return HALMAC_RET_FW_NO_SUPPORT;
|
|
|
|
if (adapter->ch_sw_info.total_size +
|
|
(adapter->halmac_state.update_pkt_state.used_page <<
|
|
TX_PAGE_SIZE_SHIFT_88XX) >
|
|
(u32)adapter->txff_alloc.rsvd_pg_num << TX_PAGE_SIZE_SHIFT_88XX)
|
|
return HALMAC_RET_RSVD_PG_OVERFLOW_FAIL;
|
|
|
|
PLTFM_MSG_TRACE("[TRACE]%s ===>\n", __func__);
|
|
|
|
if (opt->switch_en == 0)
|
|
*proc_status = HALMAC_CMD_PROCESS_IDLE;
|
|
|
|
if ((*proc_status == HALMAC_CMD_PROCESS_SENDING) ||
|
|
(*proc_status == HALMAC_CMD_PROCESS_RCVD)) {
|
|
PLTFM_MSG_TRACE("[TRACE]Wait event(scan)\n");
|
|
return HALMAC_RET_BUSY_STATE;
|
|
}
|
|
|
|
state = scan_cmd_cnstr_state_88xx(adapter);
|
|
if (opt->switch_en == 1) {
|
|
if (state != HALMAC_CMD_CNSTR_CNSTR) {
|
|
PLTFM_MSG_ERR("[ERR]state(en = 1)\n");
|
|
return HALMAC_RET_ERROR_STATE;
|
|
}
|
|
} else {
|
|
if (state != HALMAC_CMD_CNSTR_BUF_CLR) {
|
|
PLTFM_MSG_ERR("[ERR]state(en = 0)\n");
|
|
return HALMAC_RET_ERROR_STATE;
|
|
}
|
|
}
|
|
|
|
status = proc_ctrl_ch_switch_88xx(adapter, opt);
|
|
if (status != HALMAC_RET_SUCCESS) {
|
|
PLTFM_MSG_ERR("[ERR]ctrl ch sw!!\n");
|
|
return status;
|
|
}
|
|
|
|
PLTFM_MSG_TRACE("[TRACE]%s <===\n", __func__);
|
|
|
|
return HALMAC_RET_SUCCESS;
|
|
}
|
|
|
|
static enum halmac_ret_status
|
|
proc_ctrl_ch_switch_88xx(struct halmac_adapter *adapter,
|
|
struct halmac_ch_switch_option *opt)
|
|
{
|
|
u8 h2c_buf[H2C_PKT_SIZE_88XX] = { 0 };
|
|
u16 seq_num = 0;
|
|
u16 pg_addr = adapter->txff_alloc.rsvd_h2c_info_addr;
|
|
struct halmac_h2c_header_info hdr_info;
|
|
struct halmac_scan_rpt_info *scan_rpt_info = &adapter->scan_rpt_info;
|
|
enum halmac_ret_status status = HALMAC_RET_SUCCESS;
|
|
enum halmac_cmd_process_status *proc_status;
|
|
|
|
proc_status = &adapter->halmac_state.scan_state.proc_status;
|
|
|
|
PLTFM_MSG_TRACE("[TRACE]%s ===>\n", __func__);
|
|
|
|
if (adapter->halmac_state.update_pkt_state.used_page > 0 &&
|
|
opt->nlo_en == 1 && adapter->nlo_flag != 1)
|
|
PLTFM_MSG_WARN("[WARN]probe req is NOT nlo pkt!!\n");
|
|
|
|
if (cnv_scan_state_88xx(adapter, HALMAC_CMD_CNSTR_H2C_SENT) !=
|
|
HALMAC_RET_SUCCESS)
|
|
return HALMAC_RET_ERROR_STATE;
|
|
|
|
*proc_status = HALMAC_CMD_PROCESS_SENDING;
|
|
|
|
if (opt->switch_en != 0) {
|
|
pg_addr += adapter->halmac_state.update_pkt_state.used_page;
|
|
status = dl_rsvd_page_88xx(adapter, pg_addr,
|
|
adapter->ch_sw_info.buf,
|
|
adapter->ch_sw_info.total_size);
|
|
if (status != HALMAC_RET_SUCCESS) {
|
|
PLTFM_MSG_ERR("[ERR]dl rsvd pg!!\n");
|
|
return status;
|
|
}
|
|
adapter->halmac_state.update_pkt_state.used_page = 0;
|
|
}
|
|
|
|
CH_SWITCH_SET_START(h2c_buf, opt->switch_en);
|
|
CH_SWITCH_SET_CH_NUM(h2c_buf, adapter->ch_sw_info.ch_num);
|
|
CH_SWITCH_SET_INFO_LOC(h2c_buf,
|
|
pg_addr - adapter->txff_alloc.rsvd_boundary);
|
|
CH_SWITCH_SET_DEST_CH_EN(h2c_buf, opt->dest_ch_en);
|
|
CH_SWITCH_SET_DEST_CH(h2c_buf, opt->dest_ch);
|
|
CH_SWITCH_SET_PRI_CH_IDX(h2c_buf, opt->dest_pri_ch_idx);
|
|
CH_SWITCH_SET_ABSOLUTE_TIME(h2c_buf, opt->absolute_time_en);
|
|
CH_SWITCH_SET_TSF_LOW(h2c_buf, opt->tsf_low);
|
|
CH_SWITCH_SET_PERIODIC_OPT(h2c_buf, opt->periodic_option);
|
|
CH_SWITCH_SET_NORMAL_CYCLE(h2c_buf, opt->normal_cycle);
|
|
CH_SWITCH_SET_NORMAL_PERIOD(h2c_buf, opt->normal_period);
|
|
CH_SWITCH_SET_SLOW_PERIOD(h2c_buf, opt->phase_2_period);
|
|
CH_SWITCH_SET_NORMAL_PERIOD_SEL(h2c_buf, opt->normal_period_sel);
|
|
CH_SWITCH_SET_SLOW_PERIOD_SEL(h2c_buf, opt->phase_2_period_sel);
|
|
CH_SWITCH_SET_SCAN_MODE(h2c_buf, opt->scan_mode_en);
|
|
CH_SWITCH_SET_INFO_SIZE(h2c_buf, adapter->ch_sw_info.total_size);
|
|
|
|
hdr_info.sub_cmd_id = SUB_CMD_ID_CH_SWITCH;
|
|
hdr_info.content_size = 20;
|
|
if (opt->nlo_en == 1)
|
|
hdr_info.ack = 0;
|
|
else
|
|
hdr_info.ack = 1;
|
|
|
|
if (opt->scan_mode_en == 1) {
|
|
adapter->ch_sw_info.scan_mode = 1;
|
|
if (!scan_rpt_info->buf) {
|
|
scan_rpt_info->buf =
|
|
(u8 *)PLTFM_MALLOC(SCAN_INFO_RSVDPG_SIZE);
|
|
if (!scan_rpt_info->buf)
|
|
return HALMAC_RET_NULL_POINTER;
|
|
} else {
|
|
PLTFM_MEMSET(scan_rpt_info->buf, 0,
|
|
SCAN_INFO_RSVDPG_SIZE);
|
|
}
|
|
scan_rpt_info->buf_wptr = scan_rpt_info->buf;
|
|
scan_rpt_info->buf_size = SCAN_INFO_RSVDPG_SIZE;
|
|
scan_rpt_info->avl_buf_size = SCAN_INFO_RSVDPG_SIZE;
|
|
scan_rpt_info->total_size = 0;
|
|
scan_rpt_info->ack_tsf_high = 0;
|
|
scan_rpt_info->ack_tsf_low = 0;
|
|
scan_rpt_info->rpt_tsf_high = 0;
|
|
scan_rpt_info->rpt_tsf_low = 0;
|
|
} else {
|
|
adapter->ch_sw_info.scan_mode = 0;
|
|
if (!scan_rpt_info->buf)
|
|
PLTFM_FREE(scan_rpt_info->buf, scan_rpt_info->buf_size);
|
|
scan_rpt_info->buf_wptr = NULL;
|
|
scan_rpt_info->buf_size = 0;
|
|
scan_rpt_info->avl_buf_size = 0;
|
|
scan_rpt_info->total_size = 0;
|
|
}
|
|
|
|
set_h2c_pkt_hdr_88xx(adapter, h2c_buf, &hdr_info, &seq_num);
|
|
adapter->halmac_state.scan_state.seq_num = seq_num;
|
|
|
|
status = send_h2c_pkt_88xx(adapter, h2c_buf);
|
|
|
|
if (status != HALMAC_RET_SUCCESS) {
|
|
PLTFM_MSG_ERR("[ERR]send h2c!!\n");
|
|
reset_ofld_feature_88xx(adapter, HALMAC_FEATURE_CHANNEL_SWITCH);
|
|
}
|
|
PLTFM_FREE(adapter->ch_sw_info.buf, adapter->ch_sw_info.buf_size);
|
|
adapter->ch_sw_info.buf = NULL;
|
|
adapter->ch_sw_info.buf_wptr = NULL;
|
|
adapter->ch_sw_info.extra_info_en = 0;
|
|
adapter->ch_sw_info.buf_size = 0;
|
|
adapter->ch_sw_info.avl_buf_size = 0;
|
|
adapter->ch_sw_info.total_size = 0;
|
|
adapter->ch_sw_info.ch_num = 0;
|
|
|
|
if (cnv_scan_state_88xx(adapter, HALMAC_CMD_CNSTR_IDLE) !=
|
|
HALMAC_RET_SUCCESS)
|
|
return HALMAC_RET_ERROR_STATE;
|
|
|
|
adapter->nlo_flag = 0;
|
|
|
|
return status;
|
|
}
|
|
|
|
/**
|
|
* clear_ch_info_88xx() -clear channel information
|
|
* @adapter : the adapter of halmac
|
|
* Author : KaiYuan Chang/Ivan Lin
|
|
* Return : enum halmac_ret_status
|
|
* More details of status code can be found in prototype document
|
|
*/
|
|
enum halmac_ret_status
|
|
clear_ch_info_88xx(struct halmac_adapter *adapter)
|
|
{
|
|
PLTFM_MSG_TRACE("[TRACE]%s ===>\n", __func__);
|
|
|
|
if (scan_cmd_cnstr_state_88xx(adapter) == HALMAC_CMD_CNSTR_H2C_SENT) {
|
|
PLTFM_MSG_WARN("[WARN]state(clear)\n");
|
|
return HALMAC_RET_ERROR_STATE;
|
|
}
|
|
|
|
if (cnv_scan_state_88xx(adapter, HALMAC_CMD_CNSTR_BUF_CLR) !=
|
|
HALMAC_RET_SUCCESS)
|
|
return HALMAC_RET_ERROR_STATE;
|
|
|
|
PLTFM_FREE(adapter->ch_sw_info.buf, adapter->ch_sw_info.buf_size);
|
|
adapter->ch_sw_info.buf = NULL;
|
|
adapter->ch_sw_info.buf_wptr = NULL;
|
|
adapter->ch_sw_info.extra_info_en = 0;
|
|
adapter->ch_sw_info.buf_size = 0;
|
|
adapter->ch_sw_info.avl_buf_size = 0;
|
|
adapter->ch_sw_info.total_size = 0;
|
|
adapter->ch_sw_info.ch_num = 0;
|
|
|
|
PLTFM_MSG_TRACE("[TRACE]%s <===\n", __func__);
|
|
|
|
return HALMAC_RET_SUCCESS;
|
|
}
|
|
|
|
/**
|
|
* chk_txdesc_88xx() -check if the tx packet format is incorrect
|
|
* @adapter : the adapter of halmac
|
|
* @buf : tx Packet buffer, tx desc is included
|
|
* @size : tx packet size
|
|
* Author : KaiYuan Chang
|
|
* Return : enum halmac_ret_status
|
|
* More details of status code can be found in prototype document
|
|
*/
|
|
enum halmac_ret_status
|
|
chk_txdesc_88xx(struct halmac_adapter *adapter, u8 *buf, u32 size)
|
|
{
|
|
u32 mac_clk = 0;
|
|
u8 value8;
|
|
enum halmac_ret_status status = HALMAC_RET_SUCCESS;
|
|
struct halmac_api *api = (struct halmac_api *)adapter->halmac_api;
|
|
|
|
PLTFM_MSG_TRACE("[TRACE]%s ===>\n", __func__);
|
|
|
|
if (GET_TX_DESC_BMC(buf) == 1 && GET_TX_DESC_AGG_EN(buf) == 1)
|
|
PLTFM_MSG_ERR("[ERR]txdesc - agg + bmc\n");
|
|
|
|
if (size < (GET_TX_DESC_TXPKTSIZE(buf) +
|
|
adapter->hw_cfg_info.txdesc_size +
|
|
(GET_TX_DESC_PKT_OFFSET(buf) << 3))) {
|
|
PLTFM_MSG_ERR("[ERR]txdesc - total size\n");
|
|
status = HALMAC_RET_TXDESC_SET_FAIL;
|
|
}
|
|
|
|
if (wlhdr_valid_88xx(adapter, buf) != HALMAC_RET_SUCCESS) {
|
|
PLTFM_MSG_ERR("[ERR]wlhdr\n");
|
|
status = HALMAC_RET_WLHDR_FAIL;
|
|
}
|
|
|
|
if (GET_TX_DESC_AMSDU_PAD_EN(buf) != 0) {
|
|
PLTFM_MSG_ERR("[ERR]txdesc - amsdu_pad\n");
|
|
status = HALMAC_RET_TXDESC_SET_FAIL;
|
|
}
|
|
|
|
if (GET_TX_DESC_USE_MAX_TIME_EN(buf) == 1) {
|
|
value8 = (u8)GET_TX_DESC_AMPDU_MAX_TIME(buf);
|
|
if (value8 > HALMAC_REG_R8(REG_AMPDU_MAX_TIME_V1)) {
|
|
PLTFM_MSG_ERR("[ERR]txdesc - ampdu_max_time\n");
|
|
status = HALMAC_RET_TXDESC_SET_FAIL;
|
|
}
|
|
}
|
|
|
|
switch (BIT_GET_MAC_CLK_SEL(HALMAC_REG_R32(REG_AFE_CTRL1))) {
|
|
case 0x0:
|
|
mac_clk = 80;
|
|
break;
|
|
case 0x1:
|
|
mac_clk = 40;
|
|
break;
|
|
case 0x2:
|
|
mac_clk = 20;
|
|
break;
|
|
case 0x3:
|
|
mac_clk = 10;
|
|
break;
|
|
}
|
|
|
|
PLTFM_MSG_ALWAYS("MAC clock : 0x%XM\n", mac_clk);
|
|
PLTFM_MSG_ALWAYS("mac agg en : 0x%X\n", GET_TX_DESC_AGG_EN(buf));
|
|
PLTFM_MSG_ALWAYS("mac agg num : 0x%X\n", GET_TX_DESC_MAX_AGG_NUM(buf));
|
|
|
|
PLTFM_MSG_TRACE("[TRACE]%s <===\n", __func__);
|
|
|
|
return status;
|
|
}
|
|
|
|
static enum halmac_ret_status
|
|
wlhdr_valid_88xx(struct halmac_adapter *adapter, u8 *buf)
|
|
{
|
|
u32 txdesc_size = adapter->hw_cfg_info.txdesc_size +
|
|
GET_TX_DESC_PKT_OFFSET(buf);
|
|
enum halmac_ret_status status = HALMAC_RET_SUCCESS;
|
|
struct wlhdr_frame_ctrl *wlhdr;
|
|
|
|
wlhdr = (struct wlhdr_frame_ctrl *)(buf + txdesc_size);
|
|
|
|
if (wlhdr->protocol != WLHDR_PROT_VER) {
|
|
PLTFM_MSG_ERR("[ERR]prot ver!!\n");
|
|
return HALMAC_RET_WLHDR_FAIL;
|
|
}
|
|
|
|
switch (wlhdr->type) {
|
|
case WLHDR_TYPE_MGMT:
|
|
if (wlhdr_mgmt_valid_88xx(adapter, wlhdr) != 1)
|
|
status = HALMAC_RET_WLHDR_FAIL;
|
|
break;
|
|
case WLHDR_TYPE_CTRL:
|
|
if (wlhdr_ctrl_valid_88xx(adapter, wlhdr) != 1)
|
|
status = HALMAC_RET_WLHDR_FAIL;
|
|
break;
|
|
case WLHDR_TYPE_DATA:
|
|
if (wlhdr_data_valid_88xx(adapter, wlhdr) != 1)
|
|
status = HALMAC_RET_WLHDR_FAIL;
|
|
break;
|
|
default:
|
|
PLTFM_MSG_ERR("[ERR]undefined type!!\n");
|
|
status = HALMAC_RET_WLHDR_FAIL;
|
|
break;
|
|
}
|
|
|
|
return status;
|
|
}
|
|
|
|
static u8
|
|
wlhdr_mgmt_valid_88xx(struct halmac_adapter *adapter,
|
|
struct wlhdr_frame_ctrl *wlhdr)
|
|
{
|
|
u8 state;
|
|
|
|
switch (wlhdr->sub_type) {
|
|
case WLHDR_SUB_TYPE_ASSOC_REQ:
|
|
case WLHDR_SUB_TYPE_ASSOC_RSPNS:
|
|
case WLHDR_SUB_TYPE_REASSOC_REQ:
|
|
case WLHDR_SUB_TYPE_REASSOC_RSPNS:
|
|
case WLHDR_SUB_TYPE_PROBE_REQ:
|
|
case WLHDR_SUB_TYPE_PROBE_RSPNS:
|
|
case WLHDR_SUB_TYPE_BCN:
|
|
case WLHDR_SUB_TYPE_DISASSOC:
|
|
case WLHDR_SUB_TYPE_AUTH:
|
|
case WLHDR_SUB_TYPE_DEAUTH:
|
|
case WLHDR_SUB_TYPE_ACTION:
|
|
case WLHDR_SUB_TYPE_ACTION_NOACK:
|
|
state = 1;
|
|
break;
|
|
default:
|
|
PLTFM_MSG_ERR("[ERR]mgmt invalid!!\n");
|
|
state = 0;
|
|
break;
|
|
}
|
|
|
|
return state;
|
|
}
|
|
|
|
static u8
|
|
wlhdr_ctrl_valid_88xx(struct halmac_adapter *adapter,
|
|
struct wlhdr_frame_ctrl *wlhdr)
|
|
{
|
|
u8 state;
|
|
|
|
switch (wlhdr->sub_type) {
|
|
case WLHDR_SUB_TYPE_BF_RPT_POLL:
|
|
case WLHDR_SUB_TYPE_NDPA:
|
|
state = 1;
|
|
break;
|
|
default:
|
|
PLTFM_MSG_ERR("[ERR]ctrl invalid!!\n");
|
|
state = 0;
|
|
break;
|
|
}
|
|
|
|
return state;
|
|
}
|
|
|
|
static u8
|
|
wlhdr_data_valid_88xx(struct halmac_adapter *adapter,
|
|
struct wlhdr_frame_ctrl *wlhdr)
|
|
{
|
|
u8 state;
|
|
|
|
switch (wlhdr->sub_type) {
|
|
case WLHDR_SUB_TYPE_DATA:
|
|
case WLHDR_SUB_TYPE_NULL:
|
|
case WLHDR_SUB_TYPE_QOS_DATA:
|
|
case WLHDR_SUB_TYPE_QOS_NULL:
|
|
state = 1;
|
|
break;
|
|
default:
|
|
PLTFM_MSG_ERR("[ERR]data invalid!!\n");
|
|
state = 0;
|
|
break;
|
|
}
|
|
|
|
return state;
|
|
}
|
|
|
|
/**
|
|
* get_version_88xx() - get HALMAC version
|
|
* @ver : return version of major, prototype and minor information
|
|
* Author : KaiYuan Chang / Ivan Lin
|
|
* Return : enum halmac_ret_status
|
|
* More details of status code can be found in prototype document
|
|
*/
|
|
enum halmac_ret_status
|
|
get_version_88xx(struct halmac_adapter *adapter, struct halmac_ver *ver)
|
|
{
|
|
PLTFM_MSG_TRACE("[TRACE]%s ===>\n", __func__);
|
|
|
|
ver->major_ver = (u8)HALMAC_MAJOR_VER;
|
|
ver->prototype_ver = (u8)HALMAC_PROTOTYPE_VER;
|
|
ver->minor_ver = (u8)HALMAC_MINOR_VER;
|
|
|
|
PLTFM_MSG_TRACE("[TRACE]%s <===\n", __func__);
|
|
|
|
return HALMAC_RET_SUCCESS;
|
|
}
|
|
|
|
enum halmac_ret_status
|
|
p2pps_88xx(struct halmac_adapter *adapter, struct halmac_p2pps *info)
|
|
{
|
|
enum halmac_ret_status status = HALMAC_RET_SUCCESS;
|
|
|
|
if (halmac_fw_validate(adapter) != HALMAC_RET_SUCCESS)
|
|
return HALMAC_RET_NO_DLFW;
|
|
|
|
if (adapter->fw_ver.h2c_version < 6)
|
|
return HALMAC_RET_FW_NO_SUPPORT;
|
|
|
|
status = proc_p2pps_88xx(adapter, info);
|
|
if (status != HALMAC_RET_SUCCESS) {
|
|
PLTFM_MSG_ERR("[ERR]p2pps!!\n");
|
|
return status;
|
|
}
|
|
|
|
return HALMAC_RET_SUCCESS;
|
|
}
|
|
|
|
static enum halmac_ret_status
|
|
proc_p2pps_88xx(struct halmac_adapter *adapter, struct halmac_p2pps *info)
|
|
{
|
|
u8 h2c_buf[H2C_PKT_SIZE_88XX] = { 0 };
|
|
u16 seq_num = 0;
|
|
struct halmac_h2c_header_info hdr_info;
|
|
enum halmac_ret_status status = HALMAC_RET_SUCCESS;
|
|
|
|
P2PPS_SET_OFFLOAD_EN(h2c_buf, info->offload_en);
|
|
P2PPS_SET_ROLE(h2c_buf, info->role);
|
|
P2PPS_SET_CTWINDOW_EN(h2c_buf, info->ctwindow_en);
|
|
P2PPS_SET_NOA_EN(h2c_buf, info->noa_en);
|
|
P2PPS_SET_NOA_SEL(h2c_buf, info->noa_sel);
|
|
P2PPS_SET_ALLSTASLEEP(h2c_buf, info->all_sta_sleep);
|
|
P2PPS_SET_DISCOVERY(h2c_buf, info->discovery);
|
|
P2PPS_SET_DISABLE_CLOSERF(h2c_buf, info->disable_close_rf);
|
|
P2PPS_SET_P2P_PORT_ID(h2c_buf, info->p2p_port_id);
|
|
P2PPS_SET_P2P_GROUP(h2c_buf, info->p2p_group);
|
|
P2PPS_SET_P2P_MACID(h2c_buf, info->p2p_macid);
|
|
|
|
P2PPS_SET_CTWINDOW_LENGTH(h2c_buf, info->ctwindow_length);
|
|
|
|
P2PPS_SET_NOA_DURATION_PARA(h2c_buf, info->noa_duration_para);
|
|
P2PPS_SET_NOA_INTERVAL_PARA(h2c_buf, info->noa_interval_para);
|
|
P2PPS_SET_NOA_START_TIME_PARA(h2c_buf, info->noa_start_time_para);
|
|
P2PPS_SET_NOA_COUNT_PARA(h2c_buf, info->noa_count_para);
|
|
|
|
hdr_info.sub_cmd_id = SUB_CMD_ID_P2PPS;
|
|
hdr_info.content_size = 24;
|
|
hdr_info.ack = 0;
|
|
set_h2c_pkt_hdr_88xx(adapter, h2c_buf, &hdr_info, &seq_num);
|
|
|
|
status = send_h2c_pkt_88xx(adapter, h2c_buf);
|
|
|
|
if (status != HALMAC_RET_SUCCESS)
|
|
PLTFM_MSG_ERR("[ERR]send h2c!!\n");
|
|
|
|
return status;
|
|
}
|
|
|
|
/**
|
|
* query_status_88xx() -query the offload feature status
|
|
* @adapter : the adapter of halmac
|
|
* @feature_id : feature_id
|
|
* @proc_status : feature_status
|
|
* @data : data buffer
|
|
* @size : data size
|
|
*
|
|
* Note :
|
|
* If user wants to know the data size, user can allocate zero
|
|
* size buffer first. If this size less than the data size, halmac
|
|
* will return HALMAC_RET_BUFFER_TOO_SMALL. User need to
|
|
* re-allocate data buffer with correct data size.
|
|
*
|
|
* Author : Ivan Lin/KaiYuan Chang
|
|
* Return : enum halmac_ret_status
|
|
* More details of status code can be found in prototype document
|
|
*/
|
|
enum halmac_ret_status
|
|
query_status_88xx(struct halmac_adapter *adapter,
|
|
enum halmac_feature_id feature_id,
|
|
enum halmac_cmd_process_status *proc_status, u8 *data,
|
|
u32 *size)
|
|
{
|
|
enum halmac_ret_status status = HALMAC_RET_SUCCESS;
|
|
|
|
if (!proc_status)
|
|
return HALMAC_RET_NULL_POINTER;
|
|
|
|
switch (feature_id) {
|
|
case HALMAC_FEATURE_CFG_PARA:
|
|
status = get_cfg_param_status_88xx(adapter, proc_status);
|
|
break;
|
|
case HALMAC_FEATURE_DUMP_PHYSICAL_EFUSE:
|
|
status = get_dump_phy_efuse_status_88xx(adapter, proc_status,
|
|
data, size);
|
|
break;
|
|
case HALMAC_FEATURE_DUMP_LOGICAL_EFUSE:
|
|
status = get_dump_log_efuse_status_88xx(adapter, proc_status,
|
|
data, size);
|
|
break;
|
|
case HALMAC_FEATURE_DUMP_LOGICAL_EFUSE_MASK:
|
|
status = get_dump_log_efuse_mask_status_88xx(adapter,
|
|
proc_status,
|
|
data, size);
|
|
break;
|
|
case HALMAC_FEATURE_CHANNEL_SWITCH:
|
|
status = get_ch_switch_status_88xx(adapter, proc_status);
|
|
break;
|
|
case HALMAC_FEATURE_UPDATE_PACKET:
|
|
status = get_update_packet_status_88xx(adapter, proc_status);
|
|
break;
|
|
case HALMAC_FEATURE_SEND_SCAN_PACKET:
|
|
status = get_send_scan_packet_status_88xx(adapter, proc_status);
|
|
break;
|
|
case HALMAC_FEATURE_DROP_SCAN_PACKET:
|
|
status = get_drop_scan_packet_status_88xx(adapter, proc_status);
|
|
break;
|
|
case HALMAC_FEATURE_IQK:
|
|
status = get_iqk_status_88xx(adapter, proc_status);
|
|
break;
|
|
case HALMAC_FEATURE_POWER_TRACKING:
|
|
status = get_pwr_trk_status_88xx(adapter, proc_status);
|
|
break;
|
|
case HALMAC_FEATURE_PSD:
|
|
status = get_psd_status_88xx(adapter, proc_status, data, size);
|
|
break;
|
|
case HALMAC_FEATURE_FW_SNDING:
|
|
status = get_fw_snding_status_88xx(adapter, proc_status);
|
|
break;
|
|
case HALMAC_FEATURE_DPK:
|
|
status = get_dpk_status_88xx(adapter, proc_status, data, size);
|
|
break;
|
|
default:
|
|
return HALMAC_RET_INVALID_FEATURE_ID;
|
|
}
|
|
|
|
return status;
|
|
}
|
|
|
|
static enum halmac_ret_status
|
|
get_cfg_param_status_88xx(struct halmac_adapter *adapter,
|
|
enum halmac_cmd_process_status *proc_status)
|
|
{
|
|
*proc_status = adapter->halmac_state.cfg_param_state.proc_status;
|
|
|
|
return HALMAC_RET_SUCCESS;
|
|
}
|
|
|
|
static enum halmac_ret_status
|
|
get_ch_switch_status_88xx(struct halmac_adapter *adapter,
|
|
enum halmac_cmd_process_status *proc_status)
|
|
{
|
|
*proc_status = adapter->halmac_state.scan_state.proc_status;
|
|
|
|
return HALMAC_RET_SUCCESS;
|
|
}
|
|
|
|
static enum halmac_ret_status
|
|
get_update_packet_status_88xx(struct halmac_adapter *adapter,
|
|
enum halmac_cmd_process_status *proc_status)
|
|
{
|
|
*proc_status = adapter->halmac_state.update_pkt_state.proc_status;
|
|
|
|
return HALMAC_RET_SUCCESS;
|
|
}
|
|
|
|
static enum halmac_ret_status
|
|
get_send_scan_packet_status_88xx(struct halmac_adapter *adapter,
|
|
enum halmac_cmd_process_status *proc_status)
|
|
{
|
|
*proc_status = adapter->halmac_state.scan_pkt_state.proc_status;
|
|
|
|
return HALMAC_RET_SUCCESS;
|
|
}
|
|
|
|
static enum halmac_ret_status
|
|
get_drop_scan_packet_status_88xx(struct halmac_adapter *adapter,
|
|
enum halmac_cmd_process_status *proc_status)
|
|
{
|
|
*proc_status = adapter->halmac_state.drop_pkt_state.proc_status;
|
|
|
|
return HALMAC_RET_SUCCESS;
|
|
}
|
|
|
|
/**
|
|
* cfg_drv_rsvd_pg_num_88xx() -config reserved page number for driver
|
|
* @adapter : the adapter of halmac
|
|
* @pg_num : page number
|
|
* Author : KaiYuan Chang
|
|
* Return : enum halmac_ret_status
|
|
* More details of status code can be found in prototype document
|
|
*/
|
|
enum halmac_ret_status
|
|
cfg_drv_rsvd_pg_num_88xx(struct halmac_adapter *adapter,
|
|
enum halmac_drv_rsvd_pg_num pg_num)
|
|
{
|
|
if (adapter->api_registry.cfg_drv_rsvd_pg_en == 0)
|
|
return HALMAC_RET_NOT_SUPPORT;
|
|
|
|
PLTFM_MSG_TRACE("[TRACE]%s ===>\n", __func__);
|
|
PLTFM_MSG_TRACE("[TRACE]pg_num = %d\n", pg_num);
|
|
|
|
switch (pg_num) {
|
|
case HALMAC_RSVD_PG_NUM8:
|
|
adapter->txff_alloc.rsvd_drv_pg_num = 8;
|
|
break;
|
|
case HALMAC_RSVD_PG_NUM16:
|
|
adapter->txff_alloc.rsvd_drv_pg_num = 16;
|
|
break;
|
|
case HALMAC_RSVD_PG_NUM24:
|
|
adapter->txff_alloc.rsvd_drv_pg_num = 24;
|
|
break;
|
|
case HALMAC_RSVD_PG_NUM32:
|
|
adapter->txff_alloc.rsvd_drv_pg_num = 32;
|
|
break;
|
|
case HALMAC_RSVD_PG_NUM64:
|
|
adapter->txff_alloc.rsvd_drv_pg_num = 64;
|
|
break;
|
|
case HALMAC_RSVD_PG_NUM128:
|
|
adapter->txff_alloc.rsvd_drv_pg_num = 128;
|
|
break;
|
|
case HALMAC_RSVD_PG_NUM256:
|
|
adapter->txff_alloc.rsvd_drv_pg_num = 256;
|
|
break;
|
|
}
|
|
|
|
PLTFM_MSG_TRACE("[TRACE]%s <===\n", __func__);
|
|
|
|
return HALMAC_RET_SUCCESS;
|
|
}
|
|
|
|
/**
|
|
* (debug API)h2c_lb_88xx() - send h2c loopback packet
|
|
* @adapter : the adapter of halmac
|
|
* Author : KaiYuan Chang/Ivan Lin
|
|
* Return : enum halmac_ret_status
|
|
* More details of status code can be found in prototype document
|
|
*/
|
|
enum halmac_ret_status
|
|
h2c_lb_88xx(struct halmac_adapter *adapter)
|
|
{
|
|
return HALMAC_RET_SUCCESS;
|
|
}
|
|
|
|
enum halmac_ret_status
|
|
pwr_seq_parser_88xx(struct halmac_adapter *adapter,
|
|
struct halmac_wlan_pwr_cfg **cmd_seq)
|
|
{
|
|
u8 cut;
|
|
u8 intf;
|
|
u32 idx = 0;
|
|
enum halmac_ret_status status = HALMAC_RET_SUCCESS;
|
|
struct halmac_wlan_pwr_cfg *cmd;
|
|
|
|
switch (adapter->chip_ver) {
|
|
case HALMAC_CHIP_VER_A_CUT:
|
|
cut = HALMAC_PWR_CUT_A_MSK;
|
|
break;
|
|
case HALMAC_CHIP_VER_B_CUT:
|
|
cut = HALMAC_PWR_CUT_B_MSK;
|
|
break;
|
|
case HALMAC_CHIP_VER_C_CUT:
|
|
cut = HALMAC_PWR_CUT_C_MSK;
|
|
break;
|
|
case HALMAC_CHIP_VER_D_CUT:
|
|
cut = HALMAC_PWR_CUT_D_MSK;
|
|
break;
|
|
case HALMAC_CHIP_VER_E_CUT:
|
|
cut = HALMAC_PWR_CUT_E_MSK;
|
|
break;
|
|
case HALMAC_CHIP_VER_F_CUT:
|
|
cut = HALMAC_PWR_CUT_F_MSK;
|
|
break;
|
|
case HALMAC_CHIP_VER_TEST:
|
|
cut = HALMAC_PWR_CUT_TESTCHIP_MSK;
|
|
break;
|
|
default:
|
|
PLTFM_MSG_ERR("[ERR]chip info!!\n");
|
|
return HALMAC_RET_SWITCH_CASE_ERROR;
|
|
}
|
|
|
|
switch (adapter->intf) {
|
|
case HALMAC_INTERFACE_PCIE:
|
|
case HALMAC_INTERFACE_AXI:
|
|
intf = HALMAC_PWR_INTF_PCI_MSK;
|
|
break;
|
|
case HALMAC_INTERFACE_USB:
|
|
intf = HALMAC_PWR_INTF_USB_MSK;
|
|
break;
|
|
case HALMAC_INTERFACE_SDIO:
|
|
intf = HALMAC_PWR_INTF_SDIO_MSK;
|
|
break;
|
|
default:
|
|
PLTFM_MSG_ERR("[ERR]interface!!\n");
|
|
return HALMAC_RET_SWITCH_CASE_ERROR;
|
|
}
|
|
|
|
do {
|
|
cmd = cmd_seq[idx];
|
|
|
|
if (!cmd)
|
|
break;
|
|
|
|
status = pwr_sub_seq_parser_88xx(adapter, cut, intf, cmd);
|
|
if (status != HALMAC_RET_SUCCESS) {
|
|
PLTFM_MSG_ERR("[ERR]pwr sub seq!!\n");
|
|
return status;
|
|
}
|
|
|
|
idx++;
|
|
} while (1);
|
|
|
|
return status;
|
|
}
|
|
|
|
static enum halmac_ret_status
|
|
pwr_sub_seq_parser_88xx(struct halmac_adapter *adapter, u8 cut, u8 intf,
|
|
struct halmac_wlan_pwr_cfg *cmd)
|
|
{
|
|
u8 value;
|
|
u32 offset;
|
|
struct halmac_api *api = (struct halmac_api *)adapter->halmac_api;
|
|
|
|
do {
|
|
if ((cmd->interface_msk & intf) && (cmd->cut_msk & cut)) {
|
|
switch (cmd->cmd) {
|
|
case HALMAC_PWR_CMD_WRITE:
|
|
offset = cmd->offset;
|
|
|
|
if (cmd->base == HALMAC_PWR_ADDR_SDIO)
|
|
offset |= SDIO_LOCAL_OFFSET;
|
|
|
|
value = HALMAC_REG_R8(offset);
|
|
value = (u8)(value & (u8)(~(cmd->msk)));
|
|
value = (u8)(value | (cmd->value & cmd->msk));
|
|
|
|
HALMAC_REG_W8(offset, value);
|
|
break;
|
|
case HALMAC_PWR_CMD_POLLING:
|
|
if (pwr_cmd_polling_88xx(adapter, cmd) !=
|
|
HALMAC_RET_SUCCESS)
|
|
return HALMAC_RET_PWRSEQ_POLLING_FAIL;
|
|
break;
|
|
case HALMAC_PWR_CMD_DELAY:
|
|
if (cmd->value == HALMAC_PWR_DELAY_US)
|
|
PLTFM_DELAY_US(cmd->offset);
|
|
else
|
|
PLTFM_DELAY_US(1000 * cmd->offset);
|
|
break;
|
|
case HALMAC_PWR_CMD_READ:
|
|
break;
|
|
case HALMAC_PWR_CMD_END:
|
|
return HALMAC_RET_SUCCESS;
|
|
default:
|
|
return HALMAC_RET_PWRSEQ_CMD_INCORRECT;
|
|
}
|
|
}
|
|
cmd++;
|
|
} while (1);
|
|
|
|
return HALMAC_RET_SUCCESS;
|
|
}
|
|
|
|
static enum halmac_ret_status
|
|
pwr_cmd_polling_88xx(struct halmac_adapter *adapter,
|
|
struct halmac_wlan_pwr_cfg *cmd)
|
|
{
|
|
u8 value;
|
|
u8 flg;
|
|
u8 poll_bit;
|
|
u32 offset;
|
|
u32 cnt;
|
|
static u32 stats;
|
|
enum halmac_interface intf;
|
|
struct halmac_api *api = (struct halmac_api *)adapter->halmac_api;
|
|
|
|
poll_bit = 0;
|
|
cnt = HALMAC_PWR_POLLING_CNT;
|
|
flg = 0;
|
|
intf = adapter->intf;
|
|
|
|
if (cmd->base == HALMAC_PWR_ADDR_SDIO)
|
|
offset = cmd->offset | SDIO_LOCAL_OFFSET;
|
|
else
|
|
offset = cmd->offset;
|
|
|
|
do {
|
|
cnt--;
|
|
value = HALMAC_REG_R8(offset);
|
|
value = (u8)(value & cmd->msk);
|
|
|
|
if (value == (cmd->value & cmd->msk)) {
|
|
poll_bit = 1;
|
|
} else {
|
|
if (cnt == 0) {
|
|
if (intf == HALMAC_INTERFACE_PCIE && flg == 0) {
|
|
/* PCIE + USB package */
|
|
/* power bit polling timeout issue */
|
|
stats++;
|
|
PLTFM_MSG_WARN("[WARN]PCIE stats:%d\n",
|
|
stats);
|
|
value = HALMAC_REG_R8(REG_SYS_PW_CTRL);
|
|
value |= BIT(3);
|
|
HALMAC_REG_W8(REG_SYS_PW_CTRL, value);
|
|
value &= ~BIT(3);
|
|
HALMAC_REG_W8(REG_SYS_PW_CTRL, value);
|
|
poll_bit = 0;
|
|
cnt = HALMAC_PWR_POLLING_CNT;
|
|
flg = 1;
|
|
} else {
|
|
PLTFM_MSG_ERR("[ERR]polling to!!\n");
|
|
PLTFM_MSG_ERR("[ERR]cmd offset:%X\n",
|
|
cmd->offset);
|
|
PLTFM_MSG_ERR("[ERR]cmd value:%X\n",
|
|
cmd->value);
|
|
PLTFM_MSG_ERR("[ERR]cmd msk:%X\n",
|
|
cmd->msk);
|
|
PLTFM_MSG_ERR("[ERR]offset = %X\n",
|
|
offset);
|
|
PLTFM_MSG_ERR("[ERR]value = %X\n",
|
|
value);
|
|
return HALMAC_RET_PWRSEQ_POLLING_FAIL;
|
|
}
|
|
} else {
|
|
PLTFM_DELAY_US(50);
|
|
}
|
|
}
|
|
} while (!poll_bit);
|
|
|
|
return HALMAC_RET_SUCCESS;
|
|
}
|
|
|
|
enum halmac_ret_status
|
|
parse_intf_phy_88xx(struct halmac_adapter *adapter,
|
|
struct halmac_intf_phy_para *param,
|
|
enum halmac_intf_phy_platform pltfm,
|
|
enum hal_intf_phy intf_phy)
|
|
{
|
|
u16 value;
|
|
u16 cur_cut;
|
|
u16 offset;
|
|
u16 ip_sel;
|
|
struct halmac_intf_phy_para *cur_param;
|
|
struct halmac_api *api = (struct halmac_api *)adapter->halmac_api;
|
|
enum halmac_ret_status result = HALMAC_RET_SUCCESS;
|
|
|
|
switch (adapter->chip_ver) {
|
|
case HALMAC_CHIP_VER_A_CUT:
|
|
cur_cut = (u16)HALMAC_INTF_PHY_CUT_A;
|
|
break;
|
|
case HALMAC_CHIP_VER_B_CUT:
|
|
cur_cut = (u16)HALMAC_INTF_PHY_CUT_B;
|
|
break;
|
|
case HALMAC_CHIP_VER_C_CUT:
|
|
cur_cut = (u16)HALMAC_INTF_PHY_CUT_C;
|
|
break;
|
|
case HALMAC_CHIP_VER_D_CUT:
|
|
cur_cut = (u16)HALMAC_INTF_PHY_CUT_D;
|
|
break;
|
|
case HALMAC_CHIP_VER_E_CUT:
|
|
cur_cut = (u16)HALMAC_INTF_PHY_CUT_E;
|
|
break;
|
|
case HALMAC_CHIP_VER_F_CUT:
|
|
cur_cut = (u16)HALMAC_INTF_PHY_CUT_F;
|
|
break;
|
|
case HALMAC_CHIP_VER_TEST:
|
|
cur_cut = (u16)HALMAC_INTF_PHY_CUT_TESTCHIP;
|
|
break;
|
|
default:
|
|
return HALMAC_RET_FAIL;
|
|
}
|
|
|
|
cur_param = param;
|
|
|
|
do {
|
|
if ((cur_param->cut & cur_cut) &&
|
|
(cur_param->plaform & (u16)pltfm)) {
|
|
offset = cur_param->offset;
|
|
value = cur_param->value;
|
|
ip_sel = cur_param->ip_sel;
|
|
|
|
if (offset == 0xFFFF)
|
|
break;
|
|
|
|
if (ip_sel == HALMAC_IP_SEL_MAC) {
|
|
HALMAC_REG_W8((u32)offset, (u8)value);
|
|
} else if (intf_phy == HAL_INTF_PHY_USB2 ||
|
|
intf_phy == HAL_INTF_PHY_USB3) {
|
|
#if HALMAC_USB_SUPPORT
|
|
if (offset > 0x100)
|
|
usb_page_switch_88xx(adapter,
|
|
intf_phy,
|
|
1);
|
|
else
|
|
usb_page_switch_88xx(adapter,
|
|
intf_phy,
|
|
0);
|
|
offset = offset & 0xFF;
|
|
result = usbphy_write_88xx(adapter, (u8)offset,
|
|
value, intf_phy);
|
|
if (result != HALMAC_RET_SUCCESS)
|
|
PLTFM_MSG_ERR("[ERR]usb phy!!\n");
|
|
#endif
|
|
} else if (intf_phy == HAL_INTF_PHY_PCIE_GEN1 ||
|
|
intf_phy == HAL_INTF_PHY_PCIE_GEN2) {
|
|
#if HALMAC_PCIE_SUPPORT
|
|
if (ip_sel == HALMAC_IP_INTF_PHY)
|
|
result = mdio_write_88xx(adapter,
|
|
(u8)offset,
|
|
value,
|
|
intf_phy);
|
|
else
|
|
result = dbi_w8_88xx(adapter, offset,
|
|
(u8)value);
|
|
if (result != HALMAC_RET_SUCCESS)
|
|
PLTFM_MSG_ERR("[ERR]mdio/dbi!!\n");
|
|
#endif
|
|
} else {
|
|
PLTFM_MSG_ERR("[ERR]intf phy sel!!\n");
|
|
}
|
|
}
|
|
cur_param++;
|
|
} while (1);
|
|
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* txfifo_is_empty_88xx() -check if txfifo is empty
|
|
* @adapter : the adapter of halmac
|
|
* @chk_num : check number
|
|
* Author : Ivan Lin
|
|
* Return : enum halmac_ret_status
|
|
* More details of status code can be found in prototype document
|
|
*/
|
|
enum halmac_ret_status
|
|
txfifo_is_empty_88xx(struct halmac_adapter *adapter, u32 chk_num)
|
|
{
|
|
u32 cnt;
|
|
struct halmac_api *api = (struct halmac_api *)adapter->halmac_api;
|
|
|
|
PLTFM_MSG_TRACE("[TRACE]%s ===>\n", __func__);
|
|
|
|
cnt = (chk_num <= 10) ? 10 : chk_num;
|
|
do {
|
|
if (HALMAC_REG_R8(REG_TXPKT_EMPTY) != 0xFF)
|
|
return HALMAC_RET_TXFIFO_NO_EMPTY;
|
|
|
|
if ((HALMAC_REG_R8(REG_TXPKT_EMPTY + 1) & 0x06) != 0x06)
|
|
return HALMAC_RET_TXFIFO_NO_EMPTY;
|
|
cnt--;
|
|
|
|
} while (cnt != 0);
|
|
|
|
PLTFM_MSG_TRACE("[TRACE]%s <===\n", __func__);
|
|
|
|
return HALMAC_RET_SUCCESS;
|
|
}
|
|
|
|
/**
|
|
* (internal use)
|
|
* smart_malloc_88xx() - adapt malloc size
|
|
* @adapter : the adapter of halmac
|
|
* @size : expected malloc size
|
|
* @pNew_size : real malloc size
|
|
* Author : Ivan Lin
|
|
* Return : address pointer
|
|
*/
|
|
u8*
|
|
smart_malloc_88xx(struct halmac_adapter *adapter, u32 size, u32 *new_size)
|
|
{
|
|
u8 retry_num;
|
|
u8 *malloc_buf = NULL;
|
|
|
|
for (retry_num = 0; retry_num < 5; retry_num++) {
|
|
malloc_buf = (u8 *)PLTFM_MALLOC(size);
|
|
|
|
if (malloc_buf) {
|
|
*new_size = size;
|
|
return malloc_buf;
|
|
}
|
|
|
|
size = size >> 1;
|
|
|
|
if (size == 0)
|
|
break;
|
|
}
|
|
|
|
PLTFM_MSG_ERR("[ERR]adptive malloc!!\n");
|
|
|
|
return NULL;
|
|
}
|
|
|
|
/**
|
|
* (internal use)
|
|
* ltecoex_reg_read_88xx() - read ltecoex register
|
|
* @adapter : the adapter of halmac
|
|
* @offset : offset
|
|
* @pValue : value
|
|
* Author : Ivan Lin
|
|
* Return : enum halmac_ret_status
|
|
*/
|
|
enum halmac_ret_status
|
|
ltecoex_reg_read_88xx(struct halmac_adapter *adapter, u16 offset, u32 *value)
|
|
{
|
|
u32 cnt;
|
|
struct halmac_api *api = (struct halmac_api *)adapter->halmac_api;
|
|
|
|
cnt = 10000;
|
|
while ((HALMAC_REG_R8(LTECOEX_ACCESS_CTRL + 3) & BIT(5)) == 0) {
|
|
if (cnt == 0) {
|
|
PLTFM_MSG_ERR("[ERR]lte ready(R)\n");
|
|
return HALMAC_RET_LTECOEX_READY_FAIL;
|
|
}
|
|
cnt--;
|
|
PLTFM_DELAY_US(50);
|
|
}
|
|
|
|
HALMAC_REG_W32(LTECOEX_ACCESS_CTRL, 0x800F0000 | offset);
|
|
*value = HALMAC_REG_R32(REG_WL2LTECOEX_INDIRECT_ACCESS_READ_DATA_V1);
|
|
|
|
return HALMAC_RET_SUCCESS;
|
|
}
|
|
|
|
/**
|
|
* (internal use)
|
|
* ltecoex_reg_write_88xx() - write ltecoex register
|
|
* @adapter : the adapter of halmac
|
|
* @offset : offset
|
|
* @value : value
|
|
* Author : Ivan Lin
|
|
* Return : enum halmac_ret_status
|
|
*/
|
|
enum halmac_ret_status
|
|
ltecoex_reg_write_88xx(struct halmac_adapter *adapter, u16 offset, u32 value)
|
|
{
|
|
u32 cnt;
|
|
struct halmac_api *api = (struct halmac_api *)adapter->halmac_api;
|
|
|
|
cnt = 10000;
|
|
while ((HALMAC_REG_R8(LTECOEX_ACCESS_CTRL + 3) & BIT(5)) == 0) {
|
|
if (cnt == 0) {
|
|
PLTFM_MSG_ERR("[ERR]lte ready(W)\n");
|
|
return HALMAC_RET_LTECOEX_READY_FAIL;
|
|
}
|
|
cnt--;
|
|
PLTFM_DELAY_US(50);
|
|
}
|
|
|
|
HALMAC_REG_W32(REG_WL2LTECOEX_INDIRECT_ACCESS_WRITE_DATA_V1, value);
|
|
HALMAC_REG_W32(LTECOEX_ACCESS_CTRL, 0xC00F0000 | offset);
|
|
|
|
return HALMAC_RET_SUCCESS;
|
|
}
|
|
|
|
static void
|
|
pwr_state_88xx(struct halmac_adapter *adapter, enum halmac_mac_power *state)
|
|
{
|
|
struct halmac_api *api = (struct halmac_api *)adapter->halmac_api;
|
|
|
|
if ((HALMAC_REG_R8(REG_SYS_FUNC_EN + 1) & BIT(3)) == 0)
|
|
*state = HALMAC_MAC_POWER_OFF;
|
|
else
|
|
*state = HALMAC_MAC_POWER_ON;
|
|
}
|
|
|
|
static u8
|
|
packet_in_nlo_88xx(struct halmac_adapter *adapter,
|
|
enum halmac_packet_id pkt_id)
|
|
{
|
|
enum halmac_packet_id nlo_pkt = HALMAC_PACKET_PROBE_REQ_NLO;
|
|
|
|
if (pkt_id >= nlo_pkt)
|
|
return 1;
|
|
else
|
|
return 0;
|
|
}
|
|
|
|
static enum halmac_packet_id
|
|
get_real_pkt_id_88xx(struct halmac_adapter *adapter,
|
|
enum halmac_packet_id pkt_id)
|
|
{
|
|
enum halmac_packet_id real_pkt_id;
|
|
|
|
PLTFM_MSG_TRACE("[TRACE]%s ===>\n", __func__);
|
|
|
|
switch (pkt_id) {
|
|
case HALMAC_PACKET_PROBE_REQ_NLO:
|
|
real_pkt_id = HALMAC_PACKET_PROBE_REQ;
|
|
break;
|
|
case HALMAC_PACKET_SYNC_BCN_NLO:
|
|
real_pkt_id = HALMAC_PACKET_SYNC_BCN;
|
|
break;
|
|
case HALMAC_PACKET_DISCOVERY_BCN_NLO:
|
|
real_pkt_id = HALMAC_PACKET_DISCOVERY_BCN;
|
|
break;
|
|
default:
|
|
real_pkt_id = pkt_id;
|
|
}
|
|
PLTFM_MSG_TRACE("[TRACE]%s <===\n", __func__);
|
|
return real_pkt_id;
|
|
}
|
|
|
|
static u32
|
|
get_update_packet_page_size(struct halmac_adapter *adapter, u32 size)
|
|
{
|
|
struct halmac_api *api = (struct halmac_api *)adapter->halmac_api;
|
|
u32 txdesc_size;
|
|
u32 total;
|
|
|
|
api->halmac_get_hw_value(adapter, HALMAC_HW_TX_DESC_SIZE, &txdesc_size);
|
|
|
|
total = size + txdesc_size;
|
|
return (total & 0x7f) > 0 ?
|
|
(total >> TX_PAGE_SIZE_SHIFT_88XX) + 1 :
|
|
total >> TX_PAGE_SIZE_SHIFT_88XX;
|
|
}
|
|
|
|
#endif /* HALMAC_88XX_SUPPORT */
|