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;
 | |
|     }
 | |
| }
 |