594 lines
		
	
	
		
			19 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
		
		
			
		
	
	
			594 lines
		
	
	
		
			19 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 "beacon_frame.h"
							 | 
						||
| 
								 | 
							
								#include "beacon.h"
							 | 
						||
| 
								 | 
							
								#include "iot_errno.h"
							 | 
						||
| 
								 | 
							
								#include "iot_io.h"
							 | 
						||
| 
								 | 
							
								#include "mac_bcm_api.h"
							 | 
						||
| 
								 | 
							
								#include "mpdu_frame.h"
							 | 
						||
| 
								 | 
							
								#include "mac_tx_hw.h"
							 | 
						||
| 
								 | 
							
								#include "mac_data_api.h"
							 | 
						||
| 
								 | 
							
								#include "iot_pkt_api.h"
							 | 
						||
| 
								 | 
							
								#include "mac_data.h"
							 | 
						||
| 
								 | 
							
								#include "os_mem.h"
							 | 
						||
| 
								 | 
							
								#include "mac_desc_engine.h"
							 | 
						||
| 
								 | 
							
								#include "plc_mac_header.h"
							 | 
						||
| 
								 | 
							
								#include "hw_tonemap.h"
							 | 
						||
| 
								 | 
							
								#include "iot_crc.h"
							 | 
						||
| 
								 | 
							
								#include "iot_utils.h"
							 | 
						||
| 
								 | 
							
								#include "mac_msg.h"
							 | 
						||
| 
								 | 
							
								#include "mac.h"
							 | 
						||
| 
								 | 
							
								#include "mac_crc.h"
							 | 
						||
| 
								 | 
							
								#include "iot_bitops.h"
							 | 
						||
| 
								 | 
							
								#include "mac_peer.h"
							 | 
						||
| 
								 | 
							
								#include "rate_control.h"
							 | 
						||
| 
								 | 
							
								#include "hw_desc.h"
							 | 
						||
| 
								 | 
							
								#include "mac_stream.h"
							 | 
						||
| 
								 | 
							
								#include "sw_sched.h"
							 | 
						||
| 
								 | 
							
								#include "iot_module.h"
							 | 
						||
| 
								 | 
							
								#include "phy_bb.h"
							 | 
						||
| 
								 | 
							
								#include "plc_mac_cfg.h"
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#if CPLC_IOT_CERT_SUPPORT
							 | 
						||
| 
								 | 
							
								#include "mac_cert_test.h"
							 | 
						||
| 
								 | 
							
								#include "plc_cert_test.h"
							 | 
						||
| 
								 | 
							
								#endif
							 | 
						||
| 
								 | 
							
								#include "iot_dbglog_api.h"
							 | 
						||
| 
								 | 
							
								#include "iot_dbglog_parser.h"
							 | 
						||
| 
								 | 
							
								#include "mac_pm.h"
							 | 
						||
| 
								 | 
							
								#include "mac_pdev.h"
							 | 
						||
| 
								 | 
							
								#include "mac_status.h"
							 | 
						||
| 
								 | 
							
								#include "mac_mm_sniffer.h"
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#if SUPPORT_IEEE_1901
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								static void mac_data_msdu_i1901_to_sg(iot_pkt_t *src_msdu)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								    uint8_t *data, *tmp_addr;
							 | 
						||
| 
								 | 
							
								    mac_rx_info_t *src_rx_info, tmp_rx_info;
							 | 
						||
| 
								 | 
							
								    i1901_mac_header_t *i1901_mac_hdr;
							 | 
						||
| 
								 | 
							
								    frame_control_t *sg_fc;
							 | 
						||
| 
								 | 
							
								    uint8_t buff[MAC_HDR_LEN_WITH_ADDR] = {0};
							 | 
						||
| 
								 | 
							
								    mac_header_t *sg_mac_hdr = (mac_header_t *)buff;
							 | 
						||
| 
								 | 
							
								    uint8_t sg_mac_hdr_len;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    data = iot_pkt_data(src_msdu);
							 | 
						||
| 
								 | 
							
								    src_rx_info = (mac_rx_info_t *)(data - sizeof(*src_rx_info));
							 | 
						||
| 
								 | 
							
								    os_mem_cpy(&tmp_rx_info, src_rx_info, sizeof(mac_rx_info_t));
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    i1901_mac_hdr = (i1901_mac_header_t *)data;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    uint32_t i1901_hdr_len;
							 | 
						||
| 
								 | 
							
								    if (i1901_mac_hdr_var_is_valid(i1901_mac_hdr)) {
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        sg_mac_hdr->org_src_tei = (uint16_t)i1901_mac_hdr->var[0].org_src_tei;
							 | 
						||
| 
								 | 
							
								        sg_mac_hdr->org_dest_tei = (uint16_t)i1901_mac_hdr->var[0].org_dest_tei;
							 | 
						||
| 
								 | 
							
								        sg_mac_hdr->total_hop_cnt = (uint8_t)i1901_mac_hdr->var[0].total_hop_cnt;
							 | 
						||
| 
								 | 
							
								        sg_mac_hdr->rest_hop_cnt = (uint8_t)i1901_mac_hdr->var[0].rest_hop_cnt;
							 | 
						||
| 
								 | 
							
								        sg_mac_hdr->main_path_flag = (uint16_t)i1901_mac_hdr->var[0].main_path_flag;
							 | 
						||
| 
								 | 
							
								        sg_mac_hdr->bc_direction = (uint16_t)i1901_mac_hdr->var[0].bc_direction;
							 | 
						||
| 
								 | 
							
								        sg_mac_hdr->network_sn = (uint8_t)i1901_mac_hdr->var[0].network_sn;
							 | 
						||
| 
								 | 
							
								#if PLC_SILA_NHM_ENABLE
							 | 
						||
| 
								 | 
							
								        sg_mac_hdr->mac_exist_flag = (uint8_t)i1901_mac_hdr->var[0].mac_exist_flag;
							 | 
						||
| 
								 | 
							
								#else
							 | 
						||
| 
								 | 
							
								        sg_mac_hdr->mac_exist_flag = 0;
							 | 
						||
| 
								 | 
							
								#endif
							 | 
						||
| 
								 | 
							
								        if (sg_mac_hdr->mac_exist_flag) {
							 | 
						||
| 
								 | 
							
								            i1901_hdr_len = MAC_HDR_LEN_WITH_VAR_ADDR_I1901;
							 | 
						||
| 
								 | 
							
								            sg_mac_hdr_len = MAC_HDR_LEN_WITH_ADDR;
							 | 
						||
| 
								 | 
							
								            tmp_addr = data + sizeof(i1901_mac_header_t) +
							 | 
						||
| 
								 | 
							
								                sizeof(i1901_mac_header_var_t);
							 | 
						||
| 
								 | 
							
								            os_mem_cpy(sg_mac_hdr->mac[0], tmp_addr, IOT_MAC_ADDR_LEN * 2);
							 | 
						||
| 
								 | 
							
								        } else {
							 | 
						||
| 
								 | 
							
								            i1901_hdr_len = MAC_HDR_LEN_WITH_VAR_I1901;
							 | 
						||
| 
								 | 
							
								            sg_mac_hdr_len = MAC_HDR_LEN_NO_ADDR;
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								    } else {
							 | 
						||
| 
								 | 
							
								        i1901_hdr_len = MAC_HDR_LEN_NO_VAR_I1901;
							 | 
						||
| 
								 | 
							
								        sg_mac_hdr_len = MAC_HDR_LEN_NO_ADDR;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        sg_fc = (frame_control_t *)src_rx_info->fc;
							 | 
						||
| 
								 | 
							
								        sg_mac_hdr->org_src_tei = (uint16_t)sg_fc->vf.sof.src_tei;
							 | 
						||
| 
								 | 
							
								        sg_mac_hdr->org_dest_tei = (uint16_t)sg_fc->vf.sof.dst_tei;
							 | 
						||
| 
								 | 
							
								        sg_mac_hdr->total_hop_cnt = 0;
							 | 
						||
| 
								 | 
							
								        sg_mac_hdr->rest_hop_cnt = 0;
							 | 
						||
| 
								 | 
							
								        sg_mac_hdr->main_path_flag = 0;
							 | 
						||
| 
								 | 
							
								        sg_mac_hdr->bc_direction = 0;
							 | 
						||
| 
								 | 
							
								        sg_mac_hdr->network_sn = 0;
							 | 
						||
| 
								 | 
							
								        sg_mac_hdr->mac_exist_flag = 0;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    sg_mac_hdr->version = i1901_mac_hdr->version;
							 | 
						||
| 
								 | 
							
								    sg_mac_hdr->send_type = i1901_mac_hdr->send_type;
							 | 
						||
| 
								 | 
							
								    sg_mac_hdr->send_max_cnt = i1901_mac_hdr->send_max_cnt;
							 | 
						||
| 
								 | 
							
								    sg_mac_hdr->msdu_sn = i1901_mac_hdr->msdu_sn;
							 | 
						||
| 
								 | 
							
								    sg_mac_hdr->msdu_type = i1901_mac_hdr->msdu_type;
							 | 
						||
| 
								 | 
							
								    sg_mac_hdr->msdu_len = i1901_mac_hdr->msdu_len;
							 | 
						||
| 
								 | 
							
								    sg_mac_hdr->reboot_cnt = i1901_mac_hdr->reboot_cnt;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    sg_mac_hdr->path_fix_flag = 0; /* ieee1901 not this field */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    /* get new mac header addr */
							 | 
						||
| 
								 | 
							
								    tmp_addr = data + i1901_hdr_len - sg_mac_hdr_len;
							 | 
						||
| 
								 | 
							
								    /* copy sg mac header into rx buffer */
							 | 
						||
| 
								 | 
							
								    os_mem_cpy(tmp_addr, sg_mac_hdr, sg_mac_hdr_len);
							 | 
						||
| 
								 | 
							
								    /* update rx buffer pkt data addr */
							 | 
						||
| 
								 | 
							
								    iot_pkt_set_data(src_msdu, tmp_addr);
							 | 
						||
| 
								 | 
							
								    /* get new rx info addr */
							 | 
						||
| 
								 | 
							
								    tmp_addr -= sizeof(mac_rx_info_t);
							 | 
						||
| 
								 | 
							
								    /* copy rx info into rx buffer */
							 | 
						||
| 
								 | 
							
								    os_mem_cpy(tmp_addr, &tmp_rx_info, sizeof(mac_rx_info_t));
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								void mac_data_msdu_sg_to_i1901(iot_pkt_t *src_msdu)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								    uint16_t sg_mac_hdr_len, i1901_mac_hdr_len;
							 | 
						||
| 
								 | 
							
								    uint8_t i1901_mac_l_hdr[MAC_HDR_LEN_WITH_VAR_ADDR_I1901] = {0};
							 | 
						||
| 
								 | 
							
								    i1901_mac_header_t *i1901_mac_hdr = (i1901_mac_header_t *)i1901_mac_l_hdr;
							 | 
						||
| 
								 | 
							
								    mac_header_t *sg_mac_hdr;
							 | 
						||
| 
								 | 
							
								    uint16_t len;
							 | 
						||
| 
								 | 
							
								    uint8_t *addr;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    sg_mac_hdr = (mac_header_t *)iot_pkt_data(src_msdu);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    sg_mac_hdr_len = sg_mac_hdr->mac_exist_flag ? MAC_HDR_LEN_WITH_ADDR
							 | 
						||
| 
								 | 
							
								        : MAC_HDR_LEN_NO_ADDR;
							 | 
						||
| 
								 | 
							
								    /* sg mac header to ieee 1901 mac header */
							 | 
						||
| 
								 | 
							
								    i1901_mac_hdr->version = I1901_MAC_HDR_STD_VER;
							 | 
						||
| 
								 | 
							
								    i1901_mac_hdr->send_type = (uint8_t)sg_mac_hdr->send_type;
							 | 
						||
| 
								 | 
							
								    i1901_mac_hdr->send_max_cnt = sg_mac_hdr->send_max_cnt;
							 | 
						||
| 
								 | 
							
								    i1901_mac_hdr->msdu_sn = sg_mac_hdr->msdu_sn;
							 | 
						||
| 
								 | 
							
								    i1901_mac_hdr->msdu_type = sg_mac_hdr->msdu_type; //TODO:
							 | 
						||
| 
								 | 
							
								    i1901_mac_hdr->msdu_len = sg_mac_hdr->msdu_len; //check max length
							 | 
						||
| 
								 | 
							
								    i1901_mac_hdr->reboot_cnt = sg_mac_hdr->reboot_cnt;
							 | 
						||
| 
								 | 
							
								#if PLC_SILA_NHM_ENABLE
							 | 
						||
| 
								 | 
							
								    i1901_mac_hdr->mac_frame_type = 1;
							 | 
						||
| 
								 | 
							
								#else
							 | 
						||
| 
								 | 
							
								    i1901_mac_hdr->mac_frame_type = 0;
							 | 
						||
| 
								 | 
							
								#endif
							 | 
						||
| 
								 | 
							
								    i1901_mac_hdr->var[0].org_src_tei = sg_mac_hdr->org_src_tei;
							 | 
						||
| 
								 | 
							
								    i1901_mac_hdr->var[0].org_dest_tei = sg_mac_hdr->org_dest_tei;
							 | 
						||
| 
								 | 
							
								    i1901_mac_hdr->var[0].total_hop_cnt = sg_mac_hdr->total_hop_cnt;
							 | 
						||
| 
								 | 
							
								    i1901_mac_hdr->var[0].rest_hop_cnt = sg_mac_hdr->rest_hop_cnt;
							 | 
						||
| 
								 | 
							
								    i1901_mac_hdr->var[0].main_path_flag = (uint8_t)sg_mac_hdr->main_path_flag;
							 | 
						||
| 
								 | 
							
								    i1901_mac_hdr->var[0].bc_direction = (uint8_t)sg_mac_hdr->bc_direction;
							 | 
						||
| 
								 | 
							
								    i1901_mac_hdr->var[0].network_sn = sg_mac_hdr->network_sn;
							 | 
						||
| 
								 | 
							
								#if PLC_SILA_NHM_ENABLE
							 | 
						||
| 
								 | 
							
								    i1901_mac_hdr->var[0].mac_exist_flag = 0; //TODO: enable filling mac addr
							 | 
						||
| 
								 | 
							
								    if (i1901_mac_hdr->var[0].mac_exist_flag) {
							 | 
						||
| 
								 | 
							
								        i1901_mac_hdr_len = MAC_HDR_LEN_WITH_VAR_ADDR_I1901;
							 | 
						||
| 
								 | 
							
								        addr = i1901_mac_l_hdr + sizeof(i1901_mac_header_t) +
							 | 
						||
| 
								 | 
							
								            sizeof(i1901_mac_header_var_t);
							 | 
						||
| 
								 | 
							
								        os_mem_cpy(addr, sg_mac_hdr->mac[0], IOT_MAC_ADDR_LEN * 2);
							 | 
						||
| 
								 | 
							
								    } else {
							 | 
						||
| 
								 | 
							
								        i1901_mac_hdr_len = MAC_HDR_LEN_WITH_VAR_I1901;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								#else
							 | 
						||
| 
								 | 
							
								    i1901_mac_hdr->var[0].mac_exist_flag = 0;
							 | 
						||
| 
								 | 
							
								    i1901_mac_hdr_len = MAC_HDR_LEN_WITH_VAR_I1901;
							 | 
						||
| 
								 | 
							
								#endif
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    if (i1901_mac_hdr_len > sg_mac_hdr_len) {
							 | 
						||
| 
								 | 
							
								        len = i1901_mac_hdr_len - sg_mac_hdr_len;
							 | 
						||
| 
								 | 
							
								        IOT_ASSERT(iot_pkt_block_len(src_msdu, IOT_PKT_BLOCK_HEAD) >=
							 | 
						||
| 
								 | 
							
								            (sizeof(mac_tx_info) + sizeof(frame_control_t) + len));
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        addr = iot_pkt_push(src_msdu, len);
							 | 
						||
| 
								 | 
							
								    } else {
							 | 
						||
| 
								 | 
							
								        len = sg_mac_hdr_len - i1901_mac_hdr_len;
							 | 
						||
| 
								 | 
							
								        addr = iot_pkt_pull(src_msdu, len);
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    os_mem_cpy(addr, i1901_mac_hdr, i1901_mac_hdr_len);
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#else /* SUPPORT_IEEE_1901 */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#define mac_data_msdu_i1901_to_sg(src_msdu)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#define mac_data_msdu_sg_to_i1901(src_msdu)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#endif /* SUPPORT_IEEE_1901 */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								uint32_t mac_data_rx_msdu(mac_vdev_t *vdev, iot_pkt_t *msdu_buf)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								    uint8_t *data;
							 | 
						||
| 
								 | 
							
								    uint8_t *msdu_crc_ptr = NULL;
							 | 
						||
| 
								 | 
							
								    uint32_t msdu_crc_old;
							 | 
						||
| 
								 | 
							
								    uint8_t  proto = (uint8_t)PHY_PROTO_TYPE_GET();
							 | 
						||
| 
								 | 
							
								    uint16_t msdu = 0;
							 | 
						||
| 
								 | 
							
								    uint16_t mac_hdr_len = 0;
							 | 
						||
| 
								 | 
							
								    IOT_ASSERT(vdev && msdu_buf);
							 | 
						||
| 
								 | 
							
								    mac_add_rx_msdu_cnt();
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    /*check crc*/
							 | 
						||
| 
								 | 
							
								    data = iot_pkt_data(msdu_buf);
							 | 
						||
| 
								 | 
							
								    mac_msdu_frame_info_get(proto, msdu_buf, &msdu_crc_ptr, \
							 | 
						||
| 
								 | 
							
								                    &msdu, &mac_hdr_len);
							 | 
						||
| 
								 | 
							
								    if(msdu == 0)
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								        mac_add_rx_msdu_len_is_0_cnt();
							 | 
						||
| 
								 | 
							
								        iot_printf("msdu len is 0 cnt:%d\n", mac_get_rx_msdu_len_is_0_cnt());
							 | 
						||
| 
								 | 
							
								        iot_dbglog_input(PLC_MAC_RX_HW_MID, DBGLOG_INFO,
							 | 
						||
| 
								 | 
							
								            IOT_MAC_RX_MSDU_LEN_INVALID_ID, 1, mac_get_rx_msdu_len_is_0_cnt());
							 | 
						||
| 
								 | 
							
								        iot_pkt_free(msdu_buf);
							 | 
						||
| 
								 | 
							
								        return ERR_FAIL;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								    IOT_ASSERT(msdu_crc_ptr && (mac_hdr_len > 0));
							 | 
						||
| 
								 | 
							
								    data += mac_hdr_len;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#ifndef DISABLE_SW_SOF_PAYLOAD_CRC_CHECK
							 | 
						||
| 
								 | 
							
								#if SUPPORT_IEEE_1901
							 | 
						||
| 
								 | 
							
								    uint32_t msdu_crc_new = iot_getcrc32_update(0, data, msdu);
							 | 
						||
| 
								 | 
							
								#else
							 | 
						||
| 
								 | 
							
								    uint32_t msdu_crc_new = iot_getcrc32(data, msdu);
							 | 
						||
| 
								 | 
							
								#endif
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    os_mem_cpy(&msdu_crc_old, msdu_crc_ptr, sizeof(msdu_crc_old));
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    if (msdu_crc_old != msdu_crc_new)
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								        mac_add_rx_msdu_crc_err_cnt();
							 | 
						||
| 
								 | 
							
								        iot_printf("msdu crc err cnt:%d\n", mac_get_rx_msdu_crc_err_cnt());
							 | 
						||
| 
								 | 
							
								        iot_dbglog_input(PLC_MAC_DATA_MID, DBGLOG_INFO,
							 | 
						||
| 
								 | 
							
								            IOT_MAC_RX_MSDU_CRC_CNT_ID, 1, mac_get_rx_msdu_crc_err_cnt());
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#if PLC_HW_ISSUE_ASSERT_LEVEL <= PLC_HW_ISSUE_ASSERT_ALL
							 | 
						||
| 
								 | 
							
								        /* should not happen as the pb's crc is passed */
							 | 
						||
| 
								 | 
							
								        IOT_ASSERT(0);
							 | 
						||
| 
								 | 
							
								#endif
							 | 
						||
| 
								 | 
							
								        iot_pkt_free(msdu_buf);
							 | 
						||
| 
								 | 
							
								        return ERR_FAIL;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								#endif
							 | 
						||
| 
								 | 
							
								    /* trim this iot pkt to msdu len */
							 | 
						||
| 
								 | 
							
								    IOT_ASSERT(iot_pkt_set_tail(msdu_buf, msdu_crc_ptr));
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#if ((MAC_MM_SNIFFER_MODE == MAC_SNIFFER_TYPE_MSDU) || \
							 | 
						||
| 
								 | 
							
								    ((MAC_MM_SNIFFER_MODE == MAC_SNIFFER_TYPE_MSDU_UART)))
							 | 
						||
| 
								 | 
							
								    mac_mm_sniffer_rx_msdu(proto, msdu_buf);
							 | 
						||
| 
								 | 
							
								    iot_pkt_free(msdu_buf);
							 | 
						||
| 
								 | 
							
								    return ERR_OK;
							 | 
						||
| 
								 | 
							
								#endif
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    /* convert ieee 1901 msdu data to sg */
							 | 
						||
| 
								 | 
							
								    mac_data_msdu_i1901_to_sg(msdu_buf);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#if CPLC_IOT_CERT_SUPPORT
							 | 
						||
| 
								 | 
							
								    switch (mac_get_cert_test_mode()) {
							 | 
						||
| 
								 | 
							
								    case CERT_TEST_CMD_ENTER_MAC_T:
							 | 
						||
| 
								 | 
							
								    case CERT_TEST_CMD_ENTER_SEC:
							 | 
						||
| 
								 | 
							
								        iot_printf("msdu:len%d forward to uart\n", msdu);
							 | 
						||
| 
								 | 
							
								        if(g_mt_ctxt && g_mt_ctxt->mt_msdu_tx_funt) {
							 | 
						||
| 
								 | 
							
								            g_mt_ctxt->mt_msdu_tx_funt(vdev->start_cfg.mac_callback_arg,
							 | 
						||
| 
								 | 
							
								                msdu_buf);
							 | 
						||
| 
								 | 
							
								        } else {
							 | 
						||
| 
								 | 
							
								            iot_pkt_free(msdu_buf);
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								        return 0;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    default:
							 | 
						||
| 
								 | 
							
								        break;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								#endif
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    /* upload to upper layer */
							 | 
						||
| 
								 | 
							
								#if PLC_MAC_RX_DEBUG_LOG
							 | 
						||
| 
								 | 
							
								    iot_printf("msdu len %d formed \n", msdu);
							 | 
						||
| 
								 | 
							
								    iot_dbglog_input(PLC_MAC_DATA_MID, DBGLOG_INFO,
							 | 
						||
| 
								 | 
							
								        IOT_MAC_RX_MSDU_LENGTH_ID, 1, msdu);
							 | 
						||
| 
								 | 
							
								#endif
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    if (vdev->start_cfg.mac_data_rx_func) {
							 | 
						||
| 
								 | 
							
								#if (SIMU_DBG > 3)
							 | 
						||
| 
								 | 
							
								        iot_printf("%s, msdu->buf = %p", __FUNCTION__, iot_pkt_block_ptr(msdu_buf, IOT_PKT_BLOCK_DATA));
							 | 
						||
| 
								 | 
							
								        iot_dbglog_input(PLC_MAC_DATA_MID, DBGLOG_INFO,
							 | 
						||
| 
								 | 
							
								            IOT_MAC_RX_MSDU_PTR_ID, 1, iot_pkt_block_ptr(msdu_buf, IOT_PKT_BLOCK_DATA));
							 | 
						||
| 
								 | 
							
								#endif
							 | 
						||
| 
								 | 
							
								        vdev->start_cfg.mac_data_rx_func(vdev->start_cfg.mac_callback_arg,
							 | 
						||
| 
								 | 
							
								            msdu_buf);
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								    else {
							 | 
						||
| 
								 | 
							
								        iot_pkt_free(msdu_buf);
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    return ERR_OK;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								uint32_t mac_send_msdu_ex_internal(pdevid_t pdev_id, vdevid_t vdev_id,
							 | 
						||
| 
								 | 
							
								    iot_pkt_t* msdu_buf, mac_tx_info *tx_info)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								    mac_pdev_t *pdev = get_pdev_ptr(pdev_id);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    if(pdev->mac_pm.mac_pm_flag && !tx_info->pw_collapse)
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								        iot_printf("mac entry power off mode, dorp non power_off_pkt\n");
							 | 
						||
| 
								 | 
							
								        return ERR_FAIL;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								    if(pdev->mac_pm.mac_pm_flag)
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								        iot_printf("send power_off report pkt_\n");
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								    lid_t lid = tx_info->link_id;
							 | 
						||
| 
								 | 
							
								    uint32_t bcn_region_type;
							 | 
						||
| 
								 | 
							
								    uint8_t *data = iot_pkt_data(msdu_buf);
							 | 
						||
| 
								 | 
							
								    uint8_t proto = (uint8_t)PHY_PROTO_TYPE_GET();
							 | 
						||
| 
								 | 
							
								    uint8_t retry_cnt = 0;
							 | 
						||
| 
								 | 
							
								    uint8_t l_phase;
							 | 
						||
| 
								 | 
							
								    uint8_t stream_trxn = IS_TX_STREAM;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#if PLC_SUPPORT_DBG_PKT_MODE
							 | 
						||
| 
								 | 
							
								    /* check meter dbg mode parameter valid */
							 | 
						||
| 
								 | 
							
								    if (tx_info->is_dbg_pkt) {
							 | 
						||
| 
								 | 
							
								        //check link id
							 | 
						||
| 
								 | 
							
								        if (lid > (lid_t)LID_CSMA_CAP3) {
							 | 
						||
| 
								 | 
							
								            lid = (lid_t)PLC_DBG_PKT_MODE_DEF_LID;
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								        stream_trxn = IS_DBG_TX_STREAM;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        /* fix debug pkt mode vdev id */
							 | 
						||
| 
								 | 
							
								        vdev_id = (vdevid_t)pdev->dbg_pkt_vdev_id;
							 | 
						||
| 
								 | 
							
								        IOT_ASSERT(vdev_id != (vdevid_t)PLC_INV_DBG_PKT_MODE_VDEV_ID);
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								#endif
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    mac_vdev_t *vdev = get_vdev_ptr(pdev_id, vdev_id);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    if (!vdev->is_up || vdev->stop_flag) {
							 | 
						||
| 
								 | 
							
								        iot_printf("vdev %d not ready\n", vdev_id);
							 | 
						||
| 
								 | 
							
								        return ERR_NOT_READY;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    if (vdev->tx_rx_suspend) {
							 | 
						||
| 
								 | 
							
								        return ERR_FAIL;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#if PLC_SUPPORT_DBG_PKT_MODE
							 | 
						||
| 
								 | 
							
								    if (!vdev_get_block_dbg_pkt_4_rx_only(vdev) && tx_info->is_dbg_pkt) {
							 | 
						||
| 
								 | 
							
								        lid += LID_BCSMA_START;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								#endif
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    bcn_region_type = mac_get_bcn_region_type(lid);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    /* check if has token for current sending */
							 | 
						||
| 
								 | 
							
								    if (ERR_NOMEM == mac_token_check(bcn_region_type, lid, 0)) {
							 | 
						||
| 
								 | 
							
								        iot_printf("warning:%s:no msdu for sending,lid=%d\r\n", \
							 | 
						||
| 
								 | 
							
								            __FUNCTION__, lid);
							 | 
						||
| 
								 | 
							
								        iot_dbglog_input(PLC_MAC_DATA_MID, DBGLOG_WARN,
							 | 
						||
| 
								 | 
							
								            IOT_MAC_WARING_NO_MSDU_FOR_SEND_ID, 1, lid);
							 | 
						||
| 
								 | 
							
								        mac_add_no_msdu_to_send_cnt();
							 | 
						||
| 
								 | 
							
								        return ERR_NOMEM;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    /* convert sg msdu data to ieee1901 */
							 | 
						||
| 
								 | 
							
								    mac_data_msdu_sg_to_i1901(msdu_buf);
							 | 
						||
| 
								 | 
							
								    /* put crc len */
							 | 
						||
| 
								 | 
							
								    iot_pkt_put(msdu_buf, sizeof(uint32_t));
							 | 
						||
| 
								 | 
							
								    IOT_ASSERT(ERR_OK == mac_crc_set_msdu_swcrc(proto, msdu_buf));
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    /* for sof frame, find the correct peer and stream
							 | 
						||
| 
								 | 
							
								     * if the peer or stream is not created, then create it
							 | 
						||
| 
								 | 
							
								     * here
							 | 
						||
| 
								 | 
							
								     */
							 | 
						||
| 
								 | 
							
								    uint32_t vdev_nid;
							 | 
						||
| 
								 | 
							
								    tei_t dtei = tx_info->receiver;
							 | 
						||
| 
								 | 
							
								    uint32_t ret;
							 | 
						||
| 
								 | 
							
								    mac_stream_t *stream;
							 | 
						||
| 
								 | 
							
								    mac_peer_t *peer;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    if (ERR_OK != vdev_get_nid(vdev, (nid_t *)&vdev_nid)) {
							 | 
						||
| 
								 | 
							
								        iot_printf("warning:not nid for send,vid:%d,reduced:%d\r\n",\
							 | 
						||
| 
								 | 
							
								            vdev->vdev_id, vdev->mac_vdev_cfg.is_reduced_vdev);
							 | 
						||
| 
								 | 
							
								        return ERR_FAIL;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    if (dtei == PLC_TEI_BCAST) {
							 | 
						||
| 
								 | 
							
								        /* broadcast address
							 | 
						||
| 
								 | 
							
								         * return bcast peer
							 | 
						||
| 
								 | 
							
								         */
							 | 
						||
| 
								 | 
							
								        peer = (mac_peer_t*)vdev->bcast_peer;
							 | 
						||
| 
								 | 
							
								        /* must be a bcast flag */
							 | 
						||
| 
								 | 
							
								        IOT_ASSERT(tx_info->bcast);
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								    else {
							 | 
						||
| 
								 | 
							
								        peer = find_peer(vdev, vdev_nid, dtei);
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								    if (!peer) {
							 | 
						||
| 
								 | 
							
								        /* if the peer is not exist,
							 | 
						||
| 
								 | 
							
								        * create it right now
							 | 
						||
| 
								 | 
							
								        */
							 | 
						||
| 
								 | 
							
								        ret = mac_peer_alloc(vdev, dtei, \
							 | 
						||
| 
								 | 
							
								            0, 1, 0, 0, &peer);
							 | 
						||
| 
								 | 
							
								        if (ret) {
							 | 
						||
| 
								 | 
							
								            /* create peer failed */
							 | 
						||
| 
								 | 
							
								            IOT_ASSERT(0);
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    stream = find_stream(peer, vdev_nid,
							 | 
						||
| 
								 | 
							
								        dtei, lid, stream_trxn, IS_PLC_STREAM);
							 | 
						||
| 
								 | 
							
								    if (!stream) {
							 | 
						||
| 
								 | 
							
								        /* if stream is not found
							 | 
						||
| 
								 | 
							
								        * create it now
							 | 
						||
| 
								 | 
							
								        */
							 | 
						||
| 
								 | 
							
								        ret = mac_stream_alloc(peer, stream_trxn,
							 | 
						||
| 
								 | 
							
								            lid, IS_PLC_STREAM, &stream);
							 | 
						||
| 
								 | 
							
								        if (ret != ERR_OK && ret != ERR_EXIST) {
							 | 
						||
| 
								 | 
							
								            /* create stream failed */
							 | 
						||
| 
								 | 
							
								            IOT_ASSERT(0);
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    if (tx_info->phase > PLC_PHASE_CNT
							 | 
						||
| 
								 | 
							
								        || tx_info->phase == PLC_PHASE_ALL) {
							 | 
						||
| 
								 | 
							
								        tx_info->phase = PLC_PHASE_A;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    l_phase = tx_info->phase;
							 | 
						||
| 
								 | 
							
								    if (PLC_SUPPORT_CCO_TX_3_PHASE_SLOT ||
							 | 
						||
| 
								 | 
							
								        (mac_vdev_cfg_get_node_role(vdev) != PLC_DEV_ROLE_CCO)) {
							 | 
						||
| 
								 | 
							
								        /* note that for sta role device, we always send packet in phase A hwq.
							 | 
						||
| 
								 | 
							
								         * logical phase only control the time slot the packet to be sent.
							 | 
						||
| 
								 | 
							
								         * while for cco role device, we always use phase A hwq as packet
							 | 
						||
| 
								 | 
							
								         * alwasy be sent in 3 physical phases simultaneously. logical phase
							 | 
						||
| 
								 | 
							
								         * only control the physical phase rx.
							 | 
						||
| 
								 | 
							
								         */
							 | 
						||
| 
								 | 
							
								        tx_info->phase = PLC_PHASE_A;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    mac_msdu_frame_t *mac_frame;
							 | 
						||
| 
								 | 
							
								    mac_desc_get(&g_mac_desc_eng, PLC_MAC_MSDU_FRAME_POOL, \
							 | 
						||
| 
								 | 
							
								        (void **)&mac_frame);
							 | 
						||
| 
								 | 
							
								    IOT_ASSERT(mac_frame);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    if (tx_info->retry_prior) {
							 | 
						||
| 
								 | 
							
								        retry_cnt = (uint8_t)tx_info->retry_cnt;
							 | 
						||
| 
								 | 
							
								    } else {
							 | 
						||
| 
								 | 
							
								        retry_cnt = mac_msdu_retry_cnt_get(proto, data);
							 | 
						||
| 
								 | 
							
								        if (retry_cnt > 0) {
							 | 
						||
| 
								 | 
							
								            /* if retry_cnt exist,
							 | 
						||
| 
								 | 
							
								             * use it in mac header
							 | 
						||
| 
								 | 
							
								             */
							 | 
						||
| 
								 | 
							
								            retry_cnt -= 1;
							 | 
						||
| 
								 | 
							
								        } else {
							 | 
						||
| 
								 | 
							
								            /* if mac header retry cnt = 0
							 | 
						||
| 
								 | 
							
								             * use retry cnt in tx_info
							 | 
						||
| 
								 | 
							
								             */
							 | 
						||
| 
								 | 
							
								            retry_cnt = (uint8_t)tx_info->retry_cnt;
							 | 
						||
| 
								 | 
							
								            if (retry_cnt == 0) {
							 | 
						||
| 
								 | 
							
								                /* if tx_info retry cnt also = 0
							 | 
						||
| 
								 | 
							
								                 * use retry cnt default value
							 | 
						||
| 
								 | 
							
								                 */
							 | 
						||
| 
								 | 
							
								                if (dtei != PLC_TEI_BCAST) {
							 | 
						||
| 
								 | 
							
								                    retry_cnt = MAC_DEF_RETRY_CNT;
							 | 
						||
| 
								 | 
							
								                } else {
							 | 
						||
| 
								 | 
							
								                    retry_cnt = MAC_BCAST_DEF_RETRY_CNT;
							 | 
						||
| 
								 | 
							
								                }
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    if (dtei != PLC_TEI_BCAST) {
							 | 
						||
| 
								 | 
							
								        retry_cnt = retry_cnt > MAC_UCAST_MAX_RETRY_CNT ? \
							 | 
						||
| 
								 | 
							
								            MAC_UCAST_MAX_RETRY_CNT : retry_cnt;
							 | 
						||
| 
								 | 
							
								    } else {
							 | 
						||
| 
								 | 
							
								        retry_cnt = retry_cnt > MAC_BCAST_MAX_RETRY_CNT ? \
							 | 
						||
| 
								 | 
							
								            MAC_BCAST_MAX_RETRY_CNT : retry_cnt;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    /* NOTE: kl1 HW retry design: HW_retry_cnt = retry_cnt;
							 | 
						||
| 
								 | 
							
								     *                            tx cnt = HW_retry_cnt + 1;
							 | 
						||
| 
								 | 
							
								     *       kl2 HW retry design: HW_retry_cnt = retry_cnt;
							 | 
						||
| 
								 | 
							
								     *                            tx cnt = HW_retry_cnt;
							 | 
						||
| 
								 | 
							
								     *       SW retry action: tx cnt = retry_cnt;
							 | 
						||
| 
								 | 
							
								     *
							 | 
						||
| 
								 | 
							
								     *       kl1 HW retry have a bug, so we need use SW retry replace HW retry.
							 | 
						||
| 
								 | 
							
								     *       kl2 directly use HW retry.
							 | 
						||
| 
								 | 
							
								     */
							 | 
						||
| 
								 | 
							
								    retry_cnt++;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    /* calculate retry cnt if multi-band mode */
							 | 
						||
| 
								 | 
							
								    retry_cnt = mac_get_tx_retry_cnt_by_band(vdev,
							 | 
						||
| 
								 | 
							
								        phy_band_id_get(), retry_cnt);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    mac_frame_list_init(mac_frame, msdu_buf, tx_info->bcast,
							 | 
						||
| 
								 | 
							
								        tx_info->phase, l_phase, retry_cnt, tx_info->is_dbg_pkt,
							 | 
						||
| 
								 | 
							
								        tx_info->tx_3_phase, !tx_info->same_vendor, tx_info->ppm_step,
							 | 
						||
| 
								 | 
							
								        tx_info->ppm_step_type);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    if (!stream->msdu.tx.mac_frame_list) {
							 | 
						||
| 
								 | 
							
								        stream->msdu.tx.mac_frame_list = mac_frame;
							 | 
						||
| 
								 | 
							
								        stream->msdu.tx.last_mac_frame = mac_frame;
							 | 
						||
| 
								 | 
							
								        stream->msdu.tx.mac_frame_num = 1;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								    else {
							 | 
						||
| 
								 | 
							
								        /* TODO: put it at the end of list */
							 | 
						||
| 
								 | 
							
								        stream->msdu.tx.last_mac_frame->next = mac_frame;
							 | 
						||
| 
								 | 
							
								        stream->msdu.tx.last_mac_frame = mac_frame;
							 | 
						||
| 
								 | 
							
								        stream->msdu.tx.mac_frame_num++;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    /* check if need to decrease token number */
							 | 
						||
| 
								 | 
							
								    mac_token_alloc(bcn_region_type, lid, 0);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    /* TODO: put the stream to the swq */
							 | 
						||
| 
								 | 
							
								    mac_queue_t swq_id;
							 | 
						||
| 
								 | 
							
								    swq_id = mac_q_get_swq_type(bcn_region_type, \
							 | 
						||
| 
								 | 
							
								        tx_info->phase, (lid_t)lid);
							 | 
						||
| 
								 | 
							
								    /* check if swq type is support */
							 | 
						||
| 
								 | 
							
								    if (swq_id == MAX_MAC_QUE_NUM)
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								        /* swq type error */
							 | 
						||
| 
								 | 
							
								        IOT_ASSERT(0);
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    mac_swsch_append(g_mac_swq[swq_id], tx_info->phase, stream);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#if STATIC_POWER_SAVE
							 | 
						||
| 
								 | 
							
								    if (pdev->mac_pm.is_start) {
							 | 
						||
| 
								 | 
							
								        mac_pm_stop(pdev);
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								#endif
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    mac_add_send_msdu_cnt();
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    /* trigger the sw scheduler to send */
							 | 
						||
| 
								 | 
							
								    /* send a msg to self */
							 | 
						||
| 
								 | 
							
								    return mac_swsch_trigger_tx(pdev_id, vdev_id);
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/* interface expose to high mac - CL layer */
							 | 
						||
| 
								 | 
							
								uint32_t mac_send_msdu_ex(pdevid_t pdev_id, vdevid_t vdev_id,
							 | 
						||
| 
								 | 
							
								    iot_pkt_t* msdu_buf, mac_tx_info *tx_info)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								    uint8_t *data;
							 | 
						||
| 
								 | 
							
								    uint32_t ret = 0;
							 | 
						||
| 
								 | 
							
								#if ((MAC_MM_SNIFFER_MODE == MAC_SNIFFER_TYPE_MSDU) || \
							 | 
						||
| 
								 | 
							
								    ((MAC_MM_SNIFFER_MODE == MAC_SNIFFER_TYPE_MSDU_UART)))
							 | 
						||
| 
								 | 
							
								    iot_pkt_free_tx_done(msdu_buf, IOT_PKT_STATE_TX_FAIL);
							 | 
						||
| 
								 | 
							
								    return ERR_OK;
							 | 
						||
| 
								 | 
							
								#endif
							 | 
						||
| 
								 | 
							
								    mac_msg_t *msg = mac_alloc_msg();
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    if (msg == NULL) {
							 | 
						||
| 
								 | 
							
								        iot_pkt_free_tx_done(msdu_buf, IOT_PKT_STATE_TX_FAIL);
							 | 
						||
| 
								 | 
							
								        IOT_ASSERT(0);
							 | 
						||
| 
								 | 
							
								        ret = ERR_NOMEM;
							 | 
						||
| 
								 | 
							
								        goto out;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								    /* make sure packet is started with 4 bytes aligned */
							 | 
						||
| 
								 | 
							
								    data = iot_pkt_data(msdu_buf);
							 | 
						||
| 
								 | 
							
								    IOT_ASSERT(((uint32_t)data & 0x3) == 0);
							 | 
						||
| 
								 | 
							
								    BUILD_BUG_ON(MAC_REQ_HEAD_RSVD_LEN >=
							 | 
						||
| 
								 | 
							
								        (sizeof(mac_tx_info) + sizeof(frame_control_t)));
							 | 
						||
| 
								 | 
							
								    /* put tx_info in the header of iot_pkt */
							 | 
						||
| 
								 | 
							
								    mac_tx_info *info = (mac_tx_info *)iot_pkt_block_ptr(msdu_buf,
							 | 
						||
| 
								 | 
							
								        IOT_PKT_BLOCK_HEAD);
							 | 
						||
| 
								 | 
							
								    IOT_ASSERT(info);
							 | 
						||
| 
								 | 
							
								    os_mem_cpy(info, tx_info, sizeof(mac_tx_info));
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    msg->type = MAC_MSG_TYPE_CVG;
							 | 
						||
| 
								 | 
							
								    msg->id = MAC_MSG_ID_CVG_MSDU_SEND;
							 | 
						||
| 
								 | 
							
								    msg->data1 = (((uint32_t)pdev_id) << 8) | vdev_id;
							 | 
						||
| 
								 | 
							
								    msg->data2 = msdu_buf;
							 | 
						||
| 
								 | 
							
								    msg->data3 = info;
							 | 
						||
| 
								 | 
							
								    mac_queue_msg(msg, MAC_MSG_QUEUE_HP);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								out:
							 | 
						||
| 
								 | 
							
								    return ret;
							 | 
						||
| 
								 | 
							
								}
							 |