755 lines
		
	
	
		
			24 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
		
		
			
		
	
	
			755 lines
		
	
	
		
			24 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 "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;
							 | 
						||
| 
								 | 
							
								}
							 |