1725 lines
69 KiB
C
Executable File
1725 lines
69 KiB
C
Executable File
/****************************************************************************
|
|
|
|
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_rx_hw.h"
|
|
#include "mac_pdev.h"
|
|
#include "mpdu_frame.h"
|
|
#include "iot_errno.h"
|
|
#include "iot_pkt.h"
|
|
#include "iot_io.h"
|
|
#include "iot_system.h"
|
|
#include "plc_protocol.h"
|
|
#include "hw_tonemap.h"
|
|
#include "mac_vdev.h"
|
|
#include "mac_stream.h"
|
|
#include "mac_peer.h"
|
|
#include "mac_isr.h"
|
|
#include "mac_sched_hw.h"
|
|
#include "plc_const.h"
|
|
#include "phy_chn.h"
|
|
#include "phy_phase.h"
|
|
#include "mpdu_header.h"
|
|
#include "mac_rx_reg.h"
|
|
#include "mac_msg.h" /* for msg send */
|
|
#include "mac.h" /* for msg id */
|
|
#include "plc_mpdu_header.h" /* for frame_control_t */
|
|
#include "mac_sched.h"
|
|
#include "mac_cert_test.h"
|
|
#include "mac_rawdata_hw.h"
|
|
#include "iot_dbglog_api.h"
|
|
#include "iot_dbglog_parser.h"
|
|
#include "iot_plc_led.h"
|
|
#include "mac_ppm_scan.h"
|
|
#include "chip_reg_base.h"
|
|
#include "mac_reset.h"
|
|
#include "iot_system_api.h"
|
|
#include "mac_crc.h"
|
|
#include "mac_channel.h"
|
|
#include "hw_war.h"
|
|
#include "mac_hplc_ext.h"
|
|
#include "mac_hplc_ext_api.h"
|
|
#include "mac_check_spur_sta.h"
|
|
#if MAC_TIMESTAMPING
|
|
#include "mac_sys_reg.h"
|
|
#include "hw_reg_api.h"
|
|
#endif
|
|
#include "multi_nid_sync.h"
|
|
#include "phy_multi_ppm.h"
|
|
#include "mac_cmn_hw.h"
|
|
#include "iot_oem_api.h"
|
|
|
|
static bool_t mac_rx_check_pb_st_ssn_valid(uint32_t proto, uint32_t pbsz,
|
|
uint32_t pb_num, rx_pb_start *pb_st)
|
|
{
|
|
bool_t is_valid = true;
|
|
uint32_t msdu_pl_max;
|
|
switch (proto) {
|
|
#if SUPPORT_SMART_GRID
|
|
case PLC_PROTO_TYPE_SG:
|
|
msdu_pl_max = (PB_SIZE_520 - SG_SOF_PB_HDR_CRC_LEN) \
|
|
* PLC_SG_MAX_PB_NUM;
|
|
if ((((pbsz - SG_SOF_PB_HDR_CRC_LEN) * pb_st->ssn) > msdu_pl_max)
|
|
|| (pb_st->msdu_start && (pb_st->ssn != 0))
|
|
|| (!pb_st->msdu_start && (pb_st->ssn == 0))) {
|
|
is_valid = false;
|
|
}
|
|
break;
|
|
#endif
|
|
|
|
#if SUPPORT_SOUTHERN_POWER_GRID
|
|
case PLC_PROTO_TYPE_SPG:
|
|
/* for spg, msdu_start & msdu_end invalid */
|
|
if (pb_st->ssn >= min(PLC_SPG_MAX_PB_NUM, pb_num)){
|
|
is_valid = false;
|
|
}
|
|
break;
|
|
#endif
|
|
|
|
#if SUPPORT_GREEN_PHY
|
|
//add code
|
|
#endif
|
|
|
|
default:
|
|
(void)msdu_pl_max;
|
|
(void)pbsz;
|
|
(void)pb_num;
|
|
(void)pb_st;
|
|
break;
|
|
}
|
|
|
|
return is_valid;
|
|
}
|
|
|
|
/* return. 0 - check fc crc ok, 1 - check fc crc error */
|
|
static uint8_t mac_rx_check_fccs(rx_attention *att, rx_mpdu_start *mpdu_st)
|
|
{
|
|
uint8_t is_fccs_err = 0;
|
|
|
|
#if ENA_SW_FCCRC_CHECK
|
|
rx_fc_msg_t rx_fc = {0};
|
|
mac_get_rx_frm_msg_from_fc(mac_rx_mpdu_st_get_rx_proto(mpdu_st),
|
|
mac_rx_mpdu_st_get_fc_addr(mpdu_st), &rx_fc);
|
|
uint32_t sw_crc = mac_crc_get_fc_swcrc(mac_rx_mpdu_st_get_rx_proto(mpdu_st),
|
|
mac_rx_mpdu_st_get_fc_addr(mpdu_st));
|
|
if (sw_crc != rx_fc.fccs) {
|
|
is_fccs_err = 1;
|
|
}
|
|
if (!!mac_rx_att_get_is_fcserr(att) ^ !!is_fccs_err) {
|
|
mac_add_rx_fc_err_no_match_cnt();
|
|
iot_printf("fccs:hw-%d-0x%08x, sw-%d-0x%08x\n",
|
|
mac_rx_att_get_is_fcserr(att), rx_fc.fccs,
|
|
is_fccs_err, sw_crc);
|
|
}
|
|
#else
|
|
(void)mpdu_st;
|
|
#endif
|
|
|
|
if (mac_rx_att_get_is_fcserr(att) || is_fccs_err) {
|
|
mac_add_rx_fc_err_cnt();
|
|
is_fccs_err = 1;
|
|
}
|
|
|
|
return is_fccs_err;
|
|
}
|
|
|
|
uint32_t mac_filter_bcn_by_band(uint32_t proto, uint32_t proto_band_id)
|
|
{
|
|
/* spg not care detect beacon */
|
|
if (PLC_PROTO_TYPE_SPG == proto \
|
|
&& proto_band_id != phy_proto_single_band_id_get()) {
|
|
return ERR_INVAL;
|
|
}
|
|
|
|
return ERR_OK;
|
|
}
|
|
|
|
static uint32_t mac_get_org_dtei(uint32_t proto,
|
|
rx_pb_start *pb_st, rx_pb_end *pb_ed, uint8_t *data)
|
|
{
|
|
uint32_t org_dtei = PLC_TEI_INVAL;
|
|
if (pb_st->first_pb && pb_st->last_pb &&
|
|
pb_ed->rx_pb_crc_err == 0) {
|
|
if (proto == PLC_PROTO_TYPE_SG) {
|
|
mac_header_t *mac_hd_sg = (mac_header_t *)(data);
|
|
org_dtei = mac_hd_sg->org_dest_tei;
|
|
} else if (proto == PLC_PROTO_TYPE_SPG) {
|
|
spg_mac_header_t *mac_hd_spg = (spg_mac_header_t *)(data);
|
|
org_dtei = mac_hd_spg->org_dest_tei;
|
|
} else {
|
|
/* reserve for future */
|
|
}
|
|
}
|
|
return org_dtei;
|
|
}
|
|
|
|
static uint32_t mac_judge_is_not_self_pkt(uint32_t proto,
|
|
mac_vdev_t *vdev, rx_pb_start *pb_st,
|
|
rx_pb_end *pb_ed, uint8_t *data)
|
|
{
|
|
/* if the dtei in the mac header is myself,
|
|
* mac layer need to send the packet to CVG,
|
|
* and only just 1pb packet need to do this.
|
|
*/
|
|
uint8_t do_not_upload = 1;
|
|
uint8_t cert_mode = mac_get_cert_test_mode();
|
|
if (!cert_mode) {
|
|
uint32_t org_dtei = mac_get_org_dtei(proto, pb_st, pb_ed, data);
|
|
if (org_dtei != PLC_TEI_INVAL &&
|
|
org_dtei == vdev_get_tei(vdev)) {
|
|
do_not_upload = 0;
|
|
}
|
|
}
|
|
return do_not_upload;
|
|
}
|
|
|
|
#if (MAC_RX_CHK_VALID_I1901)
|
|
|
|
/* return 0 - this packet invalid, 1 - this packet valid*/
|
|
static uint8_t mac_rx_check_data_i1901(rx_attention *att,
|
|
rx_mpdu_start *mpdu_st, rx_pb_end *pb_ed, uint32_t buf_size)
|
|
{
|
|
uint8_t is_valid;
|
|
i1901_frame_control_t *fc_1901;
|
|
uint8_t tmi = 0, tmi_ext = 0, pb_num = 0;
|
|
uint16_t stei = 0, dtei = 0;
|
|
|
|
(void)att;
|
|
(void)pb_ed;
|
|
(void)buf_size;
|
|
fc_1901 = (i1901_frame_control_t *)mac_rx_mpdu_st_get_fc_addr(mpdu_st);
|
|
|
|
switch (fc_1901->delimiter_type) {
|
|
case FC_DELIM_BEACON:
|
|
tmi = fc_1901->vf.bcn.tmi;
|
|
tmi_ext = 0;
|
|
stei = fc_1901->vf.bcn.stei;
|
|
break;
|
|
|
|
case FC_DELIM_SOF:
|
|
tmi = fc_1901->vf.sof.tmi;
|
|
tmi_ext = fc_1901->vf.sof.tmi_ext;
|
|
pb_num = fc_1901->vf.sof.pb_num;
|
|
stei = fc_1901->vf.sof.stei;
|
|
dtei = fc_1901->vf.sof.dtei;
|
|
break;
|
|
|
|
case FC_DELIM_SACK:
|
|
pb_num = fc_1901->vf.sack.rx_pb;
|
|
stei = fc_1901->vf.sack.stei;
|
|
dtei = fc_1901->vf.sack.dtei;
|
|
break;
|
|
|
|
case I1901_RTS_CTS:
|
|
stei = fc_1901->vf.rts_cts.stei;
|
|
dtei = fc_1901->vf.rts_cts.dtei;
|
|
break;
|
|
|
|
case FC_DELIM_NNCCO:
|
|
break;
|
|
|
|
default:
|
|
return 0;
|
|
}
|
|
|
|
is_valid = 0;
|
|
do {
|
|
if (tmi_ext) {
|
|
if (tmi >= I1901_EXT_TMI_MAX) {
|
|
break;
|
|
}
|
|
} else {
|
|
if (tmi >= I1901_TMI_MAX) {
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (pb_num > PLC_I1901_MAX_PB_NUM) {
|
|
break;
|
|
}
|
|
|
|
if ((PLC_TEI_BCAST != stei) && (PLC_TEI_CTRL != stei)
|
|
&& (PLC_TEI_CTRL_GW != stei) && (stei > PLC_TEI_MAX_NUM)) {
|
|
break;
|
|
}
|
|
|
|
if ((PLC_TEI_BCAST != dtei) && (PLC_TEI_CTRL != dtei)
|
|
&& (PLC_TEI_CTRL_GW != dtei) && (dtei > PLC_TEI_MAX_NUM)) {
|
|
break;
|
|
}
|
|
is_valid = 1;
|
|
} while (0);
|
|
|
|
return is_valid;
|
|
}
|
|
|
|
#else /* MAC_RX_CHK_VALID_I1901 */
|
|
|
|
#define mac_rx_check_data_i1901(att, mpdu_st, pb_ed, buf_size) (1)
|
|
|
|
#endif /* MAC_RX_CHK_VALID_I1901 */
|
|
|
|
#if SUPPORT_SOUTHERN_POWER_GRID
|
|
|
|
const uint8_t g_spg_gx_swich_band_pl[] = {
|
|
0x03, 0x00, 0x13, 0x00, 0x01, 0x00, 0x00, 0x00,
|
|
0x10, 0x02, 0x21, 0x43, 0x00, 0x01, 0x11, 0x01,
|
|
0x01, 0x00, 0x02, 0x40, 0xF0, 0x01, 0x34, 0x12,
|
|
0x05, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x38,
|
|
0x8B, 0xB9, 0x9A, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00,
|
|
};
|
|
|
|
const uint32_t g_spg_gx_swich_band_crc = 0xC547CD;
|
|
|
|
const uint8_t g_spg_guizhou_assoc_ind_pl[] = {
|
|
0x02, 0x00, 0x3C, 0x00, 0xFF, 0x1F, 0x00, 0x06,
|
|
0x11, 0x12, 0x01, 0x00, 0xFF, 0xFF, 0xFF, 0xFF,
|
|
0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x19, 0x21,
|
|
0x68, 0x00, 0x00, 0x01, 0x00, 0x81, 0x00, 0x00,
|
|
0xE1, 0x88, 0x01, 0x3A, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x01, 0x19, 0x21, 0x68, 0x00, 0x00, 0x01,
|
|
0x01, 0x00, 0x08, 0x01, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x19, 0x21, 0x68, 0x00,
|
|
0x09, 0x04, 0x05, 0x00, 0x96, 0x44, 0x56, 0x3E,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00,
|
|
};
|
|
|
|
const uint32_t g_spg_guizhou_assoc_ind_crc = 0x218E56;
|
|
|
|
#endif
|
|
|
|
#define MAC_WAR_RX_ABORT_SPG_WAR_MAX 5
|
|
static uint8_t mac_rx_abort_packet_check(rx_fc_msg_t *rx_fc,
|
|
rx_mpdu_end *mpdu_end, rx_pb_start *pb_start, rx_pb_end *pb_end,
|
|
uint8_t *payload)
|
|
{
|
|
uint8_t is_free_pkt = 1;
|
|
|
|
if (4 == mac_rx_mpdu_end_get_rx_abnormal_id(mpdu_end)) {
|
|
if (rx_fc->delimiter == FC_DELIM_BEACON) {
|
|
pb_end->rx_pb_crc_err = 1;
|
|
/* not free beacon pkt for rx abort reason4 */
|
|
is_free_pkt = 0;
|
|
} else if (rx_fc->delimiter == FC_DELIM_SOF) {
|
|
#if SUPPORT_SOUTHERN_POWER_GRID
|
|
mac_pdev_t *pdev = get_pdev_ptr(PLC_PDEV_ID);
|
|
mac_vdev_t *vdev = get_vdev_ptr(PLC_PDEV_ID, PLC_DEFAULT_VDEV);
|
|
uint32_t user_type = iot_oem_get_user_type();
|
|
|
|
if (pdev->rx_abort_spg_war_cnt <= MAC_WAR_RX_ABORT_SPG_WAR_MAX) {
|
|
pdev->rx_abort_spg_war_cnt++;
|
|
}
|
|
|
|
/* cco */
|
|
if (mac_vdev_cfg_get_node_role(vdev) == PLC_DEV_ROLE_CCO) {
|
|
if (USER_TYPE_SOUTHEN_POWER_GRID_GX_NW21 == user_type) {
|
|
if ((pdev->rx_abort_spg_war_cnt
|
|
== MAC_WAR_RX_ABORT_SPG_WAR_MAX)
|
|
&& (rx_fc->nid == 0x0) && (rx_fc->src_tei == 0)
|
|
&& (rx_fc->dst_tei == 1) && (rx_fc->tmi == 4)
|
|
&& (rx_fc->numsym == 0x26)) {
|
|
mpdu_end->rx_abnormal_id = 0;
|
|
pb_start->first_pb = 1;
|
|
pb_start->last_pb = 1;
|
|
pb_start->msdu_start = 1;
|
|
pb_start->msdu_end = 1;
|
|
pb_start->ssn = 0;
|
|
|
|
pb_end->rx_pb_crc_err = 0;
|
|
mac_rx_pb_end_set_pb_crc(pb_end,
|
|
g_spg_gx_swich_band_crc);
|
|
os_mem_cpy(payload, g_spg_gx_swich_band_pl,
|
|
sizeof(g_spg_gx_swich_band_pl));
|
|
is_free_pkt = 0;
|
|
}
|
|
}
|
|
} else {
|
|
/* sta */
|
|
if (USER_TYPE_SOUTHEN_POWER_GRID_GUIZHOU == user_type) {
|
|
if ((pdev->rx_abort_spg_war_cnt <= 1)
|
|
&& (rx_fc->nid == 0x6) && (rx_fc->src_tei == 1)
|
|
&& (rx_fc->dst_tei == 0xFFF) && (rx_fc->tmi == 0)
|
|
&& (rx_fc->numsym == 121)) {
|
|
mpdu_end->rx_abnormal_id = 0;
|
|
pb_start->first_pb = 1;
|
|
pb_start->last_pb = 1;
|
|
pb_start->msdu_start = 1;
|
|
pb_start->msdu_end = 1;
|
|
pb_start->ssn = 0;
|
|
|
|
pb_end->rx_pb_crc_err = 0;
|
|
mac_rx_pb_end_set_pb_crc(pb_end,
|
|
g_spg_guizhou_assoc_ind_crc);
|
|
os_mem_cpy(payload, g_spg_guizhou_assoc_ind_pl,
|
|
sizeof(g_spg_guizhou_assoc_ind_pl));
|
|
is_free_pkt = 0;
|
|
}
|
|
}
|
|
}
|
|
#endif
|
|
}
|
|
}
|
|
|
|
return is_free_pkt;
|
|
}
|
|
|
|
uint32_t g_no_pb_done = 0;
|
|
uint32_t mac_rx_hw_mpdu_internal(void *pdev_in, uint32_t ring_id,
|
|
uint32_t quota_ms)
|
|
{
|
|
mac_pdev_t *pdev = (mac_pdev_t*)pdev_in;
|
|
iot_pkt_t *iot_pkt_array[1] = { 0 };
|
|
rx_attention *att;
|
|
rx_mpdu_start *mpdu_st;
|
|
rx_mpdu_end *mpdu_ed;
|
|
rx_pb_start *pb_st;
|
|
rx_pb_end *pb_ed;
|
|
uint32_t is_retry_mpdu = 0;
|
|
uint32_t ret;
|
|
mac_vdev_t *vdev;
|
|
mac_peer_t *peer = NULL;
|
|
mac_stream_t *stream = NULL;
|
|
rx_buf_ring_t *ring;
|
|
int32_t delta_ntb;
|
|
uint8_t *payload;
|
|
uint32_t nid = 0;
|
|
uint32_t proto = 0;
|
|
int8_t snr = INVALID_SNR;
|
|
uint32_t is_overflow;
|
|
uint32_t delimiter_type = 0xFFFFFFFF;
|
|
uint32_t proto_band_id;
|
|
uint8_t rx_phase;
|
|
rx_fc_msg_t rx_fc_msg = { 0 };
|
|
uint8_t is_vdev_found;
|
|
uint8_t is_not_my_ucast;
|
|
uint32_t pbsz = 0;
|
|
int8_t raw_snr = INVALID_SNR;
|
|
uint8_t rssi = INV_RSSI;
|
|
uint8_t node_role;
|
|
|
|
#if HW_PLATFORM == HW_PLATFORM_SIMU
|
|
ring = &pdev->simu.rx_ring[ring_id];
|
|
#else
|
|
ring = &pdev->ring_hdl.ring[ring_id];
|
|
#endif
|
|
mac_pdev_t *pdev_t = g_mac_pdev[PLC_PDEV_ID];
|
|
#if MAC_TIMESTAMPING
|
|
/* mac rx ntb in dsr */
|
|
pdev->mac_rx_ntb = RGF_MAC_READ_REG(CFG_RD_NTB_ADDR);
|
|
#endif
|
|
|
|
#if ((HW_PLATFORM > HW_PLATFORM_SIMU) && PLC_SUPPORT_STA_ROLE && IOT_MP_SUPPORT)
|
|
BUILD_BUG_ON(ENA_SYNC_DIFF_CCO_PPM);
|
|
#endif
|
|
|
|
uint32_t cur_ts = os_boot_time32();
|
|
do {
|
|
if (pop_buf_from_ring(ring, 1, iot_pkt_array))
|
|
{
|
|
if (pdev->vdev[PLC_DEFAULT_VDEV]->stop_flag ||
|
|
pdev->vdev[PLC_DEFAULT_VDEV]->tx_rx_suspend) {
|
|
goto free_pkt;
|
|
}
|
|
mac_add_rx_pb_cnt();
|
|
/* if pop something out */
|
|
uint8_t *tmp =
|
|
iot_pkt_block_ptr(iot_pkt_array[0], IOT_PKT_BLOCK_DATA);
|
|
if(iot_pkt_validation(iot_pkt_array[0]))
|
|
{
|
|
uint32_t *p = (uint32_t *) (((uint8_t *) iot_pkt_array[0])
|
|
- ring->buf_sz - 16);
|
|
(void)p;
|
|
mem_dump(p, (ring->buf_sz >> 1) + 4);
|
|
IOT_ASSERT_DUMP(0, p, (ring->buf_sz >> 1) + 4);
|
|
goto free_pkt;
|
|
}
|
|
#if WAR_MPDU_NOT_DONE
|
|
if (ring->not_done) {
|
|
/* if not done due to HW overflow or overwrite issue,
|
|
* just skip some pkt
|
|
*/
|
|
ring->not_done--;
|
|
ring->overflow = 1;
|
|
mem_dump((uint32_t *)iot_pkt_array[0], 20);
|
|
goto free_pkt;
|
|
}
|
|
#endif
|
|
att = (rx_attention*)(tmp + RX_ATTENTION_OFFSET);
|
|
mpdu_st = (rx_mpdu_start *)(tmp + MPDU_START_OFFSET);
|
|
mpdu_ed = (rx_mpdu_end *)(tmp + MPDU_END_OFFSET);
|
|
pb_st = (rx_pb_start *)(tmp + PB_START_OFFSET);
|
|
pb_ed = (rx_pb_end *)(tmp + PB_END_OFFSET);
|
|
payload = tmp + PB_PAYLOAD_OFFSET;
|
|
(void)payload;
|
|
|
|
#if MAC_TIMESTAMPING
|
|
/* record rx timestamp */
|
|
pdev_t->mac_rx_timestamp = \
|
|
mac_rx_mpdu_end_get_local_timestamp(mpdu_ed);
|
|
#endif
|
|
//log for ring id and delimiter type
|
|
mac_rx_debug_log_ringid_and_detype(mpdu_st);
|
|
//log for info
|
|
mac_rx_debug_log_info(iot_pkt_array[0]);
|
|
|
|
/* if this pb done */
|
|
if (pb_ed->rx_pb_done) {
|
|
/* check rx phy err */
|
|
mac_rx_debug_log_check_phy_err(pb_st, mpdu_ed);
|
|
|
|
/* check rx protocol */
|
|
#if (SUPPORT_SOUTHERN_POWER_GRID && (HW_PLATFORM >= HW_PLATFORM_FPGA))
|
|
proto = mac_rx_mpdu_st_get_rx_proto(mpdu_st);
|
|
if (PLC_PROTO_TYPE_SPG != proto) {
|
|
iot_printf("mac_rx_proto:hw-%d,phy-%d\n", \
|
|
proto, PHY_PROTO_TYPE_GET());
|
|
mac_add_rx_proto_nomatch_cnt();
|
|
goto free_pkt;
|
|
}
|
|
#endif
|
|
/* handle rx abort */
|
|
if((mac_rx_pb_st_get_last_pb(pb_st) \
|
|
&& mac_rx_mpdu_end_get_rx_abort(mpdu_ed)) || \
|
|
(mac_rx_pb_st_get_first_pb(pb_st) \
|
|
&& mac_rx_att_get_rx_abort(att)))
|
|
{
|
|
#if (SUPPORT_SOUTHERN_POWER_GRID && (HW_PLATFORM >= HW_PLATFORM_FPGA))
|
|
if (pdev->rx_abort_rst_cnt < 10) {
|
|
/* disable mac raw data mode */
|
|
mac_rawdata_mode_enable(0);
|
|
/* clear pb size BB */
|
|
phy_rawdata_mode_bb_set_ps_tr(0, 0, 0);
|
|
pdev->rx_abort_rst_cnt++;
|
|
}
|
|
#endif
|
|
|
|
#if DBG_RX_ABORT_REASON_4 == 1
|
|
if (++pdev->cont_rx_abort4_cnt > 20) {
|
|
/* rx abort continues */
|
|
iot_printf("rx abort stuck!\n");
|
|
/* TODO: call dump and reset phy here */
|
|
#if DBG_HW_DUMP == 1
|
|
mac_dump_buf((uint32_t *)att,
|
|
sizeof(rx_buf_hdr_t)/sizeof(uint32_t),
|
|
(uint32_t *)RGF_RX_BASEADDR, 128, NULL, 0, true);
|
|
#else
|
|
#if IOT_MP_SUPPORT
|
|
mac_pdev_send_reset_war_msg(pdev, CONT_RX_ABORT4);
|
|
#endif
|
|
pdev->cont_rx_abort4_cnt = 0;
|
|
#endif
|
|
}
|
|
#endif
|
|
//log for rx abort
|
|
mac_rx_debug_log_rxabort(iot_pkt_array[0]);
|
|
|
|
mac_add_rx_abort_cnt();
|
|
|
|
if (pb_st->last_pb) {
|
|
ring->cur_mpdu = NULL;
|
|
} else if (pb_st->first_pb) {
|
|
/* if multi pb and first pb's rx abort
|
|
* we need to save the buf's mpdu_st desc
|
|
* or else the rest print info is not reliable
|
|
*/
|
|
goto save_mpdu_st_and_free;
|
|
}
|
|
#if (SIMU_DBG == 1)
|
|
iot_printf("simu_dbg, mac drop package, rx abort\n");
|
|
#endif
|
|
|
|
proto = mac_rx_mpdu_st_get_rx_proto(mpdu_st);
|
|
mac_get_rx_frm_msg_from_fc(proto,
|
|
mac_rx_mpdu_st_get_fc_addr(mpdu_st), &rx_fc_msg);
|
|
if (mac_rx_abort_packet_check(&rx_fc_msg, mpdu_ed, pb_st,
|
|
pb_ed, payload)) {
|
|
goto free_pkt;
|
|
}
|
|
}
|
|
|
|
/* handle overflow */
|
|
if((mac_rx_pb_st_get_last_pb(pb_st) \
|
|
&& mac_rx_mpdu_end_get_is_overflow(mpdu_ed)) || \
|
|
(mac_rx_pb_st_get_first_pb(pb_st) \
|
|
&& mac_rx_att_get_is_overflow(att)))
|
|
{
|
|
/* handle pb payload overflow */
|
|
#if (PLC_MAC_RX_DEBUG_LOG >= PLC_MAC_LOG_LEVEL_1)
|
|
iot_printf("rx pb overflow:att@0x%x\n", att);
|
|
#endif
|
|
if (pb_st->last_pb) {
|
|
ring->cur_mpdu = NULL;
|
|
}
|
|
goto free_pkt;
|
|
}
|
|
//half_mpdu_check:
|
|
/* handle desc overflow */
|
|
is_overflow = ring->overflow | \
|
|
(rx_ring_get_overflow_status() & (0x1 << ring_id));
|
|
if (pb_st->first_pb) {
|
|
/* for first pb */
|
|
if (!mac_rx_att_get_rx_mpdu_done(att)) {
|
|
//add mpdu not done cnt
|
|
mac_add_rx_att_not_done_cnt();
|
|
|
|
/* should not happen, mpdu_done should
|
|
* always be valid when first pb
|
|
*/
|
|
iot_printf("mpdu_done not set correctly," \
|
|
" att@0x%x\n", att);
|
|
#if PLC_HW_ISSUE_ASSERT_LEVEL <= PLC_HW_ISSUE_ASSERT_ALL
|
|
IOT_ASSERT(0);
|
|
#endif
|
|
if (!pb_st->last_pb) {
|
|
/* if multi pb and first pb's freed
|
|
* we need to save the buf's mpdu_st desc
|
|
* or else the rest print info is not reliable
|
|
*/
|
|
goto save_mpdu_st_and_free;
|
|
}
|
|
|
|
goto free_pkt;
|
|
}
|
|
if (mac_rx_check_fccs(att, mpdu_st)) {
|
|
if (!pb_st->last_pb) {
|
|
/* if multi pb and first pb's freed
|
|
* we need to save the buf's mpdu_st desc
|
|
* or else the rest print info is not reliable
|
|
*/
|
|
goto save_mpdu_st_and_free;
|
|
}
|
|
|
|
goto free_pkt;
|
|
}
|
|
if (!is_overflow) {
|
|
if (ring->cur_mpdu != NULL && !pb_st->last_pb) {
|
|
/* if not overflow, should not happen */
|
|
/* for first pb, record the mpdu start
|
|
* only the first pb's mpdu start is valid
|
|
*/
|
|
mac_add_rx_half_pkt_cnt();
|
|
iot_printf("last pb not seen. half_pkt_cnt = %d\n",\
|
|
mac_get_rx_half_pkt_cnt());
|
|
#if PLC_HW_ISSUE_ASSERT_LEVEL <= PLC_HW_ISSUE_ASSERT_ALL
|
|
IOT_ASSERT(ring->cur_mpdu == NULL);
|
|
#endif
|
|
}
|
|
}
|
|
else {
|
|
/* overflow happen */
|
|
if (ring->cur_mpdu) {
|
|
/* if first pb but cur_mpdu is not null,
|
|
* this may result half mpdu received.
|
|
* do nothing, just restart recording
|
|
* and continue
|
|
* the mpdu record
|
|
*/
|
|
|
|
}
|
|
}
|
|
/* record the first pb */
|
|
/* correct the snr for the upper layer */
|
|
raw_snr = mac_rx_mpdu_st_get_avg_snr(mpdu_st);
|
|
mac_rx_mpdu_st_set_avg_snr(mpdu_st,
|
|
phy_rx_snr_cal(
|
|
mac_rx_mpdu_st_get_phy_info_addr(mpdu_st),
|
|
mac_rx_mpdu_st_get_rx_phase(mpdu_st)));
|
|
os_mem_cpy(&ring->saved_mpdu_st, mpdu_st,
|
|
sizeof(ring->saved_mpdu_st));
|
|
ring->cur_mpdu = &ring->saved_mpdu_st;
|
|
}
|
|
else {
|
|
/* if not first pb */
|
|
if (!is_overflow) {
|
|
if (ring->cur_mpdu == NULL) {
|
|
/* if not overflow, should not happen */
|
|
/* if not first pb and ring->cur_mpdu == null
|
|
* this means not a full mpdu received
|
|
* when enter dsr. it usually
|
|
* should not happen
|
|
*/
|
|
mac_add_rx_half_pkt_cnt();
|
|
iot_printf("first pb not seen, drop the pb, cnt:%d.\n",\
|
|
mac_get_rx_half_pkt_cnt());
|
|
#if PLC_HW_ISSUE_ASSERT_LEVEL <= PLC_HW_ISSUE_ASSERT_ALL
|
|
IOT_ASSERT(0);
|
|
#endif
|
|
goto free_pkt;
|
|
}
|
|
}
|
|
else {
|
|
#if (PLC_MAC_RX_DEBUG_LOG >= PLC_MAC_LOG_LEVEL_1)
|
|
iot_printf("rx overflow:reason-%d\n", \
|
|
mpdu_ed->rx_abnormal_id);
|
|
iot_dbglog_input(PLC_MAC_RX_HW_MID, DBGLOG_INFO_LVL_2,
|
|
IOT_MAC_RX_OVERFLOW_ID, 1,\
|
|
mpdu_ed->rx_abnormal_id);
|
|
#endif
|
|
mac_add_rx_overflow_cnt();
|
|
/* if overflow, and latter half mpdu received.
|
|
* drop the pbs till receive a first pb
|
|
*/
|
|
/* set fcs err */
|
|
mac_rx_att_set_is_fcserr(att, 1);
|
|
/* free the error pb */
|
|
#if (SIMU_DBG == 1)
|
|
iot_printf("simu_dbg, mac drop package, is_overflow\n");
|
|
#endif
|
|
goto free_pkt;
|
|
}
|
|
mpdu_st = ring->cur_mpdu;
|
|
IOT_ASSERT(mpdu_st);
|
|
}
|
|
|
|
if (0 == mac_rx_check_data_i1901(att, mpdu_st, pb_ed,
|
|
ring->buf_sz)) {
|
|
mac_add_rx_fc_invalid_cnt();
|
|
goto free_pkt;
|
|
}
|
|
mac_fc_i1901_to_sg(mac_rx_mpdu_st_get_rx_proto(mpdu_st),
|
|
mac_rx_mpdu_st_get_fc_addr(mpdu_st));
|
|
|
|
//log for fc
|
|
mac_rx_debug_log_fc(mpdu_st);
|
|
|
|
/* sta spur check */
|
|
/* sta restart timer */
|
|
uint32_t *fc_spur = \
|
|
(uint32_t*)mac_rx_mpdu_st_get_fc_addr(mpdu_st);
|
|
uint32_t is_local_nw_pkt =
|
|
(mac_get_nid_from_fc(proto, (void *)fc_spur) ==
|
|
mac_get_hw_nid());
|
|
/* pb ok and fc valid */
|
|
if (pb_ed->rx_pb_crc_err == 0 &&
|
|
mac_rx_hw_check_fc_valid(fc_spur)) {
|
|
/* sta check spur restart */
|
|
mac_sta_check_spur_timer_restart( \
|
|
&pdev_t->mac_check_spur_ctxt, is_local_nw_pkt);
|
|
}
|
|
|
|
//process_pb:
|
|
/*
|
|
* process the pb if ring pb callback exist
|
|
*/
|
|
if (pdev->ring_hdl.mpdu_pb_cb) {
|
|
ret = pdev->ring_hdl.mpdu_pb_cb(pdev, \
|
|
iot_pkt_array[0]);
|
|
if(CON_PKT_NOT_FREE == ret) //cert mode loopback
|
|
{
|
|
if (pb_st->last_pb) {
|
|
ring->cur_mpdu = NULL;
|
|
}
|
|
continue;
|
|
}
|
|
else if(CON_PKT_FREE == ret) //cert mode other test case
|
|
{
|
|
if (pb_st->first_pb && !pb_st->last_pb) {
|
|
/* if multi pb and first pb's freed
|
|
* we need to save the buf's mpdu_st desc
|
|
* or else the rest print info is not reliable
|
|
*/
|
|
goto save_mpdu_st_and_free;
|
|
}
|
|
|
|
goto free_pkt;
|
|
} else if (CON_PKT_NOT_CARE == ret) {
|
|
/* continue rx path */
|
|
}
|
|
}
|
|
|
|
/* get cert mode */
|
|
uint8_t cert_mode = mac_get_cert_test_mode();
|
|
|
|
if (pb_st->first_pb || ring->cur_mpdu) {
|
|
/* get info only first pb, used across mpdu */
|
|
/* get proto, deli, nid */
|
|
proto = mpdu_st->rx_proto;
|
|
|
|
delimiter_type = \
|
|
mac_get_rx_delimiter_from_fc(proto, \
|
|
mac_rx_mpdu_st_get_fc_addr(mpdu_st));
|
|
|
|
/* get rx fc message */
|
|
mac_get_rx_frm_msg_from_fc(proto, \
|
|
mac_rx_mpdu_st_get_fc_addr(mpdu_st), &rx_fc_msg);
|
|
nid = mac_get_nid_from_fc(proto, \
|
|
mac_rx_mpdu_st_get_fc_addr(mpdu_st));
|
|
#if (ENA_RX_DIFF_NID_BCAST)
|
|
mac_vdev_t *dft_vdev = find_vdev_by_nid(pdev->pdev_id, nid);
|
|
if ((FC_DELIM_SOF == delimiter_type)
|
|
&& (PLC_TEI_BCAST == rx_fc_msg.dst_tei)
|
|
&& !cert_mode) {
|
|
/* if bcast then force nid = local nid to rx in the
|
|
* same vdev.
|
|
*/
|
|
if (NULL == dft_vdev) {
|
|
//TODO: maybe use reduced vdev
|
|
dft_vdev = pdev->vdev[PLC_DEFAULT_VDEV];
|
|
}
|
|
vdev_get_nid(dft_vdev, &nid);
|
|
}
|
|
#endif
|
|
|
|
ret = phy_get_pb_size(proto, rx_fc_msg.tmi,
|
|
rx_fc_msg.tmi_ext, &pbsz);
|
|
if (ret!= ERR_OK) {
|
|
/* err handle */
|
|
iot_printf("pbsz get failed:tmi=%d,etmi=%d\n",
|
|
rx_fc_msg.tmi, rx_fc_msg.tmi_ext);
|
|
goto free_pkt;
|
|
}
|
|
|
|
} else {
|
|
/* no saved mpdu FC info, should
|
|
* not happen
|
|
*/
|
|
IOT_ASSERT_DUMP(0, (uint32_t * )att, 17);
|
|
goto free_pkt;
|
|
}
|
|
|
|
if (pb_st->last_pb) {
|
|
/* LED hook */
|
|
mac_rx_led_control(mpdu_st);
|
|
if (cert_mode && mac_cert_is_nid_valid(nid)) {
|
|
mac_check_spur_en(&pdev_t->mac_check_spur_ctxt, 0);
|
|
/* PHY channel estimation */
|
|
phy_info_check_entry(mpdu_st,
|
|
mac_rx_mpdu_st_get_fc_addr(mpdu_st), 0,
|
|
cert_mode);
|
|
}
|
|
|
|
/* last pb, clr the cur_mpdu */
|
|
ring->cur_mpdu = NULL;
|
|
mac_add_rx_mpdu_cnt();
|
|
}
|
|
|
|
/* find the vdev info, if no matching nid and
|
|
* not assoc yet,
|
|
* return the first vdev that nid = 0
|
|
*/
|
|
vdev = find_vdev_by_nid(pdev->pdev_id, nid);
|
|
peer = NULL;
|
|
stream = NULL;
|
|
is_vdev_found = 0;
|
|
is_not_my_ucast = 0;
|
|
|
|
if (pb_st->last_pb && vdev) {
|
|
/* save the rx time stamp */
|
|
vdev->last_rx_ntb = \
|
|
mac_rx_mpdu_end_get_ntb_timestamp(mpdu_ed);
|
|
}
|
|
|
|
proto_band_id = phy_hw_band_to_proto_band(mpdu_st->rx_band_sel);
|
|
mac_scan_update_rx_status(&pdev->scan, &rx_fc_msg,
|
|
(uint8_t)proto_band_id);
|
|
|
|
switch (delimiter_type)
|
|
{
|
|
case FC_DELIM_SOF:
|
|
{
|
|
#if (PLC_MAC_RX_DEBUG_LOG > PLC_MAC_LOG_LEVEL_2)
|
|
iot_printf("ssn = %d, msdu_start = %d, msdu_end = %d\n", \
|
|
pb_st->ssn, pb_st->msdu_start, pb_st->msdu_end);
|
|
iot_dbglog_input(PLC_MAC_RX_HW_MID, DBGLOG_INFO_LVL_2,
|
|
IOT_MAC_RX_PB_HEADER_ID, 3,\
|
|
pb_st->ssn, pb_st->msdu_start, pb_st->msdu_end);
|
|
|
|
mem_dump((uint32_t *)att, 0x50);
|
|
#endif
|
|
if (!vdev) {
|
|
/* vdev not found, drop this SOF by
|
|
* force crc error
|
|
*/
|
|
pb_ed->rx_pb_crc_err = 1;
|
|
#if (SIMU_DBG == 1)
|
|
iot_printf("simu_dbg, mac drop package, vdev not found\n");
|
|
#endif
|
|
goto handle_sof;
|
|
}
|
|
else {
|
|
is_vdev_found = 1;
|
|
}
|
|
|
|
/* remove interference from other network packets */
|
|
if ((CERT_TEST_CMD_ENTER_MAC_T == cert_mode)
|
|
&& !mac_cert_is_nid_valid(nid)) {
|
|
pb_ed->rx_pb_crc_err = 1;
|
|
goto handle_sof;
|
|
}
|
|
|
|
/* fix spg msdu_start/msdu_end */
|
|
if (PLC_PROTO_TYPE_SPG == proto) {
|
|
/**
|
|
* sof msdu_start and msdu_end
|
|
* fields always 0 in SPG protocol
|
|
*/
|
|
if (0 == mac_rx_pb_st_get_ssn(pb_st)) {
|
|
mac_rx_pb_st_set_msdu_start(pb_st, 1);
|
|
}
|
|
/* spg must be used long mpdu tx */
|
|
if (mac_rx_pb_st_get_last_pb(pb_st) &&
|
|
(rx_fc_msg.pb_num == (mac_rx_pb_st_get_ssn(pb_st) + 1))) {
|
|
mac_rx_pb_st_set_msdu_end(pb_st, 1);
|
|
}
|
|
}
|
|
|
|
/* handle bcast */
|
|
if (rx_fc_msg.dst_tei != PLC_TEI_BCAST) {
|
|
/* for uni-cast.
|
|
* for SPG, when not assoc,
|
|
* the CCO might reply with dtei with future tei or 0,
|
|
* we need receive this kind of packet
|
|
*
|
|
*/
|
|
nid_t temp;
|
|
uint8_t unicast_check = 0;
|
|
if (rx_fc_msg.dst_tei != vdev_get_tei(vdev)) {
|
|
if (mac_vdev_cfg_get_node_role(vdev) ==
|
|
PLC_DEV_ROLE_CCO) {
|
|
if (vdev_get_nid(vdev, &temp) == ERR_OK) {
|
|
unicast_check = 1;
|
|
}
|
|
/* for cco, if the networking is not started
|
|
* (NID is not set), try to receive all unicast
|
|
* packets.
|
|
*/
|
|
} else {
|
|
unicast_check = (PLC_PROTO_TYPE_SPG == proto) ?
|
|
(vdev_get_tei(vdev) != 0) : 1;
|
|
}
|
|
if (unicast_check
|
|
&& mac_judge_is_not_self_pkt(proto, vdev, pb_st,
|
|
pb_ed, payload)) {
|
|
/* not directed for me
|
|
* drop right now
|
|
*/
|
|
pb_ed->rx_pb_crc_err = 1;
|
|
is_not_my_ucast = 1;
|
|
#if (SIMU_DBG == 1)
|
|
iot_printf("simu_dbg, mac drop package,"
|
|
"rx_fc_msg.dst_tei:%d, vdev_get_tei(vdev):%d\n",
|
|
rx_fc_msg.dst_tei, vdev_get_tei(vdev));
|
|
#endif
|
|
goto handle_sof;
|
|
}
|
|
}
|
|
/* receive a unicast */
|
|
mac_add_rx_unicast_cnt();
|
|
|
|
//log for sof uncast info
|
|
mac_rx_debug_log_sof_uicast_info(rx_fc_msg, \
|
|
mpdu_st, mpdu_ed, pb_st, raw_snr);
|
|
|
|
peer = find_peer(vdev, nid, \
|
|
(tei_t)rx_fc_msg.src_tei);
|
|
}
|
|
else {
|
|
/* for bcast */
|
|
mac_add_rx_broadcast_cnt();
|
|
peer = vdev->bcast_peer;
|
|
IOT_ASSERT(peer);
|
|
|
|
//log for sof bcast
|
|
mac_rx_debug_log_sof_bcast_info(rx_fc_msg,
|
|
mpdu_st, mpdu_ed, pb_st, raw_snr);
|
|
}
|
|
|
|
#if ENA_WAR_396_DEBUG
|
|
/* check if this pb valid, for some HW error
|
|
* case, pb crc correct but it's wrong */
|
|
if ((pb_ed->rx_pb_crc_err == 0)
|
|
&& !mac_rx_check_pb_st_ssn_valid(proto, pbsz,
|
|
rx_fc_msg.pb_num, pb_st)) {
|
|
/* error case */
|
|
static uint32_t g_wrong_pbcrc_cnt = 0;
|
|
uint32_t *p =
|
|
(uint32_t *) (((uint8_t *) iot_pkt_array[0])
|
|
- 16);
|
|
(void) p;
|
|
iot_printf("Wrong RX PBCRC result from HW, pbsz:%d, cnt:%d.\n",
|
|
pbsz, ++g_wrong_pbcrc_cnt);
|
|
/* check next pkt whether overwrite */
|
|
if (iot_pkt_check_end_overwrite(iot_pkt_array[0])) {
|
|
mem_dump(p, (ring->buf_sz >> 1) + 12);
|
|
IOT_ASSERT_DUMP(0, p, (ring->buf_sz >> 1) + 12);
|
|
}
|
|
pb_ed->rx_pb_crc_err = 1;
|
|
goto handle_sof;
|
|
}
|
|
#if ENA_SW_PBCRC_CHECK
|
|
if (pb_ed->rx_pb_crc_err == 0) {
|
|
uint32_t pb_head = \
|
|
mac_desc_get_pb_head_from_rx_pb_st(proto, pb_st);
|
|
uint32_t crc_cal;
|
|
|
|
crc_cal = mac_crc_get_pb_swcrc(proto, &pb_head, \
|
|
payload, pbsz, FC_DELIM_SOF);
|
|
if (crc_cal != mac_rx_pb_end_get_pb_crc(pb_ed)) {
|
|
pb_ed->rx_pb_crc_err = 1;
|
|
goto handle_sof;
|
|
}
|
|
}
|
|
#endif
|
|
#endif
|
|
|
|
/* find the peer and stream info */
|
|
if (!peer) {
|
|
/* if the peer is not exist,
|
|
* create it right now
|
|
*/
|
|
ret = mac_peer_alloc(vdev, \
|
|
(tei_t)rx_fc_msg.src_tei, \
|
|
0, 1, 0, 0, &peer);
|
|
if (ret) {
|
|
/* create peer failed */
|
|
IOT_ASSERT(0);
|
|
}
|
|
}
|
|
|
|
stream = find_stream(peer, nid,
|
|
(tei_t)rx_fc_msg.src_tei,
|
|
(lid_t)rx_fc_msg.lid, IS_RX_STREAM, IS_PLC_STREAM);
|
|
if (!stream) {
|
|
/* if stream is not found
|
|
* create it now
|
|
*/
|
|
ret = mac_stream_alloc(peer, IS_RX_STREAM,
|
|
(lid_t)rx_fc_msg.lid, IS_PLC_STREAM,
|
|
&stream);
|
|
if (ret != ERR_OK && ret != ERR_EXIST) {
|
|
/* create stream failed */
|
|
IOT_ASSERT(0);
|
|
}
|
|
}
|
|
|
|
#if MAC_STREAM_TIMEOUT_SUPPORT
|
|
//updata rate info last rx ntb
|
|
mac_peer_rx_ts_update(peer, cur_ts);
|
|
mac_vdev_sort_peer_list(vdev, peer);
|
|
#else
|
|
(void)cur_ts;
|
|
#endif
|
|
/* handle pb flag check */
|
|
if (pb_st->first_pb) {
|
|
is_retry_mpdu = \
|
|
rx_fc_msg.retry;
|
|
}
|
|
|
|
handle_sof:
|
|
#if MAC_RX_2PB_WAR
|
|
/* NOTE: war fo dingxin 2pb.
|
|
* 1. we can't take 2PB packets of Dingxin,
|
|
* only the first package can be received correctly.
|
|
* 2. if the first pb already contains all valid data,
|
|
* and the second pb just contains msdu crc.
|
|
* 3. we can dorp data of second pb,
|
|
* and make an MSDU CRC to fill the second PB.
|
|
* 4. so uplayer can see this package and handle.
|
|
*/
|
|
if (pb_ed->rx_pb_crc_err == 1 && is_not_my_ucast == 0 &&
|
|
is_vdev_found == 1 && rx_fc_msg.pb_num == 2 &&
|
|
pb_st->first_pb == 0 && pb_st->last_pb == 1) {
|
|
/* get the first pb */
|
|
reorder_msdu_buf_t *spg_msdu =
|
|
&stream->msdu.rx.reorder_buf;
|
|
pb_buf_list_t *spg_1st_pbuf = &spg_msdu->pb_list;
|
|
if (spg_1st_pbuf->pb_buf == NULL) {
|
|
/* first pb rx error */
|
|
goto spg_war_handle;
|
|
}
|
|
/* get pld of the first pb */
|
|
uint8_t *fst_pbbuf = iot_pkt_data(spg_1st_pbuf->pb_buf)
|
|
+ PB_PAYLOAD_OFFSET;
|
|
/* get mac header len */
|
|
spg_mac_header_t *spg_mac = (spg_mac_header_t *)fst_pbbuf;
|
|
uint32_t mac_hdr_len = 0;
|
|
if (spg_mac->mac_hdr_type) {
|
|
mac_hdr_len = sizeof(spg_mac_header_t);
|
|
} else {
|
|
mac_hdr_len = sizeof(spg_mac_header_t) +
|
|
sizeof(spg_mac_lheader_tail_t);
|
|
}
|
|
/* get msdu len in the first pb */
|
|
uint32_t pb_data_size = pbsz - mac_hdr_len -
|
|
mac_get_pb_hdr_resv_crc_len(FC_DELIM_SOF,
|
|
PLC_PROTO_TYPE_SPG);
|
|
|
|
#if (PLC_MAC_RX_DEBUG_LOG > PLC_MAC_LOG_LEVEL_2)
|
|
iot_printf("dingxin war ssn:%d, msdu_st:%d, "
|
|
"msdu_ed:%d, hdr_type:%d, snid:%d, msdu_len:%d, "
|
|
"mac_hdr_len:%d, pb_valid_data:%d\n",
|
|
spg_1st_pbuf->ssn, spg_1st_pbuf->msdu_start,
|
|
spg_1st_pbuf->msdu_end, spg_mac->mac_hdr_type,
|
|
spg_mac->snid, spg_mac->msdu_len,
|
|
mac_hdr_len, pb_data_size);
|
|
#endif
|
|
/* if all msdu data in the first pb */
|
|
if (spg_mac->msdu_len <= pb_data_size) {
|
|
iot_printf("rx 2sec pb fail and war it for spg\n");
|
|
uint32_t msdu_rsv_crc =
|
|
pb_data_size - spg_mac->msdu_len;
|
|
/* calculate msdu crc */
|
|
uint8_t *msdu_valid_buf = fst_pbbuf + mac_hdr_len;
|
|
uint32_t msdu_crc = iot_getcrc32(msdu_valid_buf,
|
|
spg_mac->msdu_len);
|
|
if (msdu_rsv_crc < SPG_MAC_MSDU_CRC_LEN) {
|
|
/* 1.MSDU CRC at the beginning of next pb crc
|
|
* fill the crc to 2sec pb
|
|
* 2.one part of MSDU CRC is in the first Pb,
|
|
* and the other part of MSDU CRC is
|
|
* in the second PB
|
|
*/
|
|
uint8_t *msdu_crc_t = (uint8_t *)&msdu_crc;
|
|
/* fill the crc to 2sec pb */
|
|
os_mem_cpy(payload, msdu_crc_t + msdu_rsv_crc,
|
|
SPG_MAC_MSDU_CRC_LEN - msdu_rsv_crc);
|
|
} else {
|
|
/* the next pb has no valid data and no MSDU CRC */
|
|
}
|
|
/* modify desc */
|
|
pb_st->ssn = 1;
|
|
mac_rx_pb_st_set_msdu_end(pb_st, 1);
|
|
pb_ed->rx_pb_crc_err = 0;
|
|
}
|
|
}
|
|
spg_war_handle:
|
|
#endif
|
|
if (pb_ed->rx_pb_crc_err == 0) {
|
|
#if (PLC_MAC_RX_DEBUG_LOG > PLC_MAC_LOG_LEVEL_2)
|
|
iot_printf("%s, msdu->buf = %p", \
|
|
__FUNCTION__, iot_pkt_array[0]);
|
|
iot_dbglog_input(PLC_MAC_RX_HW_MID, DBGLOG_INFO,
|
|
IOT_MAC_RX_BUF_ID, 1, iot_pkt_array[0]);
|
|
#endif
|
|
#if DEBUG_SPG_PER_MSDU_MPDU_RX
|
|
if ((PLC_PROTO_TYPE_SPG == proto) \
|
|
&& (mac_rx_pb_st_get_ssn(pb_st) != 0) \
|
|
&& (136 == pbsz)) {
|
|
IOT_ASSERT_DUMP(0, (uint32_t *)iot_pkt_block_ptr(\
|
|
iot_pkt_array[0], IOT_PKT_BLOCK_DATA), 16);
|
|
}
|
|
#endif
|
|
|
|
reorder_buf_insert(&stream->msdu.rx.reorder_buf, \
|
|
iot_pkt_array[0], \
|
|
mac_rx_pb_st_get_ssn(pb_st), \
|
|
mac_rx_pb_st_get_msdu_start(pb_st), \
|
|
mac_rx_pb_st_get_msdu_end(pb_st), \
|
|
is_retry_mpdu, \
|
|
pbsz
|
|
);
|
|
}
|
|
else {
|
|
int16_t ppm_err = PLC_MAX_MAC_NTB_PPM;
|
|
uint32_t rate_id = MAX_RATE_IDX;
|
|
(void)rate_id;
|
|
(void)ppm_err;
|
|
|
|
ppm_err = (int16_t)mac_multi_sync_get_ppm(pdev->pdev_id,
|
|
nid);
|
|
|
|
if (is_not_my_ucast == 0 && is_vdev_found == 1)
|
|
{
|
|
/*sof err cnt*/
|
|
mac_add_rx_sof_pb_err_cnt();
|
|
#if MAC_RID_PBNUM_FLASH_LOG
|
|
/*record sof err cnt by rid and pbnum*/
|
|
ret = phy_find_rid_by_tmi((uint8_t)proto,\
|
|
phy_proto_single_band_id_get(),\
|
|
&rate_id, rx_fc_msg.tmi, rx_fc_msg.tmi_ext);
|
|
if (ret == ERR_OK && rate_id != MAX_RATE_IDX) {
|
|
mac_add_sof_err_cnt(proto, rate_id, \
|
|
(uint8_t)mac_rx_mpdu_st_get_rx_pb_num(mpdu_st));
|
|
}
|
|
#endif
|
|
mem_dump((uint32_t *)mpdu_st, sizeof(*mpdu_st)>>2);
|
|
}
|
|
#if (PLC_MAC_RX_DEBUG_LOG >= PLC_MAC_LOG_LEVEL_1)
|
|
iot_printf("sof pb dropped:"\
|
|
"not_my_ucast = %d,"\
|
|
"vdev_found = %d,"
|
|
"rid = %d,"
|
|
#if MAC_RID_PBNUM_FLASH_LOG
|
|
"sof_err_cnt = %d, "
|
|
#endif
|
|
"sw_multi_ppm = %d, "
|
|
"ppm = %d, dtei = %d, stei = %d, nid = 0x%x\n",\
|
|
is_not_my_ucast,\
|
|
is_vdev_found,
|
|
rate_id,
|
|
#if MAC_RID_PBNUM_FLASH_LOG
|
|
mac_get_sof_err_cnt(proto, rate_id,\
|
|
(uint8_t)mac_rx_mpdu_st_get_rx_pb_num(mpdu_st)),
|
|
#endif
|
|
ppm_err,
|
|
mac_rx_mpdu_st_get_estimated_ppm(mpdu_st),
|
|
rx_fc_msg.dst_tei,
|
|
rx_fc_msg.src_tei,
|
|
rx_fc_msg.nid);
|
|
iot_dbglog_input(PLC_MAC_RX_HW_MID, \
|
|
DBGLOG_INFO_LVL_2, \
|
|
IOT_MAC_RX_SOF_DROP_ID, \
|
|
3, is_not_my_ucast, is_vdev_found,\
|
|
mac_rx_mpdu_st_get_estimated_ppm(mpdu_st) \
|
|
);
|
|
#endif
|
|
#if (SIMU_DBG == 1)
|
|
iot_printf("simu_dbg, mac drop package," \
|
|
" sof pb dropped\n");
|
|
#endif
|
|
|
|
if (pb_st->first_pb && !pb_st->last_pb) {
|
|
/* if multi pb and first pb's crc err
|
|
* we need to save the buf's mpdu_st desc
|
|
* or else the rest print info is not reliable
|
|
*/
|
|
goto save_mpdu_st_and_free;
|
|
}
|
|
|
|
/* NOTE: if rx pkt pb error,
|
|
* alloc peer and stream need free.
|
|
* especially, spg not joined net, it will receive unicast.
|
|
* if this pkt pb is error, allco peer/stream need free.
|
|
*/
|
|
if (vdev) {
|
|
if (vdev_get_tei(vdev) == 0 &&
|
|
rx_fc_msg.dst_tei != PLC_TEI_BCAST && peer) {
|
|
mac_peer_del_temp_peer(peer);
|
|
}
|
|
}
|
|
|
|
goto free_pkt;
|
|
}
|
|
|
|
break;
|
|
}
|
|
case FC_DELIM_BEACON:
|
|
{
|
|
uint32_t rate_mode = mac_rx_mpdu_st_get_rx_rate_mode(mpdu_st);
|
|
uint32_t local_ts = mac_rx_mpdu_end_get_local_timestamp(mpdu_ed);
|
|
uint8_t est_ppm = mac_rx_mpdu_st_get_estimated_ppm(mpdu_st);
|
|
uint32_t ntb_ts = mac_rx_mpdu_end_get_ntb_timestamp(mpdu_ed);
|
|
snr = mac_rx_mpdu_st_get_avg_snr(mpdu_st);
|
|
uint8_t is_chk_bcn_ppm = 1;
|
|
uint8_t is_self_nid = 0;
|
|
|
|
/* TODO: remove the next line later */
|
|
(void)ntb_ts;
|
|
//log for beacon info
|
|
mac_rx_debug_log_bcn_info(&rx_fc_msg, \
|
|
mpdu_st, mpdu_ed, pb_ed, raw_snr);
|
|
|
|
if (!vdev) {
|
|
/* force first vdev, and upload all bcn */
|
|
vdev = g_mac_pdev[PLC_PDEV_ID]->vdev[PLC_DEFAULT_VDEV];
|
|
if ((mac_vdev_cfg_get_node_role(vdev) \
|
|
== PLC_DEV_ROLE_INVALID)) {
|
|
/* only upload for valid role */
|
|
goto free_pkt;
|
|
}
|
|
}
|
|
|
|
node_role = mac_vdev_cfg_get_node_role(vdev);
|
|
|
|
{
|
|
uint32_t *fc = \
|
|
(uint32_t*)mac_rx_mpdu_st_get_fc_addr(mpdu_st);
|
|
if (!mac_rx_hw_check_fc_valid(fc)) {
|
|
/* HWWAR for all 0s FC */
|
|
pb_ed->rx_pb_crc_err = 1;
|
|
goto free_pkt;
|
|
}
|
|
}
|
|
|
|
ret = mac_filter_bcn_by_band(proto, proto_band_id);
|
|
if (ret != ERR_OK) {
|
|
iot_printf("rx bcn band:%d fliter!\n", proto_band_id);
|
|
goto free_pkt;
|
|
}
|
|
|
|
nid_t cur_my_nid = PLC_NID_INVALID;
|
|
vdev_get_nid(vdev, &cur_my_nid);
|
|
if (cert_mode == CERT_TEST_CMD_NOT_RX) {
|
|
/* if not cert mode, then we need age out
|
|
* the ppm data to support more CCOs
|
|
*/
|
|
mac_multi_sync_nid_timeout_clear(pdev->pdev_id);
|
|
}
|
|
/* my ppm is updated via single PPM case down below
|
|
* my nid's ntb/ppm sync need to be done with my
|
|
* proxy tei, it would be more accurate, so only update
|
|
* other nid's ntb/ppm here */
|
|
(void)mac_multi_ppm_record(pdev->pdev_id, nid,
|
|
cur_my_nid, rate_mode, rx_fc_msg.time_stamp,
|
|
local_ts, ntb_ts,
|
|
DEF_MULTI_SYNC_PERIOD, PLC_MAX_MAC_NTB_PPM);
|
|
|
|
/* crystal ppm error sync */
|
|
#if CPLC_IOT_CERT_SUPPORT
|
|
if (cert_mode)
|
|
{
|
|
/* or if CERT test mode's CCO
|
|
* and NID = 0's bcn, use it to
|
|
* sync the crystal freq error
|
|
*/
|
|
if (mac_cert_is_nid_valid(nid)) {
|
|
int16_t ppm_cert = PLC_MAX_MAC_NTB_PPM;
|
|
mac_ntb_ppm_sync(&vdev->mac_ppm,
|
|
rate_mode,
|
|
rx_fc_msg.time_stamp,
|
|
local_ts,
|
|
ntb_ts,
|
|
est_ppm,
|
|
&ppm_cert, vdev_get_bc_period_ms(vdev, proto),
|
|
true);
|
|
/* use the first stable ppm in cert loopback mode */
|
|
if (cert_mode == CERT_TEST_CMD_ENTER_PHY_LP) {
|
|
if (mac_get_lp_cal_ppm_is_hold()) {
|
|
mac_scan_set_bb_ppm(&vdev->mac_ppm,
|
|
-mac_get_rcd_lp_ppm(),
|
|
0, BB_PPM_TXRX);
|
|
ppm_cert = PLC_MAX_MAC_NTB_PPM;
|
|
} else {
|
|
if (ppm_cert != PLC_MAX_MAC_NTB_PPM) {
|
|
int8_t rcdppm = (int8_t)(ppm_cert >>
|
|
PLC_NTB_PPM_SHIFT);
|
|
if (!mac_get_is_not_first_cal_lp_ppm()) {
|
|
mac_set_rcd_lp_ppm(rcdppm);
|
|
mac_set_not_first_cal_lp_ppm(1);
|
|
} else {
|
|
int8_t dltppm =
|
|
mac_get_rcd_lp_ppm() - rcdppm;
|
|
if (IOT_ABS(dltppm) < 3) {
|
|
iot_printf("mac cert lp mode "
|
|
"hold ppm:%d\n", rcdppm);
|
|
mac_set_lp_cal_ppm_hold(1);
|
|
}
|
|
mac_set_rcd_lp_ppm(rcdppm);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/* stop the scan to sync the bcn
|
|
* test mode no need to scan the band
|
|
*/
|
|
//mac_scan_stop(&pdev->scan);
|
|
phy_set_sw_nn_ppm_para(0, 0,
|
|
ppm_cert >> PLC_NTB_PPM_SHIFT);
|
|
phy_set_sw_nn_ppm_para(1, nid,
|
|
ppm_cert >> PLC_NTB_PPM_SHIFT);
|
|
}
|
|
}
|
|
else
|
|
#endif
|
|
if ((nid != PLC_NID_INVALID)
|
|
&& (node_role == PLC_DEV_ROLE_STA))
|
|
{
|
|
/* if STA mode
|
|
* we need to sync the crystal disparity
|
|
*/
|
|
nid_t my_nid;
|
|
tei_t my_proxy = vdev_get_proxy_tei(vdev);
|
|
|
|
vdev_get_nid(vdev, &my_nid);
|
|
|
|
if (my_nid == nid) {
|
|
/* sync with joined network if available */
|
|
if ((rx_fc_msg.src_tei == my_proxy)) {
|
|
int16_t ppm_err = PLC_MAX_MAC_NTB_PPM;
|
|
mac_ntb_ppm_sync(&vdev->mac_ppm, rate_mode, \
|
|
rx_fc_msg.time_stamp, local_ts, ntb_ts, \
|
|
est_ppm, &ppm_err,
|
|
vdev_get_bc_period_ms(vdev, proto), true);
|
|
|
|
(void)mac_multi_ppm_record(pdev->pdev_id, my_nid,
|
|
my_nid, rate_mode, rx_fc_msg.time_stamp,
|
|
local_ts, ntb_ts,
|
|
DEF_MULTI_SYNC_PERIOD,
|
|
ppm_err);
|
|
#if K48_STA_MULTI_CHANNEL_SELECT_ENABLE
|
|
iot_mac_k48sta_scan_channel_stop(pdev);
|
|
#endif
|
|
is_chk_bcn_ppm = 0;
|
|
}
|
|
|
|
mac_ppm_record_handle(vdev, nid, &rx_fc_msg,
|
|
local_ts, ntb_ts, proto);
|
|
is_self_nid = 1;
|
|
}
|
|
}
|
|
|
|
if (pb_ed->rx_pb_crc_err)
|
|
{
|
|
mac_add_rx_bcn_pb_err_cnt();
|
|
if (rx_fc_msg.src_tei == PLC_TEI_CCO) {
|
|
mac_sched_cco_snr_rx(vdev, nid, snr,
|
|
RF_CHANNEL_ID_INVALID, 0, 0,
|
|
(uint8_t)proto_band_id);
|
|
}
|
|
/* free the error pb */
|
|
goto free_pkt;
|
|
}
|
|
if (!mac_tx_hw_get_bcn_swcrc_cfg())
|
|
{
|
|
/* if hw bcn crc enabled */
|
|
if (pb_ed->rx_beacon_pld_crc_err)
|
|
{
|
|
mac_add_rx_pld_err_cnt();
|
|
/* free the error pb */
|
|
goto free_pkt;
|
|
}
|
|
}
|
|
|
|
/* if all crc is ok, start to process
|
|
* and for bcn, should be last pb, save
|
|
* snr first, will fill this into
|
|
* rx_info later
|
|
*/
|
|
if (!pb_st->last_pb) {
|
|
//IOT_ASSERT(pb_st->last_pb);
|
|
iot_printf("bcn has no last pb\n");
|
|
goto free_pkt;
|
|
}
|
|
|
|
rx_phase = (uint8_t)mpdu_st->rx_phase;
|
|
delta_ntb = rx_fc_msg.time_stamp -
|
|
mac_rx_mpdu_end_get_ntb_timestamp(mpdu_ed);
|
|
|
|
if ((node_role != PLC_DEV_ROLE_CCO)
|
|
&& !cert_mode && is_self_nid) {
|
|
if (is_chk_bcn_ppm && vdev->bcn_ctx.sta.ntb_sync_done) {
|
|
int16_t tmp_ppm;
|
|
mac_ntb_record_ctxt_t tmp_ntb_record;
|
|
os_mem_cpy(&tmp_ntb_record, &vdev->sync_ntb_record,
|
|
sizeof(tmp_ntb_record));
|
|
tmp_ppm = mac_ppm_cal(&tmp_ntb_record,
|
|
rx_fc_msg.time_stamp, local_ts, ntb_ts, 1);
|
|
if (IOT_ABS(tmp_ppm) > PLC_SYNC_NTB_MAX_PPM) {
|
|
delta_ntb = 0;
|
|
} else {
|
|
os_mem_cpy(&vdev->sync_ntb_record,
|
|
&tmp_ntb_record, sizeof(tmp_ntb_record));
|
|
}
|
|
} else {
|
|
os_mem_cpy(&vdev->sync_ntb_record,
|
|
&vdev->mac_ppm.ntb_record,
|
|
sizeof(vdev->sync_ntb_record));
|
|
}
|
|
}
|
|
|
|
/* pull a rx desc len, after this point, rx meta info
|
|
* is overwritten with mac_rx_info_t.
|
|
*/
|
|
/* iot_pkt_array[0]'s data pointer is at the
|
|
* beginning. the following is att, mpdu_st, ...
|
|
* so we need to make sure the rx_info_t's
|
|
* memcpy is not overlay with previous FC.
|
|
* if it really does, we need to make some
|
|
* special action to copy this FC
|
|
*/
|
|
BUILD_BUG_ON(sizeof(mac_rx_info_t) < PB_PAYLOAD_OFFSET \
|
|
- sizeof(*att) - sizeof(frame_control_t));
|
|
mac_rx_info_t *p =
|
|
(mac_rx_info_t *)iot_pkt_pull(iot_pkt_array[0], \
|
|
PB_PAYLOAD_OFFSET - sizeof(mac_rx_info_t));
|
|
uint8_t *bcn_pld = \
|
|
iot_pkt_pull(iot_pkt_array[0], sizeof(mac_rx_info_t));
|
|
os_mem_cpy(&p->fc, mac_rx_mpdu_st_get_fc_addr(mpdu_st), \
|
|
sizeof(frame_control_t));
|
|
rssi = PHY_RSSI_FROM_RMI_GAIN(
|
|
mac_rx_mpdu_st_get_adc_power(mpdu_st),
|
|
mac_rx_mpdu_st_get_agc_gain_entry(mpdu_st));
|
|
/* TODO: remove this MAX/MIN and do it in PHY */
|
|
if (rssi != INV_RSSI) {
|
|
rssi = min(MAX_RSSI, rssi);
|
|
rssi = max(MIN_RSSI, rssi);
|
|
}
|
|
|
|
p->delta_ntb = delta_ntb;
|
|
p->phy.band_id = (uint8_t)proto_band_id;
|
|
p->phy.phase = rx_phase;
|
|
/* fill in snr saved before */
|
|
p->phy.snr = snr;
|
|
p->phy.rssi = PHY_RSSI_DBUV_TO_DBM(rssi);
|
|
p->phy.is_rf = 0;
|
|
p->phy.channel_id = RF_CHANNEL_ID_INVALID;
|
|
p->phy.rf_option = RF_OPTION_INVALID;
|
|
/* get the bcn pb sz and shrink the real bcn size */
|
|
ret = (uint32_t)iot_pkt_set_tail(iot_pkt_array[0], \
|
|
bcn_pld + pbsz);
|
|
if (ret == 0) {
|
|
iot_printf("pkt=0x%x, bcn_pld=0x%x, pbsz=%d\n",
|
|
iot_pkt_array[0], bcn_pld, pbsz);
|
|
IOT_ASSERT_DUMP(0,(uint32_t*)iot_pkt_array[0],17);
|
|
goto free_pkt;
|
|
}
|
|
/* upload to upper layer */
|
|
if (vdev->start_cfg.mac_bc_rx_func) {
|
|
#if defined(SIMU_NTB_SYNC)
|
|
nid_t simu_nid;
|
|
vdev_get_nid(vdev, &simu_nid); //TODO:
|
|
if ((node_role != PLC_DEV_ROLE_CCO) \
|
|
&& (nid == simu_nid))
|
|
{
|
|
vdev_ntb_sync(\
|
|
g_mac_pdev[pdev_id]->vdev[vdev_id], \
|
|
rx_fc_msg.time_stamp);
|
|
#if (PLC_MAC_RX_DEBUG_LOG)
|
|
iot_printf("vdev ntb %ld\n",
|
|
vdev_ntb_get(
|
|
g_mac_pdev[pdev_id]->vdev[vdev_id]));
|
|
iot_dbglog_input(PLC_MAC_RX_HW_MID, DBGLOG_INFO,
|
|
IOT_MAC_RX_VDEV_NTB_ID, 1,\
|
|
vdev_ntb_get(
|
|
g_mac_pdev[pdev_id]->vdev[vdev_id]));
|
|
#endif
|
|
}
|
|
#endif
|
|
mac_add_rx_bcn_ok_cnt();
|
|
mac_beacon_rx((uint8_t)proto, vdev, iot_pkt_array[0]);
|
|
#if DBG_RX_ABORT_REASON_4 == 1
|
|
/* correct bcn received, clear the cnt */
|
|
pdev->cont_rx_abort4_cnt = 0;
|
|
#endif
|
|
}
|
|
else {
|
|
/* free this frame */
|
|
goto free_pkt;
|
|
}
|
|
|
|
break;
|
|
}
|
|
case FC_DELIM_SACK:
|
|
{
|
|
if (rx_fc_msg.sack_ext_deli == SACK_EXT_TYPE_SYNC || \
|
|
rx_fc_msg.sack_ext_deli == SACK_EXT_TYPE_SEARCH) {
|
|
mac_ckq_rx_and_ppm_sync(pdev, vdev, &rx_fc_msg, \
|
|
iot_pkt_array[0]);
|
|
} else {
|
|
if (!vdev) {
|
|
/* vdev not found, drop this SACK
|
|
*/
|
|
goto free_pkt;
|
|
}
|
|
if (rx_fc_msg.dst_tei != \
|
|
vdev_get_tei(vdev)){
|
|
/* if not dest for me, drop it */
|
|
goto free_pkt;
|
|
}
|
|
|
|
peer = find_peer(vdev, nid, \
|
|
(tei_t)rx_fc_msg.src_tei);
|
|
|
|
if (!peer) {
|
|
/* if the peer is not exist,
|
|
* create it right now
|
|
*/
|
|
ret = mac_peer_alloc(vdev, \
|
|
(tei_t)rx_fc_msg.src_tei, \
|
|
0, 1, 0, 0, &peer);
|
|
if (ret) {
|
|
/* create peer failed */
|
|
IOT_ASSERT(0);
|
|
}
|
|
}
|
|
|
|
/* update the rate info in peer */
|
|
if (vdev->ra_cb) {
|
|
vdev->ra_cb(peer, &rx_fc_msg);
|
|
}
|
|
|
|
/* free temp peer */
|
|
mac_peer_del_temp_peer(peer);
|
|
|
|
goto free_pkt;
|
|
}
|
|
break;
|
|
}
|
|
case FC_DELIM_NNCCO:
|
|
{
|
|
/* TODO: handle nncco or RTS-CTS*/
|
|
if (PLC_PROTO_TYPE_GP == proto)
|
|
{
|
|
mac_rx_debug_log_for_gp(rx_fc_msg.rtsf);
|
|
goto free_pkt;
|
|
}
|
|
else {
|
|
void *fc = mac_rx_mpdu_st_get_fc_addr(mpdu_st);
|
|
proto_band_id =
|
|
phy_hw_band_to_proto_band(mpdu_st->rx_band_sel);
|
|
uint32_t rxntb =
|
|
mac_rx_mpdu_end_get_ntb_timestamp(mpdu_ed);
|
|
|
|
if (mac_get_cert_test_flag() &&
|
|
USER_TYPE_STATE_GRID_XIAN ==
|
|
iot_oem_get_user_type()) {
|
|
/* modify rxntb(-3ms) for sanxi cert test */
|
|
rxntb -= 75000;
|
|
}
|
|
|
|
mac_sched_nn_rx(pdev,
|
|
fc, rxntb,
|
|
mac_rx_mpdu_st_get_avg_snr(mpdu_st), 0,
|
|
(uint8_t)proto_band_id);
|
|
|
|
#if (PLC_MAC_RX_DEBUG_LOG >= PLC_MAC_LOG_LEVEL_1)
|
|
iot_printf("NNCCO rx - st:%d,dur:%d, s_nid:0x%x, "
|
|
"r_nid:0x%x, rx_ts:%u\n",
|
|
mac_get_nncco_protect_region_offset(proto, fc),
|
|
mac_get_nncco_protect_dur(proto, fc),
|
|
mac_get_nid_from_fc(proto, fc),
|
|
mac_get_nncco_received_nid(proto, fc), rxntb);
|
|
iot_dbglog_input(PLC_MAC_RX_HW_MID, DBGLOG_INFO_LVL_1,
|
|
IOT_MAC_RX_NNCCO_ID, 0);
|
|
#endif
|
|
goto free_pkt;
|
|
}
|
|
break;
|
|
}
|
|
|
|
case I1901_RTS_CTS:
|
|
{
|
|
if (SUPPORT_IEEE_1901 && (PLC_PROTO_TYPE_SG == proto)) {
|
|
i1901_frame_control_t *i1901_fc;
|
|
i1901_fc = (i1901_frame_control_t *)
|
|
mac_rx_mpdu_st_get_fc_addr(mpdu_st);
|
|
iot_printf("rtscts rx, stei:%d, dtei:%d, rtsf:%d, "
|
|
"dur:%d\n",
|
|
rx_fc_msg.src_tei, rx_fc_msg.dst_tei,
|
|
rx_fc_msg.rtsf, i1901_fc->vf.rts_cts.dur);
|
|
} else {
|
|
iot_printf("invalid proto %d deli %d\n",
|
|
proto, delimiter_type);
|
|
}
|
|
goto free_pkt;
|
|
}
|
|
default:
|
|
{
|
|
/* TODO: other mpdu */
|
|
iot_printf("-----Unknown MPDU!-----\n");
|
|
iot_dbglog_input(PLC_MAC_RX_HW_MID, DBGLOG_WARN,
|
|
IOT_MAC_RX_UNKNOW_MPDU_ID, 0);
|
|
mac_add_rx_mpdu_type_err_cnt();
|
|
#if PLC_HW_ISSUE_ASSERT_LEVEL <= PLC_HW_ISSUE_ASSERT_CRITICAL
|
|
mem_dump((uint32_t *)att, 16);
|
|
IOT_ASSERT(0);
|
|
#endif
|
|
goto free_pkt;
|
|
}
|
|
} // switch (delimiter_type)
|
|
/* done the switch case for type processing */
|
|
}
|
|
else {
|
|
/* should rx done */
|
|
iot_printf("-----Not done PB!-----\n");
|
|
iot_dbglog_input(PLC_MAC_RX_HW_MID, DBGLOG_WARN,
|
|
IOT_MAC_RX_MPDU_NOTDONE_ID, 0);
|
|
#if WAR_MPDU_NOT_DONE
|
|
ring->not_done = 4;
|
|
#endif
|
|
#if PLC_HW_ISSUE_ASSERT_LEVEL <= PLC_HW_ISSUE_ASSERT_ALL
|
|
mem_dump((uint32_t *)iot_pkt_array[0], 20);
|
|
IOT_ASSERT_DUMP(0, (uint32_t *)att, 17);
|
|
#endif
|
|
goto free_pkt;
|
|
}
|
|
}
|
|
else {
|
|
/* ring empty, get out normally */
|
|
break;
|
|
}
|
|
|
|
//next_pkt:
|
|
/* need up layer to free the pkt for successful case */
|
|
continue;
|
|
|
|
save_mpdu_st_and_free:
|
|
/* save the current mpdu_st and then free the pb */
|
|
os_mem_cpy(&ring->saved_mpdu_st, mpdu_st,
|
|
sizeof(ring->saved_mpdu_st));
|
|
ring->cur_mpdu = &ring->saved_mpdu_st;
|
|
|
|
free_pkt:
|
|
/* free the error pb and continue rx next pkt */
|
|
iot_pkt_free(iot_pkt_array[0]);
|
|
continue;
|
|
|
|
/* if rest time is not enough, break and
|
|
* back later
|
|
*/
|
|
} while (os_boot_time32() - cur_ts < quota_ms);
|
|
|
|
return 0;
|
|
}
|
|
|
|
uint32_t mac_rx_hw_mpdu(void *pdev, uint32_t ring_id, uint32_t quota_ms)
|
|
{
|
|
uint32_t ret = ERR_OK;
|
|
rx_buf_ring_t *ring;
|
|
#if HW_PLATFORM == HW_PLATFORM_SIMU
|
|
ring = &((mac_pdev_t*)pdev)->simu.rx_ring[ring_id];
|
|
#else
|
|
ring = &((mac_pdev_t*)pdev)->ring_hdl.ring[ring_id];
|
|
#endif
|
|
|
|
if (!ring->msg_delivered) {
|
|
/* if not delivered, queue the msg */
|
|
mac_msg_t *msg = mac_alloc_msg();
|
|
|
|
if (msg == NULL) {
|
|
IOT_ASSERT(0);
|
|
ret = ERR_NOMEM;
|
|
goto out;
|
|
}
|
|
|
|
msg->type = MAC_MSG_TYPE_DSR;
|
|
msg->id = MAC_MSG_ID_DSR_RX_TO_MSG;
|
|
/* bit0~bit15: ring id.
|
|
* bit16: indicate ring type. 0 - plc ring, 1 - rf ring.
|
|
*/
|
|
msg->data1 = ring_id & 0xFFFF;
|
|
msg->data2 = pdev;
|
|
msg->data3 = (void*)quota_ms;
|
|
mac_queue_msg(msg, MAC_MSG_QUEUE_MP);
|
|
|
|
/* TODO: this is assume in the same task of MAC */
|
|
ring->msg_delivered = 1;
|
|
}
|
|
|
|
out:
|
|
return ret;
|
|
}
|
|
|
|
|