1733 lines
48 KiB
C
1733 lines
48 KiB
C
/****************************************************************************
|
|
|
|
Copyright(c) 2019 by Aerospace C.Power (Chongqing) Microelectronics. ALL RIGHTS RESERVED.
|
|
|
|
This Information is proprietary to Aerospace C.Power (Chongqing) Microelectronics and MAY NOT
|
|
be copied by any method or incorporated into another program without
|
|
the express written consent of Aerospace C.Power. This Information or any portion
|
|
thereof remains the property of Aerospace C.Power. The Information contained herein
|
|
is believed to be accurate and Aerospace C.Power assumes no responsibility or
|
|
liability for its use in any way and conveys no license or title under
|
|
any patent or copyright and makes no representation or warranty that this
|
|
Information is free from patent or copyright infringement.
|
|
|
|
****************************************************************************/
|
|
|
|
#include "mac_vdev_api.h"
|
|
#include "mac_vdev.h"
|
|
#include "mac_pdev.h"
|
|
#include "iot_errno.h"
|
|
#include "iot_mem_pool.h"
|
|
#include "mac_msg.h"
|
|
#include "mac.h"
|
|
#include "mac_peer.h"
|
|
#include "mac_sched.h"
|
|
#include "mac_sched_hw.h"
|
|
#include "mac_cmn_hw.h"
|
|
#include "mac_tx_hw.h" /* for flush */
|
|
#include "mac_desc_engine.h"
|
|
#include "mac_rx_buf_ring.h"
|
|
#include "mac_cert_test.h"
|
|
#include "plc_cert_test.h"
|
|
#include "iot_io.h"
|
|
#include "mac_rx_hw.h"
|
|
#include "hw_war.h"
|
|
#include "iot_gptmr_api.h"
|
|
|
|
#include "rate_control.h"
|
|
#include "mac_reset.h"
|
|
#include "mac_init_api.h"
|
|
#include "phy_chn.h"
|
|
#include "phy_txrx_pwr.h"
|
|
#include "phy_phase.h"
|
|
#include "plc_mme_zero_cross.h"
|
|
#include "mac_ppm_scan.h"
|
|
#include "mac_pm.h"
|
|
#include "mac_tx_power.h"
|
|
#include "mac_channel.h"
|
|
#include "mac_stream.h"
|
|
#include "mac_mm_sniffer.h"
|
|
#include "mac_check_spur_sta.h"
|
|
#include "mac_rf_vdev.h"
|
|
#include "mac_rf_sched.h"
|
|
#include "mac_rf_tx_hw.h"
|
|
#include "mac_rf.h"
|
|
#include "mac_rf_scan.h"
|
|
#include "mac_rf_tx_power.h"
|
|
#if HPLC_RF_DEV_SUPPORT
|
|
#include "mac_rf_common_hw.h"
|
|
#endif
|
|
#include "hw_phy_init.h"
|
|
#include "iot_oem_api.h"
|
|
|
|
static void mac_vdev_set_force_phase(mac_vdev_t *vdev,
|
|
uint8_t force_en, uint8_t force_phase)
|
|
{
|
|
IOT_ASSERT(vdev);
|
|
uint8_t node_role = mac_vdev_cfg_get_node_role(vdev);
|
|
|
|
if (PLC_DEV_ROLE_CCO == node_role) {
|
|
cfg_phy_tx_phase_select(force_en, force_phase);
|
|
} else {
|
|
phy_set_trx_switch_gpio_phase(force_phase);
|
|
}
|
|
}
|
|
|
|
/*
|
|
* @brief vdev_set_sec_key() - set security key
|
|
* @param vdev: mac vdev pointer
|
|
* @param sec_key: point to sec_key infomation
|
|
*/
|
|
static void vdev_set_sec_key(mac_vdev_t *vdev, mac_sec_key_t *sec_key)
|
|
{
|
|
if (NULL == vdev->sec_key) {
|
|
iot_printf("vdev sec_key is null\n");
|
|
goto out;
|
|
}
|
|
|
|
if ((sec_key->encrypt_type > MAC_ENCRYPT_IEEE1901_1_PB_AES_CBC) ||
|
|
(sec_key->encrypt_type < MAC_ENCRYPT_SG_MSDU_AES_CBC)) {
|
|
iot_printf("vdev set sec algorithm type is error\n");
|
|
goto out;
|
|
}
|
|
|
|
if (sec_key->key_type == ENCRYPT_KEY_TYPE_NONE) {
|
|
iot_printf("vdev set sec key type is error\n");
|
|
goto out;
|
|
}
|
|
|
|
if ((sec_key->keybits != MAC_ENCRYPT_KEY_BIT_LEN_128) &&
|
|
(sec_key->keybits != MAC_ENCRYPT_KEY_BIT_LEN_192) &&
|
|
(sec_key->keybits != MAC_ENCRYPT_KEY_BIT_LEN_256)) {
|
|
iot_printf("vdev set sec keybits = %d is error\n", sec_key->keybits);
|
|
goto out;
|
|
}
|
|
|
|
os_mem_cpy(vdev->sec_key, sec_key, sizeof(mac_sec_key_t));
|
|
|
|
out:
|
|
return;
|
|
}
|
|
|
|
tei_t vdev_get_tei(mac_vdev_t* vdev)
|
|
{
|
|
if (NULL == vdev) {
|
|
IOT_ASSERT(0);
|
|
return PLC_TEI_INVAL;
|
|
}
|
|
mac_peer_t *self_peer = (mac_peer_t*)vdev->self_peer;
|
|
if (self_peer) {
|
|
return (tei_t)self_peer->tei;
|
|
}
|
|
|
|
return PLC_TEI_INVAL;
|
|
}
|
|
|
|
void vdev_set_tei(mac_vdev_t* vdev, tei_t tei)
|
|
{
|
|
IOT_ASSERT(vdev);
|
|
mac_peer_t *self_peer = (mac_peer_t*)vdev->self_peer;
|
|
if (self_peer) {
|
|
/* if not reduced vdev, update hw tei */
|
|
if (!vdev->mac_vdev_cfg.is_reduced_vdev) {
|
|
self_peer->tei = tei;
|
|
mac_config_tei(vdev, tei);
|
|
}
|
|
}
|
|
}
|
|
|
|
uint32_t mac_create_vdev(uint8_t pdev_id, uint8_t *vdev_id_created,
|
|
mac_vdev_cfg_t *cfg)
|
|
{
|
|
uint32_t ret = 0;
|
|
mac_msg_sync_t *msg = mac_alloc_msg_sync();
|
|
|
|
if (msg == NULL) {
|
|
IOT_ASSERT(0);
|
|
ret = ERR_NOMEM;
|
|
goto out;
|
|
}
|
|
|
|
msg->msg.type = MAC_MSG_TYPE_CVG;
|
|
msg->msg.id = MAC_MSG_ID_CVG_CREATE_VDEV;
|
|
msg->msg.data1 = pdev_id;
|
|
msg->msg.data2 = cfg;
|
|
mac_queue_msg_sync(msg, MAC_MSG_QUEUE_HP);
|
|
ret = msg->msg.data1;
|
|
*vdev_id_created = (uint8_t)(((uint32_t)msg->msg.data2) & 0xFF);
|
|
mac_free_msg_sync(msg);
|
|
|
|
out:
|
|
return ret;
|
|
}
|
|
|
|
uint32_t mac_create_vdev_internal(uint8_t pdev_id, uint8_t *vdev_id_created,
|
|
mac_vdev_cfg_t *cfg)
|
|
{
|
|
uint32_t cur_vdev_num, vdev_id = MAX_VDEV_NUM, ret;
|
|
mac_vdev_t *vdev;
|
|
mac_pdev_t *pdev;
|
|
|
|
if (pdev_id >= MAX_PDEV_NUM) {
|
|
return ERR_INVAL;
|
|
}
|
|
pdev = get_pdev_ptr(pdev_id);
|
|
if (!pdev) {
|
|
return ERR_INVAL;
|
|
}
|
|
|
|
cur_vdev_num = pdev->cur_vdev_num;
|
|
IOT_ASSERT(cur_vdev_num + 1 <= MAX_VDEV_NUM);
|
|
|
|
for (uint32_t i = 0; i < MAX_VDEV_NUM; i++) {
|
|
if (pdev->vdev[i] == NULL) {
|
|
vdev_id = i;
|
|
break;
|
|
}
|
|
}
|
|
IOT_ASSERT(vdev_id < MAX_VDEV_NUM);
|
|
|
|
vdev = iot_mem_pool_alloc(&pdev->vdev_pool);
|
|
if (vdev == NULL) {
|
|
return ERR_NOMEM;
|
|
}
|
|
os_mem_set(vdev, 0, sizeof(*vdev));
|
|
pdev->vdev[vdev_id] = vdev;
|
|
pdev->cur_vdev_num++;
|
|
|
|
vdev->vdev_id = (vdevid_t)vdev_id;
|
|
vdev->ref_pdev_id = pdev_id;
|
|
|
|
/* create self peer */
|
|
ret = mac_peer_alloc(vdev, PLC_TEI_INVAL, \
|
|
1, 1, 0, 0, (mac_peer_t **)&vdev->self_peer);
|
|
IOT_ASSERT(ret == 0);
|
|
|
|
/* create bcast peer */
|
|
ret = mac_peer_alloc(vdev, PLC_TEI_BCAST, \
|
|
0, 1, 0, 0, (mac_peer_t **)&vdev->bcast_peer);
|
|
IOT_ASSERT(ret == 0);
|
|
|
|
if (cfg) {
|
|
vdev->mac_vdev_cfg = *cfg;
|
|
if (cfg->node_role == PLC_DEV_ROLE_CCO) {
|
|
vdev_set_tei(vdev, PLC_TEI_CCO);
|
|
/* init logical phase of CCO role device */
|
|
vdev->l_phase1 = PLC_PHASE_ALL;
|
|
vdev->l_phase2 = PLC_PHASE_ALL;
|
|
vdev->l_phase3 = PLC_PHASE_ALL;
|
|
switch (cfg->p_phase_cnt) {
|
|
case 3:
|
|
vdev->l_phase3 = PLC_PHASE_C;
|
|
case 2:
|
|
vdev->l_phase2 = PLC_PHASE_B;
|
|
case 1:
|
|
vdev->l_phase1 = PLC_PHASE_A;
|
|
break;
|
|
default:
|
|
IOT_ASSERT(0);
|
|
break;
|
|
}
|
|
/* td tx nncco phase */
|
|
vdev->nncco_tx_3phase = (uint8_t)cfg->is_td_tx_nncco_3phase;
|
|
vdev->nncco_td_tx_phase = PLC_PHASE_A;
|
|
} else {
|
|
vdev_set_tei(vdev, PLC_TEI_INVAL);
|
|
/* sta role device logical phase will be inited later when upper
|
|
* layer plan to start the vdev. see mac_set_vdev_cfg_internal.
|
|
*/
|
|
IOT_ASSERT(cfg->p_phase_cnt == 1);
|
|
vdev->l_phase1 = PLC_PHASE_ALL;
|
|
vdev->l_phase2 = PLC_PHASE_ALL;
|
|
vdev->l_phase3 = PLC_PHASE_ALL;
|
|
}
|
|
}
|
|
*vdev_id_created = (uint8_t)vdev_id;
|
|
|
|
/* if this vdev not reduced, need create cfg and hw ctxt */
|
|
if (!vdev->mac_vdev_cfg.is_reduced_vdev) {
|
|
if (!vdev->sub_peer_bitmap) {
|
|
vdev->sub_peer_bitmap = os_mem_malloc(PLC_MAC_COMMON_MID,
|
|
sizeof(mac_tei_map_t));
|
|
}
|
|
IOT_ASSERT(vdev->sub_peer_bitmap);
|
|
mac_tei_map_reset((mac_tei_map_t *)vdev->sub_peer_bitmap);
|
|
/* init the beacon ctx */
|
|
mac_beacon_init(&vdev->bcn_ctx, vdev);
|
|
/* init the scheduler context */
|
|
mac_sched_init(vdev);
|
|
/* init mac rf info */
|
|
vdev->mac_rf = mac_rf_init();
|
|
|
|
/* init power cap */
|
|
mac_fix_power_init(vdev);
|
|
|
|
#if MAC_STREAM_TIMEOUT_SUPPORT
|
|
/*create timer for stream out*/
|
|
vdev->stream_timeout_timer = \
|
|
os_create_timer(PLC_MAC_RX_MID, true, \
|
|
mac_vdev_del_timeout_stream, vdev);
|
|
#endif
|
|
/* ppm per vdev should be init,
|
|
* because sometimes nid=0's cert
|
|
* bcn still be needed to sync ppm
|
|
*/
|
|
mac_ppm_init(&vdev->mac_ppm, phy_get_cal_ppm_in_pib(), 0);
|
|
/* rate control */
|
|
ra_init(vdev, RATE_ADAPTION_ENABLE);
|
|
} //if (!vdev->mac_vdev_cfg.is_reduced_vdev)
|
|
|
|
/* time stamp for record */
|
|
vdev->last_rx_ntb = 0;
|
|
vdev->last_tx_ntb = 0;
|
|
#if PLC_SUPPORT_DBG_PKT_MODE
|
|
/* init to allow send dbg pkt in rx only period */
|
|
vdev_set_block_dbg_pkt_4_rx_only(vdev, false);
|
|
#endif
|
|
|
|
#if CERT_WAR_TX_PWR == 1
|
|
vdev->cert_war_pwr = 0;
|
|
#endif
|
|
|
|
/* support rf dev */
|
|
if (cfg && !vdev->mac_vdev_cfg.is_reduced_vdev) {
|
|
ret = mac_create_rf_vdev_internal(pdev_id, vdev->vdev_id,
|
|
RF_PDEV_ID, &vdev->rf_vdev_id);
|
|
if (!ret) {
|
|
iot_printf("rf vdev creat success\n");
|
|
} else {
|
|
iot_printf("rf vdev creat fail\n");
|
|
}
|
|
}
|
|
|
|
if (!vdev->mac_vdev_cfg.is_reduced_vdev) {
|
|
vdev->sec_key = os_mem_malloc(PLC_MAC_COMMON_MID,
|
|
sizeof(mac_sec_key_t));
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
mac_vdev_t *get_vdev_ptr(uint32_t pdev_id, uint32_t vdev_id) {
|
|
if (pdev_id >= MAX_PDEV_NUM || vdev_id >= MAX_VDEV_NUM) {
|
|
IOT_ASSERT(0);
|
|
return NULL;
|
|
}
|
|
return g_mac_pdev[pdev_id]->vdev[vdev_id];
|
|
}
|
|
|
|
uint32_t mac_start_vdev(uint8_t pdev_id, uint8_t vdev_id,
|
|
mac_vdev_start_cfg_t *cfg)
|
|
{
|
|
uint32_t ret = 0;
|
|
mac_msg_sync_t *msg = mac_alloc_msg_sync();
|
|
|
|
if (msg == NULL) {
|
|
IOT_ASSERT(0);
|
|
ret = ERR_NOMEM;
|
|
goto out;
|
|
}
|
|
|
|
msg->msg.type = MAC_MSG_TYPE_CVG;
|
|
msg->msg.id = MAC_MSG_ID_CVG_START_VDEV;
|
|
msg->msg.data1 = (((uint32_t)pdev_id) << 8) | vdev_id;
|
|
msg->msg.data2 = cfg;
|
|
mac_queue_msg_sync(msg, MAC_MSG_QUEUE_HP);
|
|
ret = msg->msg.data1;
|
|
mac_free_msg_sync(msg);
|
|
|
|
out:
|
|
return ret;
|
|
}
|
|
|
|
uint32_t mac_start_vdev_internal(uint8_t pdev_id, uint8_t vdev_id,
|
|
mac_vdev_start_cfg_t *cfg)
|
|
{
|
|
uint64_t start_ntb;
|
|
mac_vdev_t *vdev;
|
|
mac_pdev_t *pdev_ptr = \
|
|
(mac_pdev_t *)g_mac_pdev[pdev_id];
|
|
|
|
if (cfg == NULL) {
|
|
return ERR_INVAL;
|
|
}
|
|
vdev = get_vdev_ptr(pdev_id, vdev_id);
|
|
if (vdev == NULL) {
|
|
return ERR_INVAL;
|
|
}
|
|
|
|
if (vdev->is_up) {
|
|
return ERR_OK;
|
|
}
|
|
|
|
// todo: temporary implementation for testing beacon receiving
|
|
vdev->start_cfg = *cfg;
|
|
|
|
|
|
#if CERT_WAR_TX_PWR == 1
|
|
/* check mac addr when start vdev */
|
|
vdev->cert_war_pwr = mac_cert_war_tx_pwr(cfg->mac_addr);
|
|
#endif
|
|
|
|
vdev->is_up = 1;
|
|
|
|
/* if this vdev not reduced, need init config and hw info */
|
|
if (!vdev->mac_vdev_cfg.is_reduced_vdev) {
|
|
/* clear rise power flag */
|
|
phy_rise_pwr_flag_set(false);
|
|
/* config local device role to HW */
|
|
mac_config_role(vdev, mac_vdev_cfg_get_node_role(vdev));
|
|
mac_sched_stop(vdev);
|
|
if (mac_vdev_cfg_get_node_role(vdev) == PLC_DEV_ROLE_STA) {
|
|
/* add separate phy select for PHY */
|
|
phy_rx_phase_force_set(1, 0);
|
|
/* force tx phase A for K68 */
|
|
cfg_phy_tx_phase_select(1, 1);
|
|
if (vdev->bcn_ctx.sta.force_sw_sync) {
|
|
/* disable HW ntb sync feature */
|
|
mac_sched_enable_hw_ntb_sync(vdev, 0);
|
|
} else {
|
|
/* enable HW ntb sync feature */
|
|
mac_sched_enable_hw_ntb_sync(vdev, 1);
|
|
}
|
|
#if STATIC_POWER_SAVE
|
|
/* start power save */
|
|
mac_pm_start(pdev_ptr);
|
|
pdev_ptr->mac_pm.fc_ok_pm =
|
|
mac_pm_switch_by_fc_ok(cfg->mac_addr);
|
|
#endif
|
|
|
|
#if MAC_ZC_START_FOLLOW_VDEV
|
|
mac_zc_set_func_cmd(pdev_id, MAC_ZC_FUNC_CMD_RESET_HW, NULL);
|
|
#endif
|
|
} else if (mac_vdev_cfg_get_node_role(vdev) == PLC_DEV_ROLE_CCO) {
|
|
/* disable it for CCo */
|
|
mac_sched_enable_hw_ntb_sync(vdev, 0);
|
|
#if FORCE_CCO_ON_3_PHASE
|
|
/* for CCO working on 3 phase */
|
|
phy_rx_phase_force_set(1, 0);
|
|
#endif
|
|
/* restart mac zc for cco only */
|
|
mac_zc_set_func_cmd(pdev_id, MAC_ZC_FUNC_CMD_RESET_HW, NULL);
|
|
}
|
|
|
|
/* config HW golden gap as suggested by HW team */
|
|
mac_sched_sync_ntb(vdev, MAC_SCHED_GOLDEN_GAP, 0);
|
|
|
|
/* config HW scheduler to RX only mode */
|
|
mac_sched_set_bp_ahead_alert(vdev, MAC_BP_AHEAD_ALERT_DUR);
|
|
mac_sched_set_recursive_mode(vdev, 0);
|
|
start_ntb = mac_sched_get_ntb64(vdev);
|
|
mac_sched_set_csma_only(vdev, start_ntb, 0);
|
|
/* enable hw rx */
|
|
mac_rx_all_ring_enable(pdev_ptr);
|
|
|
|
/* enable check spur */
|
|
mac_check_spur_en(&pdev_ptr->mac_check_spur_ctxt, true);
|
|
|
|
if (mac_vdev_cfg_get_node_role(vdev) == PLC_DEV_ROLE_STA) {
|
|
/* sta check spur start timer */
|
|
mac_sta_check_spur_timer_start(&pdev_ptr->mac_check_spur_ctxt,
|
|
vdev, MAC_STA_CHECK_SPUR);
|
|
/* start the scan */
|
|
mac_scan_start(&pdev_ptr->scan);
|
|
|
|
#if K48_STA_MULTI_CHANNEL_SELECT_ENABLE
|
|
iot_mac_k48sta_scan_channel_start(pdev_ptr);
|
|
#endif
|
|
}
|
|
#if (MAC_MM_SNIFFER_MODE)
|
|
mac_mm_sniffer_init(vdev);
|
|
#endif
|
|
|
|
mac_vdev_war_rx_abort_init();
|
|
} //if (!vdev->mac_vdev_cfg.is_reduced_vdev)
|
|
|
|
/* clear stop flag */
|
|
vdev->stop_flag = 0;
|
|
|
|
if (!vdev->mac_vdev_cfg.is_reduced_vdev) {
|
|
#if ENA_WAR_421_DEBUG
|
|
extern uint32_t g_is_check_phy_rx;
|
|
g_is_check_phy_rx = 1;
|
|
vdev->last_rx_ntb = 0;
|
|
#endif
|
|
|
|
#if MAC_STREAM_TIMEOUT_SUPPORT
|
|
if(vdev->stream_timeout_timer)
|
|
{
|
|
os_start_timer(vdev->stream_timeout_timer, \
|
|
MAC_RX_STREAM_TIMEOUT_MS); //20s
|
|
}
|
|
#endif
|
|
mac_ppm_record_timer_start(&vdev->mac_ppm);
|
|
} //if (!vdev->mac_vdev_cfg.is_reduced_vdev)
|
|
|
|
/* enable tx rx process */
|
|
mac_sw_trig_start(true);
|
|
|
|
#if PLC_SUPPORT_DBG_PKT_MODE
|
|
/* init to allow send dbg pkt in rx only period */
|
|
vdev_set_block_dbg_pkt_4_rx_only(vdev, false);
|
|
|
|
if ((PLC_INV_DBG_PKT_MODE_VDEV_ID != pdev_ptr->dbg_pkt_vdev_id) \
|
|
&& (vdev_id != pdev_ptr->dbg_pkt_vdev_id)) {
|
|
mac_start_vdev_internal(pdev_id, \
|
|
(uint8_t)pdev_ptr->dbg_pkt_vdev_id, cfg);
|
|
}
|
|
|
|
if (vdev->mac_vdev_cfg.is_reduced_vdev \
|
|
&& (pdev_ptr->dbg_pkt_vdev_id == vdev->vdev_id)) {
|
|
vdev_set_nid(vdev, PLC_DBG_PKT_MODE_NID);
|
|
}
|
|
#endif
|
|
|
|
/* if rf_cfg is not null and just is not reduce vdev handle start rf vdev */
|
|
if (vdev_id != pdev_ptr->dbg_pkt_vdev_id) {
|
|
uint32_t ret = mac_start_rf_vdev_internal(pdev_id,
|
|
RF_PDEV_ID, vdev->rf_vdev_id, cfg);
|
|
if (!ret) {
|
|
iot_printf("rf vdev start success\n");
|
|
} else {
|
|
iot_printf("rf vdev start fail\n");
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
uint32_t mac_set_vdev_cfg(pdevid_t pdev_id, vdevid_t vdev_id,
|
|
cfg_data_tlv *tlv)
|
|
{
|
|
uint32_t ret = 0;
|
|
mac_msg_sync_t *msg = mac_alloc_msg_sync();
|
|
|
|
if (msg == NULL) {
|
|
IOT_ASSERT(0);
|
|
ret = ERR_NOMEM;
|
|
goto out;
|
|
}
|
|
|
|
msg->msg.type = MAC_MSG_TYPE_CVG;
|
|
msg->msg.id = MAC_MSG_ID_CVG_SET_VDEV_CFG;
|
|
msg->msg.data1 = (((uint32_t)pdev_id) << 8) | vdev_id;
|
|
msg->msg.data2 = tlv;
|
|
mac_queue_msg_sync(msg, MAC_MSG_QUEUE_HP);
|
|
ret = msg->msg.data1;
|
|
mac_free_msg_sync(msg);
|
|
|
|
out:
|
|
return ret;
|
|
}
|
|
|
|
uint32_t mac_set_vdev_cfg_internal(pdevid_t pdev_id, vdevid_t vdev_id,
|
|
cfg_data_tlv *tlv)
|
|
{
|
|
uint32_t ret = 0;
|
|
mac_vdev_t *vdev;
|
|
mac_rf_vdev_t *rf_vdev = get_rf_vdev_ptr(PLC_PDEV_ID, RF_PDEV_ID,
|
|
PLC_DEFAULT_VDEV);
|
|
|
|
vdev = get_vdev_ptr(pdev_id, vdev_id);
|
|
if (vdev == NULL) {
|
|
ret = ERR_INVAL;
|
|
goto out;
|
|
}
|
|
|
|
switch (tlv->type) {
|
|
case PLC_VDEV_CFG_SET_STA_INFO:
|
|
{
|
|
PLC_VDEV_CFG_SET_STA_INFO_STRUCT *xtlv =
|
|
(PLC_VDEV_CFG_SET_STA_INFO_STRUCT *)tlv;
|
|
|
|
vdev_set_proxy_tei(vdev, xtlv->proxy_tei);
|
|
vdev_set_logic_phase(vdev, xtlv->phase);
|
|
vdev_set_tei(vdev, xtlv->self_tei);
|
|
#if STATIC_POWER_SAVE
|
|
/* stop for static power manager */
|
|
mac_pm_stop(get_pdev_ptr(pdev_id));
|
|
#endif
|
|
|
|
/* disable ckq/testing mode period check spur */
|
|
if (xtlv->self_tei != PLC_TEI_INVAL) {
|
|
mac_sta_period_check_spur_ctl_by_other(false);
|
|
}
|
|
|
|
break;
|
|
}
|
|
case PLC_VDEV_CFG_ADD_D_SUB_STA:
|
|
case PLC_VDEV_CFG_DELETE_D_SUB_STA:
|
|
{
|
|
PLC_VDEV_CFG_D_SUB_STA_STRUCT *xtlv =
|
|
(PLC_VDEV_CFG_D_SUB_STA_STRUCT *)tlv;
|
|
|
|
tei_t tei = xtlv->sub_sta;
|
|
nid_t nid;
|
|
vdev_get_nid(vdev, &nid); //TODO:
|
|
mac_peer_t *peer = find_peer(vdev, nid, tei);
|
|
if (tlv->type == PLC_VDEV_CFG_DELETE_D_SUB_STA) {
|
|
if (peer) {
|
|
if (vdev->sub_peer_cnt > 0) {
|
|
vdev->sub_peer_cnt--;
|
|
} else {
|
|
iot_printf("sub peer cnt is reach min!!!\n");
|
|
}
|
|
/* del peer */
|
|
iot_printf("cur sub peer cnt:%d, del sub peer 0x%x, tei = %d\n",
|
|
vdev->sub_peer_cnt, peer, tei);
|
|
/* should not be self peer */
|
|
IOT_ASSERT(peer->is_self_peer == 0);
|
|
/* should not be bcast peer */
|
|
IOT_ASSERT(peer->is_bcast_peer == 0);
|
|
if (is_peer_empty(peer) == 0) {
|
|
peer->is_sub_peer = 0;
|
|
goto out;
|
|
}
|
|
mac_tei_map_clear((mac_tei_map_t *)vdev->sub_peer_bitmap,
|
|
peer->tei);
|
|
mac_peer_free(vdev, peer);
|
|
}
|
|
} else {
|
|
/* add peer */
|
|
iot_printf("try to add peer 0x%x:tei=%d in nid 0x%x\n", \
|
|
peer, tei, nid);
|
|
if (peer == NULL) {
|
|
ret = mac_peer_alloc(vdev, tei, 0, 0, 1, 0, &peer);
|
|
} else {
|
|
peer->is_sub_peer = 1;
|
|
}
|
|
mac_tei_map_set((mac_tei_map_t *)vdev->sub_peer_bitmap, peer->tei);
|
|
vdev->sub_peer_cnt++;
|
|
if (vdev->sub_peer_cnt >= PLC_PCO_MAX_D_SUB_STA) {
|
|
iot_printf("sub peer cnt is reach max!!!\n");
|
|
}
|
|
iot_printf("cur sub peer cnt:%d, add sub peer 0x%x, tei = %d\n", \
|
|
vdev->sub_peer_cnt, peer, tei);
|
|
}
|
|
break;
|
|
}
|
|
case PLC_VDEV_CFG_SET_BL_NID:
|
|
{
|
|
PLC_VDEV_CFG_SET_BL_NID_STRUCT *xtlv =
|
|
(PLC_VDEV_CFG_SET_BL_NID_STRUCT *)tlv;
|
|
|
|
if (xtlv->cnt && xtlv->cnt <= PLC_BL_NID_LIST_MAX) {
|
|
vdev->nid_bl_list_cnt = xtlv->cnt;
|
|
os_mem_cpy(vdev->nid_bl_list, xtlv->nid,
|
|
sizeof(xtlv->nid[0]) * xtlv->cnt);
|
|
} else {
|
|
vdev->nid_bl_list_cnt = 0;
|
|
os_mem_set(vdev->nid_bl_list, 0, sizeof(vdev->nid_bl_list));
|
|
}
|
|
break;
|
|
}
|
|
case PLC_VDEV_CFG_SET_PREFER_NID:
|
|
{
|
|
PLC_VDEV_CFG_SET_PREFER_NID_STRUCT *xtlv =
|
|
(PLC_VDEV_CFG_SET_PREFER_NID_STRUCT *)tlv;
|
|
|
|
vdev_set_nid(vdev, xtlv->nid);
|
|
vdev_set_proxy_tei(vdev, xtlv->proxy);
|
|
/* reset the current ppm settings as we need to sync up with new nid.
|
|
* Note that we don't reset current pdev ppm settings as we need to
|
|
* stay in current ppm to sync up with preferred nid.
|
|
*/
|
|
vdev_reset_ppm_sync(vdev);
|
|
mac_rf_vdev_reset_sync_nid(rf_vdev);
|
|
|
|
/* for same case, non-response detection package.
|
|
* if rx detect pkt on band1, need no response,
|
|
* at this time cvg will set a inval nid to mac,
|
|
* and mac will scan band immediately.
|
|
*/
|
|
if (xtlv->nid == PLC_NID_INVALID &&
|
|
PHY_PROTO_TYPE_GET() == PLC_PROTO_TYPE_SPG) {
|
|
/* scan band immediately */
|
|
mac_nid_ppm_reset_msg_handler();
|
|
}
|
|
break;
|
|
}
|
|
case PLC_VDEV_CFG_SET_FIXED_RATE:
|
|
{
|
|
PLC_VDEV_CFG_SET_FIXED_RATE_STRUCT *xtlv =
|
|
(PLC_VDEV_CFG_SET_FIXED_RATE_STRUCT *)tlv;
|
|
vdev_set_fixed_rate(vdev, xtlv->enable);
|
|
vdev_set_fixed_rate_level(vdev, xtlv->rate_level);
|
|
break;
|
|
}
|
|
case PLC_VDEV_CFG_SET_TX_POWER_CAP:
|
|
{
|
|
PLC_VDEV_CFG_SET_TX_POWER_CAP_STRUCT *xtlv =
|
|
(PLC_VDEV_CFG_SET_TX_POWER_CAP_STRUCT *)tlv;
|
|
if (xtlv->hplc_valid) {
|
|
mac_set_tx_power_cap(vdev, &xtlv->hplc_power, NULL, 0);
|
|
}
|
|
if (xtlv->rf_valid) {
|
|
mac_set_tx_power_cap(vdev, NULL, &xtlv->rf_power, 0);
|
|
}
|
|
break;
|
|
}
|
|
case PLC_VDEV_CFG_SET_NID_ONLY:
|
|
{
|
|
PLC_PDEV_CFG_SET_NID_ONLY_STRUCT *xtlv =
|
|
(PLC_PDEV_CFG_SET_NID_ONLY_STRUCT *)tlv;
|
|
vdev_set_nid(vdev, xtlv->nid);
|
|
break;
|
|
}
|
|
case PLC_VDEV_CFG_SET_TEI_ONLY:
|
|
{
|
|
PLC_PDEV_CFG_SET_TEI_ONLY_STRUCT *xtlv =
|
|
(PLC_PDEV_CFG_SET_TEI_ONLY_STRUCT *)tlv;
|
|
vdev_set_tei(vdev, xtlv->self_tei);
|
|
break;
|
|
}
|
|
case PLC_VDEV_CFG_DUMP_REQ:
|
|
{
|
|
mac_dump_buf_from_cvg();
|
|
break;
|
|
}
|
|
case PLC_VDEV_CFG_SET_NW_VALID:
|
|
{
|
|
#if STATIC_POWER_SAVE
|
|
/* stop for static power manager */
|
|
mac_pm_stop(get_pdev_ptr(pdev_id));
|
|
#endif
|
|
break;
|
|
}
|
|
case PLC_VDEV_CFG_SET_PM_SAVE_CFG:
|
|
{
|
|
#if STATIC_POWER_SAVE
|
|
PLC_VDEV_CFG_SET_PM_SAVE_CFG_STRUCT *xtlv =
|
|
(PLC_VDEV_CFG_SET_PM_SAVE_CFG_STRUCT *)tlv;
|
|
req_stay_awake(MAC_PM_UPLAYER_DEMAND_MODULE_ID, !!xtlv->allow_sleep);
|
|
#endif
|
|
break;
|
|
}
|
|
case PLC_VDEV_CFG_CTL_CHECK_SPUR:
|
|
{
|
|
PLC_PDEV_CFG_CTL_CK_SPUR_STRUCT *xtlv =
|
|
(PLC_PDEV_CFG_CTL_CK_SPUR_STRUCT *)tlv;
|
|
nid_t my_nid;
|
|
tei_t tei = vdev_get_tei(vdev);
|
|
vdev_get_nid(vdev, &my_nid);
|
|
/* if associated, mac not response this evt */
|
|
if (!(PLC_TEI_IS_VALID(tei) && my_nid != PLC_NID_INVALID)) {
|
|
mac_sta_period_check_spur_ctl_by_other(xtlv->is_start);
|
|
}
|
|
break;
|
|
}
|
|
case PLC_VDEV_CFG_SET_RF_CHANNEL:
|
|
{
|
|
PLC_VDEV_CFG_SET_RF_CHANNEL_STRUCT *xtlv =
|
|
(PLC_VDEV_CFG_SET_RF_CHANNEL_STRUCT *)tlv;
|
|
mac_rf_set_self_option_channel(xtlv->rf_option, xtlv->rf_channel);
|
|
/* stop rf scan timer */
|
|
mac_rf_scan_stop();
|
|
/* set channel selected */
|
|
mac_rf_scan_set_channel_selected(1);
|
|
break;
|
|
}
|
|
case PLC_VDEV_CFG_SET_FORCE_PHASE:
|
|
{
|
|
PLC_VDEV_CFG_SET_FORCE_PHASE_STRUCT *xtlv =
|
|
(PLC_VDEV_CFG_SET_FORCE_PHASE_STRUCT *)tlv;
|
|
mac_vdev_set_force_phase(vdev, xtlv->enable, xtlv->phase);
|
|
break;
|
|
}
|
|
case PLC_VDEV_CFG_SET_STA_JOIN:
|
|
{
|
|
PLC_VDEV_CFG_SET_STA_JOIN_STRUCT *xtlv =
|
|
(PLC_VDEV_CFG_SET_STA_JOIN_STRUCT *)tlv;
|
|
vdev->sta_joined = xtlv->join_flag;
|
|
break;
|
|
}
|
|
case PLC_VDEV_CFG_SET_HPLC_RF_ASYNC_TX:
|
|
{
|
|
#if HPLC_RF_ASYNC_TX
|
|
PLC_PDEV_CFG_SET_HPLC_RF_ASYNC_TX *xtlv =
|
|
(PLC_PDEV_CFG_SET_HPLC_RF_ASYNC_TX *)tlv;
|
|
mac_rf_set_hplc_rf_async_tx(xtlv->hplc_rf_async_tx);
|
|
#endif
|
|
break;
|
|
}
|
|
case PLC_VDEV_CFG_SET_NW_NEGO:
|
|
{
|
|
PLC_VDEV_CFG_SET_NW_NEGO_STRUCT *xtlv =
|
|
(PLC_VDEV_CFG_SET_NW_NEGO_STRUCT *)tlv;
|
|
mac_sched_cco_set_nw_nego(vdev, xtlv->enable);
|
|
break;
|
|
}
|
|
case PLC_VDEV_CFG_SET_SEC_KEY:
|
|
{
|
|
PLC_VDEV_CFG_SET_SEC_KEY_STRUCT *xtlv =
|
|
(PLC_VDEV_CFG_SET_SEC_KEY_STRUCT *)tlv;
|
|
vdev_set_sec_key(vdev, &xtlv->key_info);
|
|
break;
|
|
}
|
|
case PLC_VDEV_CFG_SET_FORCE_LINK:
|
|
{
|
|
PLC_VDEV_CFG_SET_FORCE_LINK_STRUCT *xtlv =
|
|
(PLC_VDEV_CFG_SET_FORCE_LINK_STRUCT *)tlv;
|
|
if (xtlv->force_link_en) {
|
|
if (xtlv->force_rf_link) {
|
|
vdev->tx_rx_suspend = 1;
|
|
if (rf_vdev) {
|
|
rf_vdev->tx_rx_suspend = 0;
|
|
}
|
|
} else {
|
|
vdev->tx_rx_suspend = 0;
|
|
if (rf_vdev) {
|
|
rf_vdev->tx_rx_suspend = 1;
|
|
}
|
|
}
|
|
} else {
|
|
vdev->tx_rx_suspend = 0;
|
|
if (rf_vdev) {
|
|
rf_vdev->tx_rx_suspend = 0;
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
case PLC_VDEV_CFG_SET_3PS_OPPOSITE:
|
|
{
|
|
PLC_VDEV_CFG_SET_3PS_OPPOSITE_STRUCT *xtlv =
|
|
(PLC_VDEV_CFG_SET_3PS_OPPOSITE_STRUCT *)tlv;
|
|
vdev->opposite_3ps = xtlv->opposite_3ps;
|
|
break;
|
|
}
|
|
default:
|
|
IOT_ASSERT(0);
|
|
}
|
|
|
|
out:
|
|
return ret;
|
|
}
|
|
|
|
uint32_t mac_get_vdev_cfg(pdevid_t pdev_id, vdevid_t vdev_id,
|
|
cfg_data_tlv *tlv)
|
|
{
|
|
uint32_t ret = 0;
|
|
mac_msg_sync_t *msg = mac_alloc_msg_sync();
|
|
|
|
if (msg == NULL) {
|
|
IOT_ASSERT(0);
|
|
ret = ERR_NOMEM;
|
|
goto out;
|
|
}
|
|
|
|
msg->msg.type = MAC_MSG_TYPE_CVG;
|
|
msg->msg.id = MAC_MSG_ID_CVG_GET_VDEV_CFG;
|
|
msg->msg.data1 = (((uint32_t)pdev_id) << 8) | vdev_id;
|
|
msg->msg.data2 = tlv;
|
|
mac_queue_msg_sync(msg, MAC_MSG_QUEUE_HP);
|
|
ret = msg->msg.data1;
|
|
mac_free_msg_sync(msg);
|
|
|
|
out:
|
|
return ret;
|
|
}
|
|
|
|
uint32_t mac_get_vdev_cfg_internal(pdevid_t pdev_id, vdevid_t vdev_id,
|
|
cfg_data_tlv *tlv)
|
|
{
|
|
uint32_t ret = 0;
|
|
mac_vdev_t *vdev = get_vdev_ptr(pdev_id, vdev_id);
|
|
if (vdev == NULL) {
|
|
ret = ERR_INVAL;
|
|
goto out;
|
|
}
|
|
|
|
switch (tlv->type) {
|
|
case PLC_VDEV_CFG_GET_NID_PPM:
|
|
{
|
|
PLC_VDEV_CFG_NID_PPM_STRUCT *xtlv =
|
|
(PLC_VDEV_CFG_NID_PPM_STRUCT *)tlv;
|
|
xtlv->vaild_nid_cnt = mac_multi_sync_get_ppm_tbl(pdev_id,
|
|
(plc_ppm_status_t *)xtlv->ppm_tbl);
|
|
break;
|
|
}
|
|
default:
|
|
IOT_ASSERT(0);
|
|
}
|
|
|
|
out:
|
|
return ret;
|
|
|
|
}
|
|
|
|
uint32_t mac_stop_vdev(uint8_t pdev_id, uint8_t vdev_id)
|
|
{
|
|
uint32_t ret = 0;
|
|
mac_msg_sync_t *msg = mac_alloc_msg_sync();
|
|
|
|
if (msg == NULL) {
|
|
IOT_ASSERT(0);
|
|
ret = ERR_NOMEM;
|
|
goto out;
|
|
}
|
|
|
|
msg->msg.type = MAC_MSG_TYPE_CVG;
|
|
msg->msg.id = MAC_MSG_ID_CVG_STOP_VDEV;
|
|
msg->msg.data1 = (((uint32_t)pdev_id) << 8) | vdev_id;
|
|
mac_queue_msg_sync(msg, MAC_MSG_QUEUE_HP);
|
|
ret = msg->msg.data1;
|
|
mac_free_msg_sync(msg);
|
|
|
|
out:
|
|
return ret;
|
|
}
|
|
|
|
uint32_t mac_stop_vdev_internal(uint8_t pdev_id, uint8_t vdev_id)
|
|
{
|
|
mac_vdev_t * vdev = get_vdev_ptr(pdev_id, vdev_id);
|
|
mac_pdev_t *pdev_ptr = (mac_pdev_t *)g_mac_pdev[pdev_id];
|
|
|
|
if (vdev == NULL)
|
|
return ERR_INVAL;
|
|
|
|
if (vdev->is_up == 0)
|
|
return ERR_OK;
|
|
|
|
/* set stop flag */
|
|
vdev->stop_flag = 1;
|
|
|
|
/* just is not reduce vdev handle */
|
|
if (vdev_id != pdev_ptr->dbg_pkt_vdev_id) {
|
|
uint32_t ret = mac_stop_rf_vdev_internal(pdev_id, RF_PDEV_ID,
|
|
vdev->rf_vdev_id);
|
|
if (!ret) {
|
|
iot_printf("rf vdev stop success\n");
|
|
} else {
|
|
iot_printf("rf vdev stop fail\n");
|
|
}
|
|
}
|
|
|
|
/* if this vdev not reduced, need init config and hw info */
|
|
if (!vdev->mac_vdev_cfg.is_reduced_vdev) {
|
|
/* stop zc colloct */
|
|
mac_zc_set_func_cmd(pdev_id, MAC_ZC_FUNC_CMD_COLLECT_STOP, NULL);
|
|
|
|
#if DEBUG_HWQ_SHCED_HANG
|
|
pdev_ptr->dbg_status = MAC_TX_HANG_STATUS_1;
|
|
#endif
|
|
/* stop current HW scheduler */
|
|
mac_sched_stop(vdev);
|
|
|
|
#if DEBUG_HWQ_SHCED_HANG
|
|
pdev_ptr->dbg_status = MACC_TX_HANG_STATUS_MAX;
|
|
#endif
|
|
/* TODO : stop hw tx rx */
|
|
mac_rx_all_ring_disable(pdev_ptr);
|
|
/* flush all tdma/csma queue */
|
|
mac_tx_flush_all_queue(&pdev_ptr->hwq_hdl, \
|
|
true, true);
|
|
/* stop check spur */
|
|
mac_check_spur_en(&pdev_ptr->mac_check_spur_ctxt, false);
|
|
mac_sta_period_check_spur_ctl_by_other(false);
|
|
}
|
|
vdev_del_all_peer(vdev);
|
|
/* clean up local nid and tei info */
|
|
os_mem_set(&vdev->start_cfg, 0, sizeof(vdev->start_cfg));
|
|
|
|
/* if this vdev not reduced, need init config and hw info */
|
|
if (!vdev->mac_vdev_cfg.is_reduced_vdev) {
|
|
if (mac_vdev_cfg_get_node_role(vdev) != PLC_DEV_ROLE_CCO) {
|
|
/* if not CCO */
|
|
vdev_reset_nid(vdev);
|
|
vdev_set_tei(vdev, PLC_TEI_INVAL);
|
|
vdev->l_phase1 = PLC_PHASE_ALL;
|
|
vdev->l_phase2 = PLC_PHASE_ALL;
|
|
vdev->l_phase3 = PLC_PHASE_ALL;
|
|
|
|
/* stop the mac scan */
|
|
mac_scan_stop(&pdev_ptr->scan);
|
|
|
|
#if STATIC_POWER_SAVE
|
|
/* clear power manager status */
|
|
phy_pkt_found_flag_clr();
|
|
#endif
|
|
|
|
#if K48_STA_MULTI_CHANNEL_SELECT_ENABLE
|
|
iot_mac_k48sta_scan_channel_stop(pdev_ptr);
|
|
#endif
|
|
}
|
|
else {
|
|
/* if CCo */
|
|
}
|
|
mac_beacon_reset(&vdev->bcn_ctx);
|
|
/* set default value for auto rate */
|
|
vdev_set_fixed_rate(vdev, !RATE_ADAPTION_ENABLE);
|
|
}
|
|
|
|
vdev->is_up = 0;
|
|
|
|
/* clean up black list nid array */
|
|
vdev->nid_bl_list_cnt = 0;
|
|
os_mem_set(vdev->nid_bl_list, 0, sizeof(vdev->nid_bl_list));
|
|
|
|
#if PLC_SUPPORT_DBG_PKT_MODE
|
|
/* recover to allow send dbg pkt in rx only period */
|
|
vdev_set_block_dbg_pkt_4_rx_only(vdev, false);
|
|
#endif
|
|
/* if this vdev not reduced, need init config and hw info */
|
|
if (!vdev->mac_vdev_cfg.is_reduced_vdev) {
|
|
uint32_t tmp_ts = 0;
|
|
uint32_t tmp_ntb = 0;
|
|
if (vdev->sta_joined) {
|
|
tmp_ts = iot_gp_timer_get_curr_ts();
|
|
tmp_ntb = mac_sched_get_ntb(NULL);
|
|
}
|
|
|
|
/* mac reinit */
|
|
mac_reinit(MAC_RST_REASON_COLD, PHY_PROTO_TYPE_GET(),
|
|
phy_band_id_get(), phy_mask_id_get(), mac_rf_get_self_option(),
|
|
mac_rf_get_self_channel());
|
|
|
|
if (mac_vdev_cfg_get_node_role(vdev) == PLC_DEV_ROLE_CCO &&
|
|
vdev->sta_joined) {
|
|
tmp_ts = iot_gp_timer_get_curr_ts() - tmp_ts;
|
|
/* convert us to ntb */
|
|
tmp_ts *= 25;
|
|
/* fix hplc+rf test bed, PHY clock and network time sync case fail.
|
|
* even if the vdev is restarted, NTB needs to be maintained,
|
|
* otherwise the test case will fail
|
|
*/
|
|
mac_sched_sync_ntb(vdev, MAC_SCHED_GOLDEN_GAP,
|
|
tmp_ntb + tmp_ts);
|
|
}
|
|
|
|
/* sync ppm restart */
|
|
vdev_reset_ppm_sync(vdev);
|
|
|
|
/* reinit ppm */
|
|
mac_ppm_init(&vdev->mac_ppm, phy_get_cal_ppm_in_pib(), 0);
|
|
mac_scan_init(pdev_ptr, true);
|
|
|
|
/* reset power cap */
|
|
mac_fix_power_init(vdev);
|
|
|
|
if (g_phy_cpu_share_ctxt.tx_pwr_ctl_ena == 0) {
|
|
vdev->fixed_power_cap_flag = 0;
|
|
phy_pwr_adjust_set(0);
|
|
}
|
|
|
|
#if MAC_STREAM_TIMEOUT_SUPPORT
|
|
if(vdev->stream_timeout_timer)
|
|
{
|
|
os_stop_timer(vdev->stream_timeout_timer);
|
|
mac_clean_msg(MAC_MSG_TYPE_TIMER, MAC_MSG_ID_DEL_STREAM_TIMER);
|
|
}
|
|
#endif
|
|
#if CERT_WAR_TX_PWR == 1
|
|
vdev->cert_war_pwr = 0;
|
|
#endif
|
|
|
|
#if STATIC_POWER_SAVE
|
|
/* stop timer and deep sleep */
|
|
mac_pm_stop(pdev_ptr);
|
|
sleep(DEEP_SLEEP_LEVEL_1);
|
|
pdev_ptr->mac_pm.fc_ok_pm = 0;
|
|
#endif
|
|
mac_ppm_record_timer_stop(&vdev->mac_ppm);
|
|
}
|
|
|
|
vdev->sta_joined = 0;
|
|
vdev->tx_rx_suspend = 0;
|
|
vdev->opposite_3ps = 0;
|
|
|
|
if ((PLC_INV_DBG_PKT_MODE_VDEV_ID != pdev_ptr->dbg_pkt_vdev_id) \
|
|
&& (vdev_id != pdev_ptr->dbg_pkt_vdev_id)) {
|
|
mac_stop_vdev_internal(pdev_id, (uint8_t)pdev_ptr->dbg_pkt_vdev_id);
|
|
}
|
|
|
|
/* maby nid = 0 stream exist, so need wait all vdev free,
|
|
* can check peer and stream
|
|
*/
|
|
mac_check_peer_stream_desc();
|
|
|
|
if (vdev->sec_key) {
|
|
os_mem_set((uint8_t *)vdev->sec_key, 0, sizeof(mac_sec_key_t));
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
void vdev_reset_ppm_sync(mac_vdev_t *vdev)
|
|
{
|
|
IOT_ASSERT(vdev);
|
|
|
|
mac_ppm_reset_counter(&vdev->mac_ppm.ntb_record);
|
|
vdev_set_sync_proxy(vdev, PLC_TEI_INVAL);
|
|
vdev_reset_sync_nid(vdev);
|
|
|
|
#if HPLC_RF_DEV_SUPPORT
|
|
mac_pdev_t *pdev = g_mac_pdev[vdev->ref_pdev_id];
|
|
mac_rf_vdev_t *rf_vdev;
|
|
rf_vdev = get_rf_vdev_ptr(vdev->ref_pdev_id, pdev->mac_rf_pdev->rf_pdev_id,
|
|
vdev->rf_vdev_id);
|
|
mac_ppm_reset_counter(&rf_vdev->mac_rf_ppm);
|
|
#endif
|
|
}
|
|
|
|
/* find the vdev info, if no matching nid,
|
|
* return the first vdev that nid = 0
|
|
* return NULL if not found
|
|
*/
|
|
mac_vdev_t *find_vdev_by_nid(pdevid_t pid, nid_t nid)
|
|
{
|
|
uint32_t v_idx = 0;
|
|
mac_vdev_t *first_vdev = NULL, *vdev;
|
|
nid_t my_nid;
|
|
|
|
for (v_idx = 0; v_idx < MAX_VDEV_NUM; v_idx++)
|
|
{
|
|
vdev = g_mac_pdev[pid]->vdev[v_idx];
|
|
if (vdev) {
|
|
/* if the nid is set and match the request nid */
|
|
if (ERR_OK == vdev_get_nid(vdev, &my_nid)) {
|
|
if (my_nid == nid) {
|
|
return vdev;
|
|
} else {
|
|
/* NOTE: fix bug for beijin chaokongqi.
|
|
* Cvg will set nid to mac when receive beacon
|
|
* in beijin chaokongqi mode. So if the package is already
|
|
* hanging on Q, but it hasn't been sent out yet.
|
|
* At this time, cvg received a beacon
|
|
* and set the NID to mac. Mac can't get vdev
|
|
* in the complete interrupt, it will crash here.
|
|
*/
|
|
if (vdev->mac_vdev_cfg.is_reduced_vdev &&
|
|
nid == PLC_DBG_PKT_MODE_NID) {
|
|
return vdev;
|
|
}
|
|
continue;
|
|
}
|
|
} else {
|
|
/* if the vdev's nid is not set
|
|
* not matter CCo or STA, return the first vdev
|
|
* anyway, because all the packets need be uploaded
|
|
*/
|
|
if (NULL == first_vdev) {
|
|
first_vdev = vdev;
|
|
}
|
|
}
|
|
} // if (vdev)
|
|
} // for
|
|
return first_vdev;
|
|
}
|
|
|
|
/* associate a vdev and a peer */
|
|
uint32_t vdev_add_peer(mac_vdev_t *vdev, void *peer)
|
|
{
|
|
if (!vdev || !peer)
|
|
{
|
|
return ERR_INVAL;
|
|
}
|
|
mac_peer_t *tmp = (mac_peer_t *)peer;
|
|
if (tmp->is_self_peer) {
|
|
IOT_ASSERT(vdev->self_peer == NULL);
|
|
vdev->self_peer = tmp;
|
|
}
|
|
else if (tmp->is_bcast_peer) {
|
|
IOT_ASSERT(vdev->bcast_peer == NULL);
|
|
vdev->bcast_peer = tmp;
|
|
}
|
|
else
|
|
{
|
|
/* insert this peer before the head */
|
|
if (vdev->peer_list) {
|
|
iot_list_add_prev(&tmp->vdev_node, vdev->peer_list);
|
|
}
|
|
else {
|
|
vdev->peer_list = &tmp->vdev_node;
|
|
}
|
|
}
|
|
return ERR_OK;
|
|
}
|
|
|
|
uint32_t vdev_del_peer(mac_vdev_t *vdev, void *peer)
|
|
{
|
|
mac_peer_t *tmp = (mac_peer_t *)peer;
|
|
IOT_ASSERT(get_vdev_ptr(tmp->pdev_id, tmp->vdev_id) == vdev);
|
|
if (tmp->is_self_peer == 1) {
|
|
IOT_ASSERT(vdev->self_peer == tmp);
|
|
}
|
|
else if (tmp->is_bcast_peer == 1) {
|
|
IOT_ASSERT(vdev->bcast_peer == tmp);
|
|
}
|
|
else {
|
|
if (tmp->vdev_node.next == &tmp->vdev_node) {
|
|
vdev->peer_list = NULL;
|
|
}
|
|
else {
|
|
vdev->peer_list = tmp->vdev_node.next;
|
|
iot_list_del(&tmp->vdev_node);
|
|
}
|
|
}
|
|
return ERR_OK;
|
|
}
|
|
|
|
uint32_t vdev_del_all_peer(mac_vdev_t *vdev)
|
|
{
|
|
IOT_ASSERT(vdev);
|
|
if (vdev->self_peer) {
|
|
mac_peer_free(vdev, vdev->self_peer);
|
|
}
|
|
if (vdev->bcast_peer) {
|
|
mac_peer_free(vdev, vdev->bcast_peer);
|
|
}
|
|
for(uint32_t i = 0; i < PLC_MAC_PEER_POOL_SIZE; i++){
|
|
if(vdev->peer_list == NULL){
|
|
break;
|
|
}
|
|
mac_peer_t *tmp = iot_list_entry(vdev->peer_list, \
|
|
mac_peer_t, vdev_node);
|
|
mac_peer_free(vdev, tmp);
|
|
}
|
|
mac_tei_map_reset((mac_tei_map_t *)vdev->sub_peer_bitmap);
|
|
#if 0 //TODO: will replace check logic
|
|
IOT_ASSERT(g_mac_desc_eng.used[PLC_MAC_STREAM_POOL] == 0);
|
|
/* vdev->self peer + vdev->bcast peer */
|
|
IOT_ASSERT(g_mac_desc_eng.used[PLC_MAC_PEER_POOL] == 2);
|
|
#endif
|
|
return ERR_OK;
|
|
}
|
|
|
|
uint32_t mac_vdev_sort_peer_list(mac_vdev_t *vdev, void *peer)
|
|
{
|
|
iot_list_head_t *entry = &((mac_peer_t *)peer)->vdev_node;
|
|
if(vdev == NULL || peer == NULL || \
|
|
vdev->peer_list == NULL || entry == NULL)
|
|
return 1;
|
|
if(((mac_peer_t *)peer)->is_bcast_peer || \
|
|
((mac_peer_t *)peer)->is_self_peer)
|
|
return 1;
|
|
/*
|
|
* 1. if peer is not head node,
|
|
* del this peer, and insert to head node before.
|
|
* 2. if peer is the head node,
|
|
* make the head node point the head node next node.
|
|
* the purpose is that make the head node point the oldest node.
|
|
*/
|
|
if(entry != vdev->peer_list)
|
|
{
|
|
//sort peer, newest on the tail
|
|
iot_list_del(entry);
|
|
iot_list_add_prev(entry, vdev->peer_list);
|
|
}
|
|
else
|
|
{
|
|
if(vdev->peer_list)
|
|
{
|
|
vdev->peer_list = vdev->peer_list->next;
|
|
}
|
|
}
|
|
|
|
#if DEBUG_STREAM_TIMEOUT
|
|
//printf the node
|
|
iot_list_head_t *entry1 = vdev->peer_list;
|
|
mac_peer_t *tmp2 = iot_list_entry(entry1, mac_peer_t, vdev_node);
|
|
iot_printf("%s, list %d,tei:%d, peer is %p, ntb:0x%x\n", __FUNCTION__,\
|
|
0, tmp2->tei,tmp2, tmp2->rate_info.last_rx_ts);
|
|
|
|
uint32_t i = 1;
|
|
iot_list_head_t *head = vdev->peer_list->next;
|
|
while(head != vdev->peer_list)
|
|
{
|
|
mac_peer_t *tmp1 = iot_list_entry(head, mac_peer_t, vdev_node);
|
|
iot_printf("%s, list %d,tei:%d, peer is %p, ntb:0x%x\n", __FUNCTION__,\
|
|
i, tmp1->tei, tmp1, tmp1->rate_info.last_rx_ts);
|
|
head = head->next;
|
|
i++;
|
|
}
|
|
#endif
|
|
return 0;
|
|
}
|
|
|
|
void mac_vdev_del_timeout_stream_internal(void *data, uint32_t judge_time)
|
|
{
|
|
mac_vdev_t *vdev = (mac_vdev_t *)data;
|
|
IOT_ASSERT(vdev);
|
|
uint32_t cur_ts = os_boot_time32();
|
|
iot_list_head_t *node_old = vdev->peer_list;
|
|
iot_list_head_t *tmp_node;
|
|
mac_peer_t *tmp_peer;
|
|
uint32_t cur_free_cnt, total_free_cnt;
|
|
|
|
tmp_node = node_old;
|
|
total_free_cnt = 0;
|
|
while (1) {
|
|
tmp_peer = iot_list_entry(tmp_node, mac_peer_t, vdev_node);
|
|
if (judge_time) {
|
|
if ((uint32_t)(cur_ts - tmp_peer->rate_info.last_rx_ts)
|
|
< MAC_RX_STREAM_TIMEOUT_MS) {
|
|
/* not timeout */
|
|
break;
|
|
}
|
|
}
|
|
|
|
cur_free_cnt = peer_del_all_stream(tmp_peer, DEL_RX_STREAM);
|
|
#if (PLC_MAC_RX_DEBUG_LOG >= PLC_MAC_LOG_LEVEL_2)
|
|
iot_printf("%s, tei:%d, cnt:%d \n", __FUNCTION__,
|
|
tmp_peer->tei, cur_free_cnt);
|
|
#endif
|
|
/* updata the ntb and sort peer again */
|
|
mac_vdev_sort_peer_list(vdev, tmp_peer);
|
|
|
|
total_free_cnt += cur_free_cnt;
|
|
if (cur_free_cnt && !judge_time) {
|
|
break;
|
|
}
|
|
tmp_node = tmp_node->next;
|
|
if (tmp_node == node_old) {
|
|
if (!judge_time) {
|
|
/* all of peer stream not free, assert dump */
|
|
mac_stream_exhausted_dump(tmp_peer);
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
iot_printf("del_timeout_str. judge:%d, cnt:%u\n",
|
|
judge_time, total_free_cnt);
|
|
mac_add_timeout_stream_del_cnt();
|
|
}
|
|
|
|
void mac_vdev_del_overflow_peer(mac_vdev_t *vdev)
|
|
{
|
|
if(!vdev || !vdev->peer_list) {
|
|
return;
|
|
}
|
|
|
|
iot_list_head_t *node = vdev->peer_list;
|
|
mac_peer_t *peer = NULL;
|
|
|
|
for (uint8_t i = 0; i < 2; i++) {
|
|
peer = iot_list_entry(node, mac_peer_t, vdev_node);
|
|
if (ERR_OK == mac_peer_del_overflow_peer(peer)) {
|
|
return;
|
|
}
|
|
node = node->next;
|
|
}
|
|
iot_printf("del overflow peer failed\n");
|
|
mac_add_overflow_peer_del_cnt(PEER_FAIL);
|
|
}
|
|
|
|
void mac_vdev_del_timeout_stream(timer_id_t timer_id, void *arg)
|
|
{
|
|
(void)timer_id;
|
|
mac_vdev_t *vdev = (mac_vdev_t *)arg;
|
|
if(vdev == NULL || vdev->peer_list == NULL) {
|
|
return;
|
|
}
|
|
|
|
mac_msg_t *msg = mac_alloc_msg();
|
|
if (msg == NULL) {
|
|
IOT_ASSERT(0);
|
|
return;
|
|
}
|
|
|
|
msg->type = MAC_MSG_TYPE_TIMER;
|
|
msg->id = MAC_MSG_ID_DEL_STREAM_TIMER;
|
|
msg->data1 = true;
|
|
msg->data2 = (void *)vdev;
|
|
mac_queue_msg(msg, MAC_MSG_QUEUE_LP);
|
|
}
|
|
|
|
/* get vdev's nid */
|
|
uint32_t IRAM_ATTR vdev_get_nid(mac_vdev_t *vdev, nid_t *nid)
|
|
{
|
|
if ((NULL == vdev) || (NULL == nid)) {
|
|
IOT_ASSERT(0);
|
|
return ERR_FAIL;
|
|
}
|
|
|
|
if (vdev->bcn_ctx.nid_inited) {
|
|
*nid = vdev->bcn_ctx.fc.nid;
|
|
|
|
return ERR_OK;
|
|
} else {
|
|
*nid = PLC_NID_INVALID;
|
|
return ERR_FAIL;
|
|
}
|
|
}
|
|
|
|
/* reset vdev's nid */
|
|
void vdev_reset_nid(mac_vdev_t *vdev)
|
|
{
|
|
if (vdev == NULL) {
|
|
IOT_ASSERT(0);
|
|
return;
|
|
}
|
|
|
|
vdev->bcn_ctx.nid_inited = 0;
|
|
vdev->bcn_ctx.fc.nid = PLC_NID_INVALID;
|
|
}
|
|
|
|
/* set vdev's nid */
|
|
void vdev_set_nid(mac_vdev_t *vdev, uint32_t nid)
|
|
{
|
|
mac_rf_pdev_t *rf_pdev = NULL;
|
|
mac_rf_vdev_t *rf_vdev = NULL;
|
|
if (vdev == NULL) {
|
|
IOT_ASSERT(0);
|
|
return;
|
|
}
|
|
rf_pdev = get_rf_pdev_ptr(PLC_PDEV_ID, RF_PDEV_ID);
|
|
if (rf_pdev) {
|
|
rf_vdev = get_rf_vdev_ptr(vdev->ref_pdev_id, rf_pdev->rf_pdev_id,
|
|
vdev->rf_vdev_id);
|
|
}
|
|
|
|
nid = mac_mask_input_nid(nid);
|
|
|
|
/* reduced vdev, not set pdev and hw info */
|
|
if (vdev->mac_vdev_cfg.is_reduced_vdev) {
|
|
vdev->bcn_ctx.fc.nid = nid;
|
|
vdev->bcn_ctx.nid_inited = 1;
|
|
return;
|
|
}
|
|
|
|
/* clear old nid and free mem */
|
|
if (nid != PLC_NID_INVALID && vdev->bcn_ctx.fc.nid != PLC_NID_INVALID && \
|
|
nid != vdev->bcn_ctx.fc.nid && vdev->bcn_ctx.nid_inited == 1) {
|
|
iot_printf("clear old nid=0x%x\n", vdev->bcn_ctx.fc.nid);
|
|
/* stop current HW scheduler */
|
|
mac_sched_stop(vdev);
|
|
|
|
/* rf schedule stop */
|
|
mac_rf_sched_stop(rf_vdev);
|
|
|
|
/* flush all tdma/csma queue */
|
|
vdev->stop_flag = 1;
|
|
mac_tx_flush_all_queue(&g_mac_pdev[vdev->ref_pdev_id]->hwq_hdl, \
|
|
true, true);
|
|
vdev->stop_flag = 0;
|
|
|
|
if (rf_pdev) {
|
|
/* flush all tdma/csma rf queue */
|
|
mac_rf_tx_flush_all_queue(&rf_pdev->hwq_hdl);
|
|
}
|
|
|
|
/* del peer and stream */
|
|
vdev_del_all_peer(vdev);
|
|
vdev->bcn_ctx.nid_inited = 0;
|
|
vdev->bcn_ctx.fc.nid = PLC_NID_INVALID;
|
|
mac_config_nid(vdev, PLC_NID_INVALID);
|
|
}
|
|
|
|
if (nid != PLC_NID_INVALID && \
|
|
vdev->bcn_ctx.nid_inited == 0) {
|
|
vdev->bcn_ctx.fc.nid = nid;
|
|
vdev->bcn_ctx.nid_inited = 1;
|
|
mac_config_nid(vdev, nid);
|
|
iot_printf("set nid=0x%x\n", nid);
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
uint32_t vdev_is_bl_nid(mac_vdev_t *vdev, uint32_t nid)
|
|
{
|
|
uint8_t i;
|
|
|
|
if (NULL == vdev) {
|
|
IOT_ASSERT(0);
|
|
return 0;
|
|
}
|
|
nid = mac_mask_input_nid(nid);
|
|
|
|
for (i = 0; i < vdev->nid_bl_list_cnt; i++) {
|
|
vdev->nid_bl_list[i] = mac_mask_input_nid(vdev->nid_bl_list[i]);
|
|
if (vdev->nid_bl_list[i] == nid)
|
|
return 1;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
uint32_t vdev_get_sync_nid(mac_vdev_t *vdev, nid_t *sync_nid)
|
|
{
|
|
if ((NULL == vdev) || (NULL == sync_nid)) {
|
|
IOT_ASSERT(0);
|
|
return ERR_FAIL;
|
|
}
|
|
|
|
if (vdev->sync_nid_inited) {
|
|
*sync_nid = mac_mask_input_nid(vdev->sync_nid);
|
|
|
|
return ERR_OK;
|
|
} else {
|
|
*sync_nid = PLC_NID_INVALID;
|
|
return ERR_FAIL;
|
|
}
|
|
}
|
|
|
|
void vdev_set_sync_nid(mac_vdev_t *vdev, uint32_t nid)
|
|
{
|
|
if (vdev == NULL) {
|
|
IOT_ASSERT(0);
|
|
return;
|
|
}
|
|
nid = mac_mask_input_nid(nid);
|
|
|
|
vdev->sync_nid = nid;
|
|
vdev->sync_nid_inited = true;
|
|
iot_printf("set sync nid=0x%x\n", nid);
|
|
}
|
|
|
|
void vdev_reset_sync_nid(mac_vdev_t *vdev)
|
|
{
|
|
if (vdev == NULL) {
|
|
IOT_ASSERT(0);
|
|
return;
|
|
}
|
|
|
|
vdev->sync_nid_inited = false;
|
|
vdev->sync_nid = PLC_NID_INVALID;
|
|
}
|
|
|
|
tei_t vdev_get_sync_proxy(mac_vdev_t *vdev)
|
|
{
|
|
IOT_ASSERT(vdev);
|
|
return vdev->sync_proxy;
|
|
}
|
|
|
|
void vdev_set_sync_proxy(mac_vdev_t *vdev, tei_t proxy)
|
|
{
|
|
if (vdev == NULL) {
|
|
IOT_ASSERT(0);
|
|
return;
|
|
}
|
|
|
|
vdev->sync_proxy = proxy;
|
|
}
|
|
|
|
tei_t vdev_get_proxy_tei(mac_vdev_t *vdev)
|
|
{
|
|
IOT_ASSERT(vdev);
|
|
return vdev->proxy_tei;
|
|
}
|
|
|
|
void vdev_set_proxy_tei(mac_vdev_t *vdev, tei_t proxy_tei)
|
|
{
|
|
IOT_ASSERT(vdev);
|
|
nid_t nid;
|
|
if (ERR_OK != vdev_get_nid(vdev, &nid)) {
|
|
return;
|
|
}
|
|
mac_peer_t *peer = NULL;
|
|
if (PLC_TEI_IS_VALID(proxy_tei)) {
|
|
if (PLC_TEI_IS_VALID(vdev->proxy_tei) && vdev->proxy_tei != proxy_tei) {
|
|
peer = find_peer(vdev, nid, vdev->proxy_tei);
|
|
if (peer != NULL) {
|
|
peer->is_proxy_peer = 0;
|
|
/* free old pco peer */
|
|
mac_peer_del_temp_peer(peer);
|
|
}
|
|
}
|
|
|
|
vdev->proxy_tei = proxy_tei;
|
|
peer = find_peer(vdev, nid, proxy_tei);
|
|
/* add proxy peer */
|
|
if (peer == NULL) {
|
|
mac_peer_alloc(vdev, proxy_tei, 0, 0, 0, 1, &peer);
|
|
} else {
|
|
peer->is_proxy_peer = 1;
|
|
}
|
|
iot_printf("add proxy peer tei:%d\n", \
|
|
proxy_tei);
|
|
}
|
|
return;
|
|
}
|
|
|
|
phase_t vdev_get_logic_phase(mac_vdev_t *vdev)
|
|
{
|
|
return vdev->l_phase1;
|
|
}
|
|
|
|
void vdev_set_logic_phase(mac_vdev_t *vdev, phase_t phase)
|
|
{
|
|
IOT_ASSERT(vdev);
|
|
|
|
if (vdev->l_phase1 != phase) {
|
|
vdev->l_phase1 = phase;
|
|
}
|
|
}
|
|
|
|
void vdev_set_ra_cb(mac_vdev_t * vdev, rate_control_func_t cb)
|
|
{
|
|
IOT_ASSERT(vdev);
|
|
vdev->ra_cb = cb;
|
|
}
|
|
|
|
void vdev_set_sta_cap_phase(uint32_t proto, mac_vdev_t *vdev, uint8_t phase)
|
|
{
|
|
IOT_ASSERT(vdev);
|
|
|
|
switch (proto) {
|
|
case PLC_PROTO_TYPE_SG:
|
|
vdev->bcn_ctx.sg_uniq_bc_str.sta_cap.phase = phase;
|
|
break;
|
|
case PLC_PROTO_TYPE_SPG:
|
|
vdev->bcn_ctx.spg_uniq_bc_str.sta_cap.phase = phase;
|
|
break;
|
|
default:
|
|
IOT_ASSERT(0);
|
|
break;
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
uint32_t *vdev_get_bc_period_cnt_ptr(uint32_t proto, mac_vdev_t *vdev)
|
|
{
|
|
uint32_t *bc_ptr = NULL;
|
|
|
|
IOT_ASSERT(vdev);
|
|
|
|
switch (proto) {
|
|
case PLC_PROTO_TYPE_SG:
|
|
bc_ptr = \
|
|
&vdev->bcn_ctx.sg_uniq_bc_str.payload_header.bc_period_cnt;
|
|
break;
|
|
case PLC_PROTO_TYPE_SPG:
|
|
bc_ptr = \
|
|
&vdev->bcn_ctx.fc.bp_cnt;
|
|
break;
|
|
default:
|
|
IOT_ASSERT(0);
|
|
bc_ptr = NULL;
|
|
break;
|
|
}
|
|
|
|
return bc_ptr;
|
|
}
|
|
|
|
uint32_t vdev_get_bc_period_cnt(uint32_t proto, mac_vdev_t *vdev)
|
|
{
|
|
IOT_ASSERT(vdev);
|
|
|
|
uint32_t beacon_period_cnt = 0;
|
|
switch (proto) {
|
|
case PLC_PROTO_TYPE_SG:
|
|
beacon_period_cnt = \
|
|
vdev->bcn_ctx.sg_uniq_bc_str.payload_header.bc_period_cnt;
|
|
break;
|
|
case PLC_PROTO_TYPE_SPG:
|
|
beacon_period_cnt = \
|
|
vdev->bcn_ctx.fc.bp_cnt;
|
|
break;
|
|
default:
|
|
IOT_ASSERT(0);
|
|
break;
|
|
}
|
|
|
|
return beacon_period_cnt;
|
|
}
|
|
|
|
uint32_t vdev_set_fixed_rate(mac_vdev_t *vdev, uint8_t flag)
|
|
{
|
|
IOT_ASSERT(vdev);
|
|
vdev->fixed_rate_flag = !!flag;
|
|
|
|
/* for cert test WAR start */
|
|
if (mac_vdev_cfg_get_node_role(vdev) == PLC_DEV_ROLE_CCO &&
|
|
mac_get_cert_test_flag()) {
|
|
/* disable swagc */
|
|
phy_swagc_set(false);
|
|
}
|
|
/* for cert test WAR end */
|
|
|
|
return 0;
|
|
}
|
|
|
|
uint32_t vdev_get_fixed_rate(mac_vdev_t *vdev)
|
|
{
|
|
IOT_ASSERT(vdev);
|
|
return vdev->fixed_rate_flag;
|
|
}
|
|
|
|
uint32_t vdev_set_fixed_rate_level(mac_vdev_t *vdev, uint8_t rate_level)
|
|
{
|
|
IOT_ASSERT(vdev);
|
|
if (rate_level > PLC_RATE_ADAPT_RATE_HIGH) {
|
|
iot_printf("up layer set rate level:%d err, will use low level!\n",
|
|
rate_level);
|
|
rate_level = PLC_RATE_ADAPT_RATE_LOW;
|
|
}
|
|
vdev->rate_level = rate_level;
|
|
return 0;
|
|
}
|
|
|
|
uint32_t vdev_get_fixed_rate_level(mac_vdev_t *vdev)
|
|
{
|
|
IOT_ASSERT(vdev);
|
|
return vdev->rate_level;
|
|
}
|
|
|
|
uint8_t mac_vdev_cfg_get_node_role(mac_vdev_t *vdev)
|
|
{
|
|
IOT_ASSERT(vdev);
|
|
return (uint8_t)(vdev->mac_vdev_cfg.node_role);
|
|
}
|
|
|
|
uint32_t vdev_get_bc_period_ms(mac_vdev_t *vdev, uint32_t proto)
|
|
{
|
|
IOT_ASSERT(vdev);
|
|
/* TODO: for spg, may be different */
|
|
(void)proto;
|
|
return vdev->bcn_ctx.time_slot.bc_period;
|
|
}
|
|
|
|
uint32_t vdev_set_block_dbg_pkt_4_rx_only(mac_vdev_t *vdev, uint32_t block)
|
|
{
|
|
IOT_ASSERT(vdev);
|
|
mac_pdev_t *pdev = g_mac_pdev[vdev->ref_pdev_id];
|
|
uint8_t vdev_id;
|
|
mac_vdev_t *find_vdev;
|
|
for (vdev_id = 0; vdev_id < pdev->cur_vdev_num; vdev_id++) {
|
|
find_vdev = pdev->vdev[vdev_id];
|
|
if (find_vdev) {
|
|
find_vdev->block_dbg_pkt_4_rx_only = !!block;
|
|
}
|
|
}
|
|
|
|
return ERR_OK;
|
|
}
|
|
|
|
uint32_t vdev_get_block_dbg_pkt_4_rx_only(mac_vdev_t *vdev)
|
|
{
|
|
IOT_ASSERT(vdev);
|
|
return vdev->block_dbg_pkt_4_rx_only;
|
|
}
|
|
|
|
uint32_t mac_get_reduce_vdev_id(uint32_t pdev_id)
|
|
{
|
|
if (pdev_id >= MAX_PDEV_NUM) {
|
|
IOT_ASSERT(0);
|
|
}
|
|
|
|
return g_mac_pdev[pdev_id]->dbg_pkt_vdev_id;
|
|
}
|
|
|
|
void mac_vdev_war_rx_abort_init(void)
|
|
{
|
|
mac_pdev_t *pdev = get_pdev_ptr(PLC_PDEV_ID);
|
|
|
|
#if SUPPORT_SOUTHERN_POWER_GRID
|
|
uint8_t user_type = iot_oem_get_user_type();
|
|
/* WAR for guangxi spg cert */
|
|
if ((os_boot_time32() < 40000)
|
|
&& ((USER_TYPE_SOUTHEN_POWER_GRID_GX_NW21 == user_type)
|
|
|| (USER_TYPE_SOUTHEN_POWER_GRID_GUIZHOU == user_type))) {
|
|
pdev->rx_abort_rst_cnt = 0;
|
|
pdev->rx_abort_spg_war_cnt = 0;
|
|
} else
|
|
#endif
|
|
{
|
|
/* disable war */
|
|
pdev->rx_abort_rst_cnt = 255;
|
|
pdev->rx_abort_spg_war_cnt = 255;
|
|
}
|
|
}
|