Files
kunlun/plc/halmac/rx/rx_pb_reorder.c
2024-09-28 14:24:04 +08:00

755 lines
24 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 "rx_pb_reorder.h"
#include "iot_errno.h"
#include "iot_io.h"
#include "mac_data_api.h"
#include "mac_desc_engine.h"
#include <math.h>
#include "hw_tonemap.h"
#include "mac_stream.h"
#include "mac_vdev.h"
#include "mac_peer.h"
#include "mac_data.h"
#include "mac_rx_hw.h"
#include "phy_bb.h"
#include "mpdu_header.h"
#include "iot_dbglog_api.h"
#include "iot_dbglog_parser.h"
#if ENA_ALWAYS_SET_RETRY_BIT == 0
#include "mac_cert_test.h"
#endif
#if HPLC_RF_DEV_SUPPORT
#include "rf_hw_tonemap.h"
#include "mac_rf_rx_buf_ring.h"
#endif
inline uint32_t pb_buf_list_init(pb_buf_list_t *pb,
uint32_t msdu_st,
uint32_t msdu_ed,
uint32_t ssn,
iot_pkt_t *pb_buf)
{
pb->msdu_end = msdu_ed;
pb->msdu_start = msdu_st;
pb->next = NULL;
pb->pb_buf = pb_buf;
pb->ssn = ssn;
return ERR_OK;
}
uint32_t reorder_buf_init(
reorder_msdu_buf_t *msdu, \
void *stream /* refer stream */
)
{
(void)stream;
/* temp solution */
if (!msdu /*|| !stream*/)
{
return ERR_INVAL;
}
msdu->pb_rdy_cnt = 0;
msdu->pb_total_cnt = INV_PB_TOTAL_CNT;
pb_buf_list_init(&msdu->pb_list, \
0, 0, 0, NULL);
msdu->pb_alloc_cnt = 1;
msdu->is_reused = 0;
return 0;
}
uint32_t reorder_buf_free(reorder_msdu_buf_t *msdu)
{
uint32_t pb_buf_cnt = 1;
pb_buf_list_t *entry = msdu->pb_list.next;
pb_buf_list_t *tmp = entry;
if(msdu->pb_list.pb_buf){
iot_pkt_free(msdu->pb_list.pb_buf);
}
for(;pb_buf_cnt <= msdu->pb_alloc_cnt;){
if(tmp == NULL){
break;
}
entry = tmp->next;
if(tmp->pb_buf){
iot_pkt_free(tmp->pb_buf);
}
os_mem_set(tmp, 0, sizeof(pb_buf_list_t));
mac_desc_free(&g_mac_desc_eng, \
PLC_RX_PB_DESC_POOL,tmp);
tmp = entry;
pb_buf_cnt++;
}
IOT_ASSERT(pb_buf_cnt == msdu->pb_alloc_cnt && tmp == NULL);
return ERR_OK;
}
uint32_t reorder_buf_free_pb_list(reorder_msdu_buf_t *msdu)
{
uint32_t pb_buf_cnt = 1;
pb_buf_list_t *entry = msdu->pb_list.next;
pb_buf_list_t *tmp = entry;
for(;pb_buf_cnt < msdu->pb_alloc_cnt;){
if(tmp == NULL){
break;
}
entry = tmp->next;
if(tmp->pb_buf){
iot_pkt_free(tmp->pb_buf);
}
tmp->next = NULL;
mac_desc_free(&g_mac_desc_eng, \
PLC_RX_PB_DESC_POOL,tmp);
tmp = entry;
pb_buf_cnt++;
}
IOT_ASSERT(pb_buf_cnt == msdu->pb_alloc_cnt && tmp == NULL);
msdu->pb_alloc_cnt = 1;
msdu->pb_list.next = NULL;
return ERR_OK;
}
uint32_t reorder_buf_init_first_pb(
reorder_msdu_buf_t *msdu, \
uint32_t pkt_size, /* msdu buf len */
void *stream, /* refer stream */
uint32_t msdu_st,
uint32_t msdu_ed,
uint32_t ssn,
/* must be the msdu_start pb if not null,
* to optimize the memory usage,
* we can use the same pb buf if
* the msdu len is smaller than
* the pb size
*/
iot_pkt_t *pb_buf
)
{
(void)stream;
if (!msdu)
{
return ERR_INVAL;
}
if (pb_buf) {
if (ssn != 0 || msdu_st != 1) {
/* must be the first pb */
return ERR_INVAL;
}
rx_buf_hdr_t *hdr = \
(rx_buf_hdr_t *)iot_pkt_data(pb_buf);
IOT_ASSERT(hdr->pb_st.msdu_start
&& hdr->pb_ed.rx_pb_crc_err == 0
/* && hdr->mpdu_st.fc.sg_fc.vf.sof.retry == 0 */
);
msdu->pb_rdy_cnt = 1;
if (pkt_size) {
msdu->pb_total_cnt =
(uint32_t)iot_ceil(pkt_size, \
iot_pkt_data_len(pb_buf));
}
else {
msdu->pb_total_cnt = INV_PB_TOTAL_CNT;
}
}
else {
msdu->pb_rdy_cnt = 0;
msdu->pb_total_cnt = INV_PB_TOTAL_CNT;
}
pb_buf_list_init(&msdu->pb_list, \
msdu_st, msdu_ed, ssn, pb_buf);
msdu->pb_alloc_cnt = 1;
msdu->is_reused = 0;
return 0;
}
/* flush the reorder buf
* reset the msdu's counter
* and free all the pb_bufs,
* but keep the pb_buf_list allocated for fast allocation.
* usually called when a new msdu's pb received
*/
uint32_t reorder_buf_flush(reorder_msdu_buf_t *msdu)
{
uint32_t pb_buf_cnt = 0;
if (!msdu) {
return ERR_INVAL;
}
pb_buf_list_t *pb = &msdu->pb_list;
do {
if (pb->pb_buf) {
iot_pkt_free(pb->pb_buf);
pb->pb_buf = NULL;
}
pb_buf_cnt++;
pb = pb->next;
} while (pb);
if (pb_buf_cnt != msdu->pb_alloc_cnt) {
*(uint32_t *)(msdu + 1) = pb_buf_cnt;
IOT_ASSERT_DUMP(0, (uint32_t *)msdu, \
sizeof(*msdu)/sizeof(uint32_t) + 1);
}
msdu->pb_rdy_cnt = 0;
msdu->pb_total_cnt = INV_PB_TOTAL_CNT;
return ERR_OK;
}
#if DEBUG_PKT_OVERFLOW
//TODO:for debug iot_pkt set newtail assert bug, and put off later
typedef struct _dump_buf {
uint32_t p_data;
uint32_t p_end;
uint32_t buf_len;
uint32_t resv_len;
uint8_t fc[16];
}dump_buf_t;
#endif
/* release the msdu */
uint32_t reorder_buf_release(reorder_msdu_buf_t *msdu)
{
nid_t nid;
void *fc = NULL;
rx_buf_hdr_t *hdr;
if (!msdu) {
return ERR_INVAL;
}
IOT_ASSERT(msdu->pb_rdy_cnt == msdu->pb_total_cnt \
&& msdu->pb_rdy_cnt <= msdu->pb_alloc_cnt);
mac_peer_t *peer = NULL;
mac_stream_t *stream = NULL;
mac_vdev_t *vdev = NULL;
iot_pkt_t *msdu_buf, *pb_buf;
uint32_t proto = PHY_PROTO_TYPE_GET();
uint32_t pb_hdr_resv_crc_len = mac_get_pb_hdr_resv_crc_len(FC_DELIM_SOF,
proto);
pb_buf_list_t *pb = &msdu->pb_list;
pb_buf = pb->pb_buf;
stream = container_of(msdu, mac_stream_t, msdu.rx.reorder_buf);
if (pb_buf == NULL) {
mac_add_rx_msdu_null_first_pb_cnt();
if (stream && stream->peer) {
vdev = get_vdev_ptr(stream->peer->pdev_id, stream->peer->vdev_id);
vdev_get_nid(vdev, &nid);
iot_printf("msdu rx null pb, nid%d, tei%d, lid%d, "
"msdu_null_first_pb_cnt=%u\n", \
nid, \
stream->peer->tei, \
stream->lid, mac_get_rx_msdu_null_first_pb_cnt());
}
#if !WAR_BUGID757_EN
IOT_ASSERT(0);
#endif
reorder_buf_flush(msdu);
return ERR_INVAL;
}
uint32_t pb_sz = PB_SIZE_INV, ret, msdu_pad_len, pb_buf_aval_len, i = 0;
int8_t snr = INVALID_SNR;
uint8_t phase = PLC_PHASE_ALL;
uint32_t req_buf_len;
uint8_t rssi = INV_RSSI;
int8_t rf_rssi = INV_RSSI_RF;
uint8_t channel_id = 0;
/* get rx message from fc */
rx_fc_msg_t msg = {0};
if (!stream->is_rf) {
hdr = (rx_buf_hdr_t *)iot_pkt_data(pb_buf);
IOT_ASSERT(hdr->pb_st.msdu_start && (hdr->pb_ed.rx_pb_crc_err == 0));
fc = mac_rx_mpdu_st_get_fc_addr(&hdr->mpdu_st);
if (hdr->pb_st.first_pb) {
/* get the default snr if only one pb */
snr = mac_rx_mpdu_st_get_avg_snr(&hdr->mpdu_st);
phase = mac_rx_mpdu_st_get_rx_phase(&hdr->mpdu_st);
rssi = PHY_RSSI_FROM_RMI_GAIN(
mac_rx_mpdu_st_get_adc_power(&hdr->mpdu_st),
mac_rx_mpdu_st_get_agc_gain_entry(&hdr->mpdu_st));
if (rssi != INV_RSSI) {
rssi = min(MAX_RSSI, rssi);
rssi = max(MIN_RSSI, rssi);
}
}
mac_get_rx_frm_msg_from_fc(proto, fc, &msg);
ret = phy_get_pb_size(proto, msg.tmi, msg.tmi_ext, &pb_sz);
IOT_ASSERT(0 == ret);
if (pb_sz == PB_SIZE_INV) {
iot_printf("pb_sz err,tmi=%d,ex_tmi=%d\n", msg.tmi, msg.tmi_ext);
return ERR_INVAL;
}
} else {
#if HPLC_RF_DEV_SUPPORT
rf_rx_buf_hdr_t *rf_hdr;
rf_hdr = (rf_rx_buf_hdr_t *)iot_pkt_data(pb_buf);
IOT_ASSERT(rf_hdr->pb_ed.rx_pb_crc_err == 0);
fc = mac_rf_rx_mpdu_st_get_phr_addr(&rf_hdr->mpdu_st);
snr = mac_rf_rx_mpdu_st_get_avg_snr(&rf_hdr->mpdu_st);
rf_rssi = mac_rf_rx_mpdu_st_get_rssi(&rf_hdr->mpdu_st);
if (rssi != INV_RSSI_RF) {
rf_rssi = min(MAX_RSSI_RF, rf_rssi);
rf_rssi = max(MIN_RSSI_RF, rf_rssi);
}
mac_get_rx_frm_msg_from_fc(proto, fc, &msg);
pb_sz = phy_rf_get_pbsz(msg.rf_pb_sz_idx);
#else
(void)rf_rssi;
/* if not support rf, stream->is_rf must be 0 */
IOT_ASSERT_DUMP(0, (uint32_t *)msdu, sizeof(*msdu));
#endif
}
/* aval len for first pb */
pb_buf_aval_len = iot_pkt_data_len(pb_buf) \
+ iot_pkt_tail_len(pb_buf);
msdu_pad_len = (pb_sz) * msdu->pb_total_cnt;
req_buf_len = RX_FWD_RESV_LEN
+ (pb_sz - pb_hdr_resv_crc_len) * msdu->pb_total_cnt;
if (((pb_buf_aval_len - sizeof(rx_buf_hdr_t)) >= ((req_buf_len) - \
RX_FWD_RESV_LEN)) && (sizeof(rx_buf_hdr_t) >= RX_FWD_RESV_LEN)) {
/* pb buf could be reused as msdu buf because the len is enough,
* as long as header size is adequate and no need to copy
*/
/* skip the written rx buf header
* before this, the data pointer is at 0 offset
*/
uint8_t *pkt = iot_pkt_pull(pb_buf, sizeof(rx_buf_hdr_t));
if (pkt == NULL) {
IOT_ASSERT(0);
return ERR_FAIL;
}
iot_pkt_set_tail(pb_buf, pkt + pb_sz - pb_hdr_resv_crc_len);
msdu_buf = pb_buf;
msdu->is_reused = 1;
}
else {
/* if the left space for the first pb is not enough
* we have to try to alloc a new msdu buf
*/
IOT_PKT_GET(msdu_buf, req_buf_len, RX_FWD_RESV_LEN, PLC_MAC_RX_MID);
if (!msdu_buf) {
uint32_t bufsz;
uint32_t freenum[IOT_PKT_POOL_MAX] = {0};
uint32_t totalnum;
iot_printf("no buf for msdu 0x%x forming, msdu dropped.\n", msdu);
uint8_t j;
for (j = 0; j < IOT_PKT_POOL_MAX; j++) {
iot_pkt_pktpool_status(j, &bufsz, freenum + j, &totalnum);
}
mac_pdev_t *pdev_t = g_mac_pdev[PLC_PDEV_ID];
rx_buf_ring_t *ring0 = &pdev_t->ring_hdl.ring[0];
uint32_t ring0_dp = (ring0->read_idx <<16 & 0xffff0000) | \
(ring0->write_idx & 0xffff);
rx_buf_ring_t *ring1 = &pdev_t->ring_hdl.ring[1];
uint32_t ring1_dp = (ring1->read_idx <<16 & 0xffff0000) | \
(ring1->write_idx & 0xffff);
iot_printf("req_buf_len:%d, pb_sz:%d, cnt:%d, free0:%d, free1:%d"\
"free2:%d, free3:%d,free4:%d, free5:%d, ring0 w:%d, r:%d, "\
"ring1 w:%d, r:%d\n",req_buf_len, pb_sz, msdu->pb_total_cnt,\
freenum[0], freenum[1], freenum[2], freenum[3], freenum[4],\
freenum[5], ring0->write_idx, ring0->read_idx, \
ring1->write_idx, ring1->read_idx);
uint32_t * dump_buf_addr = (uint32_t *)pb_buf - 11;
*dump_buf_addr = req_buf_len;
*(dump_buf_addr + 1) = pb_sz;
*(dump_buf_addr + 2) = msdu->pb_total_cnt;
*(dump_buf_addr + 3) = freenum[0];
*(dump_buf_addr + 4) = freenum[1];
*(dump_buf_addr + 5) = freenum[2];
*(dump_buf_addr + 6) = freenum[3];
*(dump_buf_addr + 7) = freenum[4];
*(dump_buf_addr + 8) = freenum[5];
*(dump_buf_addr + 9) = ring0_dp;
*(dump_buf_addr + 10) = ring1_dp;
IOT_ASSERT_DUMP(0, (uint32_t *)dump_buf_addr, \
(pb_buf_aval_len/sizeof(uint32_t))+12);
//IOT_ASSERT(0);
return ERR_FAIL;
}
msdu->is_reused = 0;
}
uint8_t *dest = iot_pkt_data(msdu_buf);
uint32_t copy_bytes = pb_sz - pb_hdr_resv_crc_len;
do {
if (msdu->is_reused && i == 0) {
/* skip the first node if reused */
i++;
pb = pb->next;
continue;
}
if (pb->pb_buf) {
dest = iot_pkt_put(msdu_buf, copy_bytes);
IOT_ASSERT(dest && pb->ssn == i);
os_mem_cpy(dest + i * copy_bytes, \
iot_pkt_data(pb->pb_buf) + sizeof(rx_buf_hdr_t), \
copy_bytes);
iot_pkt_free(pb->pb_buf);
pb->pb_buf = NULL;
}
else {
#if ENABLE_PER_PB_RETRY
/* pb_buf should be exist for per pb case */
iot_printf("pb ssn%d buf not enough\n", i);
IOT_ASSERT(0);
#endif
return ERR_FAIL;
}
i++;
pb = pb->next;
} while (pb && i < msdu->pb_total_cnt);
/* copy mac_rx_info_t */
mac_rx_info_t *rx_info = (mac_rx_info_t *)(dest - sizeof(mac_rx_info_t));
/* todo: mac_convert_fc_rf_to_hplc() */
os_mem_cpy(rx_info->fc, fc, sizeof(rx_info->fc));
/* for sof frame, this value is set to 0 by default */
rx_info->delta_ntb = 0;
if (snr != INVALID_SNR) {
rx_info->phy.snr = snr;
}
else {
/* no last pb's snr info, should
* not happen
* TODO: check if this could save from the lower layer
*/
rx_info->phy.snr = snr;
}
rx_info->phy.phase = phase;
rx_info->phy.is_rf = stream->is_rf;
if (rx_info->phy.is_rf) {
rx_info->phy.rssi = rf_rssi;
} else {
rx_info->phy.rssi = PHY_RSSI_DBUV_TO_DBM(rssi);
}
rx_info->phy.band_id = (uint8_t)phy_band_id_get();
rx_info->phy.channel_id = channel_id;
/* set tail ptr to msdu pad len */
#if DEBUG_PKT_OVERFLOW
//TODO:for debug iot_pkt set newtail assert bug, and put off later
if(((uint8_t *)(iot_pkt_data(msdu_buf) + req_buf_len - RX_FWD_RESV_LEN) < \
msdu_buf->data) || \
((uint8_t *)(iot_pkt_data(msdu_buf) + req_buf_len - RX_FWD_RESV_LEN) > \
msdu_buf->end))
{
iot_printf("tail err! data:%p, end:%p, buf_len:%d, resv_len:%d\n",
iot_pkt_data(msdu_buf), \
iot_pkt_block_ptr(msdu_buf, IOT_PKT_BLOCK_END),\
req_buf_len, RX_FWD_RESV_LEN);
dump_buf_t dump_buf;
dump_buf.p_data = (uint32_t)iot_pkt_data(msdu_buf);
dump_buf.p_end = (uint32_t)iot_pkt_block_ptr(msdu_buf, IOT_PKT_BLOCK_END);
dump_buf.buf_len = req_buf_len;
dump_buf.resv_len = RX_FWD_RESV_LEN;
//for debug pbsize = 0
os_mem_cpy(dump_buf.fc, fc, sizeof(dump_buf.fc));
IOT_ASSERT_DUMP(0, (uint32_t *)&dump_buf, 4);
}
#endif
dest = iot_pkt_set_tail(msdu_buf, \
iot_pkt_data(msdu_buf) + req_buf_len - RX_FWD_RESV_LEN);
IOT_ASSERT(dest);
/* upload to upper layer */
#if PLC_MAC_RX_DEBUG_LOG
iot_printf("msdu pad len %d formed with %d PBs\n", \
msdu_pad_len, \
msdu->pb_total_cnt);
iot_dbglog_input(PLC_MAC_REORDER_MID, DBGLOG_INFO_LVL_2,
IOT_MAC_PLD_INFO, 2, \
msdu_pad_len, \
msdu->pb_total_cnt);
#else
(void)msdu_pad_len;
#endif
//IOT_ASSERT(stream && stream->peer && get_vdev_ptr(stream->peer->pdev_id,
// stream->peer->vdev_id));
if (stream && stream->peer)
{
peer = stream->peer;
vdev = get_vdev_ptr(peer->pdev_id, peer->vdev_id);
if (vdev) {
mac_data_rx_msdu(vdev, msdu_buf);
}
}
else {
iot_pkt_free(msdu_buf);
}
/* TODO: release desc every release to save some STA's memory here,
* but CCO could ignore this to save some cpu cycle
*/
reorder_buf_free_pb_list(msdu);
/* after release, do some clean job */
if (msdu->is_reused) {
/* for reuse case, don't free the first pb
* as upper layer to free it,
* but set pb_buf list to NULL to avoid double free when flush
* other pb already freed when copy done
*/
if (msdu->pb_list.pb_buf) {
msdu->pb_list.pb_buf = NULL;
}
}
msdu->pb_rdy_cnt = 0;
msdu->pb_total_cnt = INV_PB_TOTAL_CNT;
if (peer && peer->is_bcast_peer && !stream->is_tx
&& !msdu->is_reused) {
/* if bcast peer, release the stream to save some memory */
mac_stream_free(peer, stream);
}
mac_peer_del_temp_peer(peer);
return ERR_OK;
}
/*
* insert to exist msdu reorder structure
*/
uint32_t reorder_buf_insert(reorder_msdu_buf_t *msdu,
iot_pkt_t *pb_buf, uint32_t ssn, uint32_t msdu_start,
uint32_t msdu_end, uint32_t is_retry, uint32_t pbsz)
{
pb_buf_list_t *pb, *tmp, *tmp_next;
mac_stream_t *stream;
rx_buf_hdr_t *hdr, *tmp_hdr;
uint32_t ret, i, dup = 0;
#if HPLC_RF_DEV_SUPPORT
rf_rx_buf_hdr_t *rf_hdr, *tmp_rf_hdr;
#endif
if (!msdu || !pb_buf || ssn == INV_PB_SSN \
|| msdu_start > 1 || msdu_end > 1) {
return ERR_INVAL;
}
stream = container_of(msdu, mac_stream_t, msdu.rx.reorder_buf);
hdr = (rx_buf_hdr_t *)iot_pkt_data(pb_buf);
if (!stream->is_rf) {
IOT_ASSERT(hdr->pb_ed.rx_pb_crc_err == 0);
} else {
#if HPLC_RF_DEV_SUPPORT
rf_hdr = (rf_rx_buf_hdr_t *)hdr;
IOT_ASSERT(rf_hdr->pb_ed.rx_pb_crc_err == 0);
#else
IOT_ASSERT_DUMP(0, (uint32_t *)stream, sizeof(*stream));
#endif
/* check rf rx */
#if HPLC_RF_MPDU_SINGLE_PB
if (!msdu_end || !msdu_start || ssn) {
iot_printf("[WARN]rf rx msdu_end:%d, msdu_start:%d, ssn:%d\n",
msdu_end, msdu_start, ssn);
msdu_end = 1;
msdu_start = 1;
ssn = 0;
}
#endif
}
if (pbsz != msdu->pbsz || (is_retry == 0 && ssn == 0)) {
/* if pbsz changed */
reorder_buf_flush(msdu);
}
if (msdu_end) {
if ((INV_PB_TOTAL_CNT != msdu->pb_total_cnt) && \
(msdu->pb_total_cnt != (ssn + 1))) {
/* rx diff pb cnt msdu(bcast msdu), flush old msdu*/
reorder_buf_flush(msdu);
}
/* update total cnt if msdu end */
msdu->pb_total_cnt = ssn + 1;
}
/* find the place to insert */
for (i = 0, tmp = &msdu->pb_list, tmp_next = tmp->next;
i <= ssn; i++, tmp = tmp->next, tmp_next = tmp->next) {
if (tmp->ssn == ssn) {
/* insert */
/* check crc */
if (tmp->pb_buf) {
if (!stream->is_rf) {
hdr = (rx_buf_hdr_t *)iot_pkt_data(pb_buf);
tmp_hdr = (rx_buf_hdr_t *)iot_pkt_data(tmp->pb_buf);
if (mac_rx_pb_end_get_pb_crc(&hdr->pb_ed)
== mac_rx_pb_end_get_pb_crc(&tmp_hdr->pb_ed)) {
/* dup pb received */
/* free the old pb buf */
iot_pkt_free(tmp->pb_buf);
tmp->pb_buf = NULL;
dup = 1;
} else {
/* we should flush, as the new pb arrived */
reorder_buf_flush(msdu);
}
} else {
#if HPLC_RF_DEV_SUPPORT
rf_hdr = (rf_rx_buf_hdr_t *)hdr;
tmp_rf_hdr = (rf_rx_buf_hdr_t *)iot_pkt_data(tmp->pb_buf);
if (mac_rf_rx_pb_end_get_pb_crc(&rf_hdr->pb_ed)
== mac_rf_rx_pb_end_get_pb_crc(&tmp_rf_hdr->pb_ed)) {
/* dup pb received */
/* free the old pb buf */
iot_pkt_free(tmp->pb_buf);
tmp->pb_buf = NULL;
dup = 1;
} else {
/* we should flush, as the new pb arrived */
reorder_buf_flush(msdu);
}
#else
IOT_ASSERT_DUMP(0, (uint32_t *)stream, sizeof(*stream));
#endif
}
}
/* update the current pb */
tmp->msdu_end = msdu_end;
tmp->msdu_start = msdu_start;
tmp->pb_buf = pb_buf;
break;
}
else {
if (tmp->ssn != INV_PB_SSN) {
/* check the tmp's ssn, it should be seq */
IOT_ASSERT(tmp->ssn == i);
}
else {
/* if tmp's ssn is not inited, init it here */
tmp->ssn = i;
}
}
if (i != ssn && !tmp_next) {
/* allocate a new pb_list if not reach end
* but pb_list not enough
*/
ret = mac_desc_get(&g_mac_desc_eng,
PLC_RX_PB_DESC_POOL, (void **)&pb);
if (ret) {
/* TODO: clean process? */
IOT_ASSERT_DUMP(0, &ssn, 1);
return ERR_NOMEM;
}
msdu->pb_alloc_cnt++;
/* init the new pb_buf_list */
pb_buf_list_init(pb, 0, 0, i + 1, NULL);
tmp->next = pb;
tmp_next = pb;
}
}
if (!dup) {
msdu->pb_rdy_cnt++;
if (msdu->pb_rdy_cnt > msdu->pb_alloc_cnt) {
iot_printf("pb rdy %d > pb alloc %d\n", msdu->pb_rdy_cnt,
msdu->pb_alloc_cnt);
IOT_ASSERT(0);
}
msdu->pbsz = pbsz;
}
if (msdu->pb_rdy_cnt > msdu->pb_total_cnt) {
#if ENABLE_PER_PB_RETRY
/* per pb retry should not get more pb */
iot_printf("pb_rdy_cnt:%d > pb_total_cnt:%d\n", \
msdu->pb_rdy_cnt, msdu->pb_total_cnt);
#if ENA_ALWAYS_SET_RETRY_BIT == 0
#if CPLC_IOT_CERT_SUPPORT
if (!mac_get_cert_test_flag())
#endif
{
iot_dbglog_input(PLC_MAC_REORDER_MID, DBGLOG_ERR,
IOT_MAC_PB_CNT_ID, 3, \
msdu->pb_rdy_cnt, msdu->pb_total_cnt, msdu->pb_alloc_cnt);
#if SUPPORT_SOUTHERN_POWER_GRID
reorder_msdu_dbg_t msdu_dbg[4];
for (i = 0, tmp = &msdu->pb_list; (i < 4) && tmp;
i++, tmp = tmp->next) {
msdu_dbg[i].ssn = tmp->ssn;
msdu_dbg[i].msdu_end = tmp->msdu_end;
msdu_dbg[i].msdu_start = tmp->msdu_start;
msdu_dbg[i].resv0 = 0;
os_mem_cpy(msdu_dbg[i].desc, iot_pkt_data(tmp->pb_buf), 64);
}
IOT_ASSERT_DUMP(0, (uint32_t *)msdu_dbg, (i * \
sizeof(reorder_msdu_dbg_t)) / sizeof(uint32_t));
#else //SUPPORT_SOUTHERN_POWER_GRID
/* remove assert. HW BUGID:757
* 1. first/second pb not receive in msdu0(>=3pb. eg: pb = 3),
* before receive this msdu1(=2pb).
* and maybe hw pbbuf overlap, so pb_total_cnt not assigned.
* eg: msdu0 3pb. just 3rd(ssn = 2) rx successed.
* pb_rdy_cnt = 1. pb_total_cnt = INV_PB_TOTAL_CNT.
* 2. first receive msdu1, just received 2nd pb.
* but not received 1st pb, so go to msdu rx null pb(line260),
* and return, not post to uplayer.
* and msdu rx null pb(line260),not clear pb_rdy_cnt/pb_total_cnt.
* eg: msdu1 2pb. just 2nd(ssn = 1) rx successed.
* pb_rdy_cnt = 2. pb_total_cnt = 2.
* 3. secend/more time receive msdu1, receive first pb.
* crash here.
* eg: msdu1 2pb. 1st(ssn = 0) rx successed.
* pb_rdy_cnt = 3. pb_total_cnt = 2.
* so remove assert, make pb_rdy_cnt=pb_total_cnt(line670),
* and post to uplayer. if 2/3 step not same msdu,
* msdu crc can check out and free.
*/
#if !WAR_BUGID757_EN
IOT_ASSERT(0);
#endif
#endif
}
#endif //ENA_ALWAYS_SET_RETRY_BIT == 0
#endif //ENABLE_PER_PB_RETRY
msdu->pb_rdy_cnt = msdu->pb_total_cnt;
}
#if PLC_MAC_RX_DEBUG_LOG
iot_printf("pbcnt:%d/%d\n", msdu->pb_rdy_cnt, msdu->pb_total_cnt);
#endif
if (msdu->pb_rdy_cnt == msdu->pb_total_cnt) {
reorder_buf_release(msdu);
}
return ERR_OK;
}