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