499 lines
		
	
	
		
			15 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
		
		
			
		
	
	
			499 lines
		
	
	
		
			15 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 "mac_stream.h"
							 | 
						||
| 
								 | 
							
								#include "mac_desc_engine.h"
							 | 
						||
| 
								 | 
							
								#include "iot_errno.h"
							 | 
						||
| 
								 | 
							
								#include "hash_table.h"
							 | 
						||
| 
								 | 
							
								#include "sw_sched.h"
							 | 
						||
| 
								 | 
							
								#include "iot_io.h"
							 | 
						||
| 
								 | 
							
								#include "iot_dbglog_api.h"
							 | 
						||
| 
								 | 
							
								#include "iot_dbglog_parser.h"
							 | 
						||
| 
								 | 
							
								#include "os_utils_api.h"
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								typedef struct _mac_stream_vdev_dump_info {
							 | 
						||
| 
								 | 
							
								    uint32_t peer_cnt               : 16,
							 | 
						||
| 
								 | 
							
								        proxy_peer_cnt              : 16;
							 | 
						||
| 
								 | 
							
								    uint32_t stream_cnt             : 16,
							 | 
						||
| 
								 | 
							
								        rx_stream_cnt               : 16;
							 | 
						||
| 
								 | 
							
								    uint32_t stream_overflow_cnt    : 16,
							 | 
						||
| 
								 | 
							
								        rsvd                        : 16;
							 | 
						||
| 
								 | 
							
								} mac_stream_vdev_dump_info_t;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								typedef struct _mac_stream_exhausted_info {
							 | 
						||
| 
								 | 
							
								    uint32_t cur_ts;
							 | 
						||
| 
								 | 
							
								    mac_stream_vdev_dump_info_t vdev_info[MAX_VDEV_NUM];
							 | 
						||
| 
								 | 
							
								    mac_peer_t peer;
							 | 
						||
| 
								 | 
							
								} mac_stream_exhausted_info_t;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								mac_stream_t *g_stream_hash_tbl[stream_tbl_sz] = { 0 };
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								uint32_t stream_hash_tbl_get_hsahv(nid_t nid, tei_t tei, \
							 | 
						||
| 
								 | 
							
								    lid_t lid, uint8_t is_tx, uint8_t is_rf)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								    stream_hash_src_t hash_src = { 0 };
							 | 
						||
| 
								 | 
							
								    hash_src.nid = nid;
							 | 
						||
| 
								 | 
							
								    hash_src.tei = tei;
							 | 
						||
| 
								 | 
							
								    hash_src.lid = lid;
							 | 
						||
| 
								 | 
							
								    hash_src.is_tx= is_tx;
							 | 
						||
| 
								 | 
							
								    hash_src.is_rf = is_rf;
							 | 
						||
| 
								 | 
							
								    uint8_t *hash_str = (uint8_t*)&hash_src;
							 | 
						||
| 
								 | 
							
								    return ((stream_tbl_sz - 1) \
							 | 
						||
| 
								 | 
							
								        & iot_getcrc32(hash_str, sizeof(stream_hash_src_t)));
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/* @return stream address if found
							 | 
						||
| 
								 | 
							
								*            NULL if not found
							 | 
						||
| 
								 | 
							
								*/
							 | 
						||
| 
								 | 
							
								mac_stream_t * find_stream(mac_peer_t *peer_in, \
							 | 
						||
| 
								 | 
							
								    nid_t nid, tei_t tei, lid_t lid, uint8_t is_tx, uint8_t is_rf)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								    nid_t peer_nid = (nid_t)PLC_NID_INVALID;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    if (!nid && !peer_in) {
							 | 
						||
| 
								 | 
							
								        /* if nid = 0, peer_in must valid */
							 | 
						||
| 
								 | 
							
								        return NULL;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								    mac_vdev_t *vdev = get_vdev_ptr(peer_in->pdev_id, peer_in->vdev_id);
							 | 
						||
| 
								 | 
							
								    if (ERR_OK != vdev_get_nid(vdev, &peer_nid)) {
							 | 
						||
| 
								 | 
							
								        peer_nid = (nid_t)PLC_NID_INVALID;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								    if (peer_in->is_self_peer) {
							 | 
						||
| 
								 | 
							
								        if (PLC_NID_INVALID == peer_nid) {
							 | 
						||
| 
								 | 
							
								            /* not assoc yet, use the peer's vdev's nid instead */
							 | 
						||
| 
								 | 
							
								            nid = (nid_t)PLC_NID_INVALID;
							 | 
						||
| 
								 | 
							
								            tei = vdev_get_tei(vdev);
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								    } else if (peer_in->is_bcast_peer) {
							 | 
						||
| 
								 | 
							
								        /* else if bcast peer, and not assoc yet then
							 | 
						||
| 
								 | 
							
								         * ignore the nid of the packet, use
							 | 
						||
| 
								 | 
							
								         * the peer's vdev's nid instead
							 | 
						||
| 
								 | 
							
								         */
							 | 
						||
| 
								 | 
							
								        IOT_ASSERT(peer_in->tei == PLC_TEI_BCAST);
							 | 
						||
| 
								 | 
							
								        if (PLC_NID_INVALID == peer_nid) {
							 | 
						||
| 
								 | 
							
								            /* not assoc yet, use the peer's vdev's nid instead */
							 | 
						||
| 
								 | 
							
								            nid = (nid_t)PLC_NID_INVALID;
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								        tei = (tei_t)peer_in->tei;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    /* should be the correct peer */
							 | 
						||
| 
								 | 
							
								    IOT_ASSERT(peer_in->tei == tei);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    uint32_t hash_code = stream_hash_tbl_get_hsahv( \
							 | 
						||
| 
								 | 
							
								        nid, \
							 | 
						||
| 
								 | 
							
								        tei, \
							 | 
						||
| 
								 | 
							
								        lid,\
							 | 
						||
| 
								 | 
							
								        is_tx,\
							 | 
						||
| 
								 | 
							
								        is_rf);
							 | 
						||
| 
								 | 
							
								    mac_stream_t *tmp = \
							 | 
						||
| 
								 | 
							
								        g_stream_hash_tbl[hash_code];
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    mac_peer_t *peer;
							 | 
						||
| 
								 | 
							
								    /* look every node for the hash entry */
							 | 
						||
| 
								 | 
							
								    for (; tmp; tmp = tmp->next) {
							 | 
						||
| 
								 | 
							
								        peer = tmp->peer;
							 | 
						||
| 
								 | 
							
								        if (peer) {
							 | 
						||
| 
								 | 
							
								            vdev = get_vdev_ptr(peer->pdev_id, peer->vdev_id);
							 | 
						||
| 
								 | 
							
								            if (!vdev) {
							 | 
						||
| 
								 | 
							
								                continue;
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								        else {
							 | 
						||
| 
								 | 
							
								            continue;
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								        if ((tmp->lid == lid) \
							 | 
						||
| 
								 | 
							
								            && (peer->tei == tei) \
							 | 
						||
| 
								 | 
							
								            && (peer_nid == nid) \
							 | 
						||
| 
								 | 
							
								            && (tmp->is_tx == is_tx) \
							 | 
						||
| 
								 | 
							
								            && (tmp->is_rf == is_rf)) {
							 | 
						||
| 
								 | 
							
								            return tmp;
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								    return NULL;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/* @return - 0 for successful
							 | 
						||
| 
								 | 
							
								*           other for failed
							 | 
						||
| 
								 | 
							
								*/
							 | 
						||
| 
								 | 
							
								uint32_t stream_hash_tbl_add(mac_stream_t *stream)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								    if (!stream) {
							 | 
						||
| 
								 | 
							
								        return ERR_INVAL;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								    lid_t lid = stream->lid;
							 | 
						||
| 
								 | 
							
								    mac_peer_t *peer = stream->peer;
							 | 
						||
| 
								 | 
							
								    if (!peer) {
							 | 
						||
| 
								 | 
							
								        return ERR_INVAL;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								    tei_t tei = (tei_t)peer->tei;
							 | 
						||
| 
								 | 
							
								    mac_vdev_t *vdev = get_vdev_ptr(peer->pdev_id, peer->vdev_id);
							 | 
						||
| 
								 | 
							
								    if (!vdev) {
							 | 
						||
| 
								 | 
							
								        return ERR_INVAL;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								    nid_t nid;
							 | 
						||
| 
								 | 
							
								    vdev_get_nid(vdev, &nid);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    uint8_t is_tx = (uint8_t)stream->is_tx;
							 | 
						||
| 
								 | 
							
								    uint8_t is_rf = (uint8_t)stream->is_rf;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    if (find_stream(peer, nid, tei, lid, is_tx, is_rf)) {
							 | 
						||
| 
								 | 
							
								        return ERR_EXIST;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    mac_stream_t **tmp = \
							 | 
						||
| 
								 | 
							
								        &g_stream_hash_tbl[stream_hash_tbl_get_hsahv(nid, \
							 | 
						||
| 
								 | 
							
								        tei, lid, is_tx, is_rf)];
							 | 
						||
| 
								 | 
							
								    stream->next = *tmp;
							 | 
						||
| 
								 | 
							
								    *tmp = stream;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    return 0;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								uint32_t stream_hash_tbl_del(mac_stream_t *stream)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								    mac_stream_t *str = stream;
							 | 
						||
| 
								 | 
							
								    mac_stream_t **hash_table_entry;
							 | 
						||
| 
								 | 
							
								    mac_stream_t *entry = NULL;
							 | 
						||
| 
								 | 
							
								    tei_t tei;
							 | 
						||
| 
								 | 
							
								    nid_t nid;
							 | 
						||
| 
								 | 
							
								    if (str->peer) {
							 | 
						||
| 
								 | 
							
								        tei = (tei_t) str->peer->tei;
							 | 
						||
| 
								 | 
							
								        vdev_get_nid(get_vdev_ptr(str->peer->pdev_id, str->peer->vdev_id),
							 | 
						||
| 
								 | 
							
								            &nid); //TODO: check ret value
							 | 
						||
| 
								 | 
							
								    } else {
							 | 
						||
| 
								 | 
							
								        iot_printf("str lid=%d without peer\n", str->lid);
							 | 
						||
| 
								 | 
							
								        IOT_ASSERT(0);
							 | 
						||
| 
								 | 
							
								        tei = 0;
							 | 
						||
| 
								 | 
							
								        nid = 0;
							 | 
						||
| 
								 | 
							
								        return ERR_FAIL;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    /* for normal case */
							 | 
						||
| 
								 | 
							
								    hash_table_entry = &g_stream_hash_tbl[stream_hash_tbl_get_hsahv(nid,
							 | 
						||
| 
								 | 
							
								            tei, str->lid, (uint8_t)str->is_tx,
							 | 
						||
| 
								 | 
							
								            (uint8_t)str->is_rf)];
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    for(mac_stream_t **cur = hash_table_entry; *cur;){
							 | 
						||
| 
								 | 
							
								        entry = *cur;
							 | 
						||
| 
								 | 
							
								        if(str == entry){
							 | 
						||
| 
								 | 
							
								            *cur = entry->next;
							 | 
						||
| 
								 | 
							
								            break;
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								        else{
							 | 
						||
| 
								 | 
							
								           cur = &entry->next;
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    /* for nid valid but tei is 0 */
							 | 
						||
| 
								 | 
							
								    if(str != entry){
							 | 
						||
| 
								 | 
							
								        hash_table_entry = &g_stream_hash_tbl[stream_hash_tbl_get_hsahv( \
							 | 
						||
| 
								 | 
							
								            nid, 0, str->lid, (uint8_t)str->is_tx,
							 | 
						||
| 
								 | 
							
								            (uint8_t)str->is_rf)];
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        for(mac_stream_t **cur = hash_table_entry; *cur;){
							 | 
						||
| 
								 | 
							
								            entry = *cur;
							 | 
						||
| 
								 | 
							
								            if(str == entry){
							 | 
						||
| 
								 | 
							
								                *cur = entry->next;
							 | 
						||
| 
								 | 
							
								                break;
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								            else{
							 | 
						||
| 
								 | 
							
								                cur = &entry->next;
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    /* for nid invalid and tei invalid */
							 | 
						||
| 
								 | 
							
								    if(str != entry){
							 | 
						||
| 
								 | 
							
								        hash_table_entry = &g_stream_hash_tbl[stream_hash_tbl_get_hsahv( \
							 | 
						||
| 
								 | 
							
								            0, 0, str->lid, (uint8_t)str->is_tx,
							 | 
						||
| 
								 | 
							
								            (uint8_t)str->is_rf)];
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        for(mac_stream_t **cur = hash_table_entry; *cur;){
							 | 
						||
| 
								 | 
							
								            entry = *cur;
							 | 
						||
| 
								 | 
							
								            if(str == entry){
							 | 
						||
| 
								 | 
							
								                *cur = entry->next;
							 | 
						||
| 
								 | 
							
								                break;
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								            else{
							 | 
						||
| 
								 | 
							
								                cur = &entry->next;
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    /* for bcast when nid invalid */
							 | 
						||
| 
								 | 
							
								    if(str != entry){
							 | 
						||
| 
								 | 
							
								        hash_table_entry = &g_stream_hash_tbl[stream_hash_tbl_get_hsahv(0, tei,
							 | 
						||
| 
								 | 
							
								                str->lid, (uint8_t)str->is_tx,
							 | 
						||
| 
								 | 
							
								                (uint8_t)str->is_rf)];
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        for(mac_stream_t **cur = hash_table_entry; *cur;){
							 | 
						||
| 
								 | 
							
								            entry = *cur;
							 | 
						||
| 
								 | 
							
								            if(str == entry){
							 | 
						||
| 
								 | 
							
								                *cur = entry->next;
							 | 
						||
| 
								 | 
							
								                break;
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								            else{
							 | 
						||
| 
								 | 
							
								                cur = &entry->next;
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    if (str != entry) {
							 | 
						||
| 
								 | 
							
								        /* if not bcast peer for this stream
							 | 
						||
| 
								 | 
							
								         * we need check where is gone
							 | 
						||
| 
								 | 
							
								         */
							 | 
						||
| 
								 | 
							
								        iot_printf("str lid%d tei:%d nid 0x%x tx:%d is_rf:%d not found.\n",
							 | 
						||
| 
								 | 
							
								            str->lid, str->peer->tei, nid, str->is_tx, str->is_rf);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#if DEBUG_FREE_STREAM_FAIL
							 | 
						||
| 
								 | 
							
								        mac_debug_stream_t debug_str;
							 | 
						||
| 
								 | 
							
								        debug_str.nid = (uint32_t)nid;
							 | 
						||
| 
								 | 
							
								        debug_str.lid = (uint32_t)str->lid;
							 | 
						||
| 
								 | 
							
								        debug_str.tei = (uint32_t)str->peer->tei;
							 | 
						||
| 
								 | 
							
								        debug_str.is_tx = (uint32_t)str->is_tx;
							 | 
						||
| 
								 | 
							
								        debug_str.is_rf = (uint32_t)str->is_rf;
							 | 
						||
| 
								 | 
							
								        IOT_ASSERT_DUMP(0, (uint32_t *)&debug_str, \
							 | 
						||
| 
								 | 
							
								            sizeof(mac_debug_stream_t)/sizeof(uint32_t));
							 | 
						||
| 
								 | 
							
								#endif
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								    return 0;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								uint32_t mac_tx_stream_ctxt_init(mac_tx_stream_ctxt_t *tx, \
							 | 
						||
| 
								 | 
							
								    mac_stream_t *stream, uint32_t need_free, iot_pkt_t *iot_pkt)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								    IOT_ASSERT(tx);
							 | 
						||
| 
								 | 
							
								    tx->mac_frame_list = tx->last_mac_frame = NULL;
							 | 
						||
| 
								 | 
							
								    tx->mac_frame_num = 0;
							 | 
						||
| 
								 | 
							
								    tx->cur_tx_msdu = NULL;
							 | 
						||
| 
								 | 
							
								    iot_list_init(&tx->swq_node);
							 | 
						||
| 
								 | 
							
								    (void)stream;
							 | 
						||
| 
								 | 
							
								    (void)need_free;
							 | 
						||
| 
								 | 
							
								    (void)iot_pkt;
							 | 
						||
| 
								 | 
							
								    return 0;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								uint32_t mac_tx_stream_ctxt_deinit(mac_stream_t* stream)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								    mac_tx_stream_ctxt_t * tx = &stream->msdu.tx;
							 | 
						||
| 
								 | 
							
								    mac_msdu_frame_t *tmp = tx->mac_frame_list;
							 | 
						||
| 
								 | 
							
								    if (tx->cur_tx_msdu) {
							 | 
						||
| 
								 | 
							
								        /* free the msdu if not freed yet */
							 | 
						||
| 
								 | 
							
								        if (!tx->cur_tx_msdu->in_hwq) {
							 | 
						||
| 
								 | 
							
								            mac_msdu_deinit(tx->cur_tx_msdu);
							 | 
						||
| 
								 | 
							
								        } else {
							 | 
						||
| 
								 | 
							
								            tx->cur_tx_msdu->ref_mac_stream = NULL;
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								        tx->cur_tx_msdu = NULL;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								    uint32_t bcn_region_type = \
							 | 
						||
| 
								 | 
							
								            mac_get_bcn_region_type(stream->lid);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    if(tx->mac_frame_num == 0){
							 | 
						||
| 
								 | 
							
								        IOT_ASSERT(tx->last_mac_frame == NULL && \
							 | 
						||
| 
								 | 
							
								            tx->mac_frame_list == NULL);
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								    else{
							 | 
						||
| 
								 | 
							
								        IOT_ASSERT(tx->last_mac_frame != NULL && \
							 | 
						||
| 
								 | 
							
								            tx->mac_frame_list != NULL);
							 | 
						||
| 
								 | 
							
								        for(uint32_t i = 0; i < (PLC_MAC_MSDU_FRAME_POOL_SIZE
							 | 
						||
| 
								 | 
							
								            + RF_MAC_MSDU_FRAME_POOL_SIZE); i++){
							 | 
						||
| 
								 | 
							
								            if(tmp == NULL){
							 | 
						||
| 
								 | 
							
								                break;
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								            tx->mac_frame_list = tmp->next;
							 | 
						||
| 
								 | 
							
								            IOT_ASSERT(tmp->buf);
							 | 
						||
| 
								 | 
							
								            iot_pkt_free_tx_done(tmp->buf, IOT_PKT_STATE_TX_FAIL);
							 | 
						||
| 
								 | 
							
								            mac_token_free(bcn_region_type, stream->lid, stream->is_rf);
							 | 
						||
| 
								 | 
							
								            mac_desc_free(&g_mac_desc_eng, \
							 | 
						||
| 
								 | 
							
								            PLC_MAC_MSDU_FRAME_POOL, tmp);
							 | 
						||
| 
								 | 
							
								            tmp = tx->mac_frame_list;
							 | 
						||
| 
								 | 
							
								            tx->mac_frame_num -= 1;
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								        IOT_ASSERT(tx->mac_frame_num == 0 && tmp == NULL);
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								    return 0;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								uint32_t mac_stream_alloc(mac_peer_t *peer, uint32_t is_tx, \
							 | 
						||
| 
								 | 
							
								    lid_t lid, uint8_t is_rf, mac_stream_t **stream_ptr)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								    mac_stream_t *stream;
							 | 
						||
| 
								 | 
							
								    if (!peer) {
							 | 
						||
| 
								 | 
							
								        return ERR_INVAL;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								    mac_vdev_t *vdev = get_vdev_ptr(peer->pdev_id, peer->vdev_id);
							 | 
						||
| 
								 | 
							
								    IOT_ASSERT(vdev);
							 | 
						||
| 
								 | 
							
								#if 0
							 | 
						||
| 
								 | 
							
								    /* double check if the stream already exist
							 | 
						||
| 
								 | 
							
								    * can be omit to make faster */
							 | 
						||
| 
								 | 
							
								    mac_vdev_t *vdev = get_vdev_ptr(peer->pdev_id, peer->vdev_id);
							 | 
						||
| 
								 | 
							
								    nid_t nid;
							 | 
						||
| 
								 | 
							
								    nid = vdev_get_nid(vdev);
							 | 
						||
| 
								 | 
							
								    if (nid) {
							 | 
						||
| 
								 | 
							
								        /* if vdev's nid is known */
							 | 
						||
| 
								 | 
							
								        stream = find_stream(peer, nid, \
							 | 
						||
| 
								 | 
							
								            peer->tei, lid);
							 | 
						||
| 
								 | 
							
								        if (stream) {
							 | 
						||
| 
								 | 
							
								            /* if found the stream already */
							 | 
						||
| 
								 | 
							
								            *stream_ptr = stream;
							 | 
						||
| 
								 | 
							
								            return ERR_EXIST;
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								    else {
							 | 
						||
| 
								 | 
							
								        /* if vdev's nid is not set, use self peer */
							 | 
						||
| 
								 | 
							
								        mac_peer_t *self_peer = (mac_peer_t *)vdev->self_peer;
							 | 
						||
| 
								 | 
							
								        stream = find_stream(peer, nid, \
							 | 
						||
| 
								 | 
							
								            self_peer->tei, lid);
							 | 
						||
| 
								 | 
							
								        if (stream) {
							 | 
						||
| 
								 | 
							
								            /* if found the stream already */
							 | 
						||
| 
								 | 
							
								            *stream_ptr = stream;
							 | 
						||
| 
								 | 
							
								            return ERR_EXIST;
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								#endif
							 | 
						||
| 
								 | 
							
								    /* create the stream */
							 | 
						||
| 
								 | 
							
								    uint32_t ret = mac_desc_get(&g_mac_desc_eng, \
							 | 
						||
| 
								 | 
							
								        PLC_MAC_STREAM_POOL, (void**)&stream);
							 | 
						||
| 
								 | 
							
								    if (ret) {
							 | 
						||
| 
								 | 
							
								        /* if the first get stream fail.
							 | 
						||
| 
								 | 
							
								         * del the oldest stream. and get stream again.
							 | 
						||
| 
								 | 
							
								         */
							 | 
						||
| 
								 | 
							
								        mac_vdev_del_timeout_stream_internal(vdev, false);
							 | 
						||
| 
								 | 
							
								        vdev->stream_overflow_cnt++;
							 | 
						||
| 
								 | 
							
								        /* get stream again */
							 | 
						||
| 
								 | 
							
								        ret = mac_desc_get(&g_mac_desc_eng, \
							 | 
						||
| 
								 | 
							
								            PLC_MAC_STREAM_POOL, (void**)&stream);
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    if (ret) {
							 | 
						||
| 
								 | 
							
								        mac_peer_stream_overflow_cnt_dbglog();
							 | 
						||
| 
								 | 
							
								        return ERR_NOMEM;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								    else {
							 | 
						||
| 
								 | 
							
								        if (is_tx) {
							 | 
						||
| 
								 | 
							
								            /* for tx usage */
							 | 
						||
| 
								 | 
							
								            mac_tx_stream_ctxt_init(&stream->msdu.tx, stream, 1, NULL);
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								        else {
							 | 
						||
| 
								 | 
							
								            /* for rx usage */
							 | 
						||
| 
								 | 
							
								            reorder_buf_init(&stream->msdu.rx.reorder_buf, \
							 | 
						||
| 
								 | 
							
								                stream);
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								        iot_single_list_init(&stream->peer_node);
							 | 
						||
| 
								 | 
							
								        stream->is_tx = (uint8_t)is_tx;
							 | 
						||
| 
								 | 
							
								        stream->in_swq = 0;
							 | 
						||
| 
								 | 
							
								        stream->lid = lid;
							 | 
						||
| 
								 | 
							
								        stream->peer = peer;
							 | 
						||
| 
								 | 
							
								        stream->phase_in_swq = PLC_PHASE_ALL;
							 | 
						||
| 
								 | 
							
								        stream->is_rf = is_rf;
							 | 
						||
| 
								 | 
							
								        /* add into peer */
							 | 
						||
| 
								 | 
							
								        peer_add_stream(peer, stream);
							 | 
						||
| 
								 | 
							
								        /* add into hash table */
							 | 
						||
| 
								 | 
							
								        stream_hash_tbl_add(stream);
							 | 
						||
| 
								 | 
							
								        /* stream cnt ++*/
							 | 
						||
| 
								 | 
							
								        vdev->stream_cnt++;
							 | 
						||
| 
								 | 
							
								        if (!stream->is_tx) {
							 | 
						||
| 
								 | 
							
								            vdev->rx_stream_cnt++;
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								        *stream_ptr = stream;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								#if PLC_SUPPORT_CCO_ROLE
							 | 
						||
| 
								 | 
							
								    nid_t nid;
							 | 
						||
| 
								 | 
							
								    vdev_get_nid(get_vdev_ptr(peer->pdev_id, peer->vdev_id), &nid);
							 | 
						||
| 
								 | 
							
								    iot_printf("%s,vid:%d, str:0x%x, nid: 0x%x, tei:%d, "
							 | 
						||
| 
								 | 
							
								        "lid:%d, is_tx:%d, is_rf:%d\n", __FUNCTION__, peer->vdev_id,
							 | 
						||
| 
								 | 
							
								        stream, nid, peer->tei, lid, is_tx, is_rf);
							 | 
						||
| 
								 | 
							
								#endif
							 | 
						||
| 
								 | 
							
								    return ERR_OK;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								uint32_t mac_stream_free(mac_peer_t *peer, mac_stream_t *stream)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								    IOT_ASSERT(peer);
							 | 
						||
| 
								 | 
							
								    mac_vdev_t *vdev = get_vdev_ptr(peer->pdev_id, peer->vdev_id);
							 | 
						||
| 
								 | 
							
								    IOT_ASSERT(vdev);
							 | 
						||
| 
								 | 
							
								    mac_stream_t *str = stream;
							 | 
						||
| 
								 | 
							
								    IOT_ASSERT(str != NULL);
							 | 
						||
| 
								 | 
							
								    /* delete this node from peer */
							 | 
						||
| 
								 | 
							
								    peer_del_stream(peer, str);
							 | 
						||
| 
								 | 
							
								    /* delete this node from hash table streamlist */
							 | 
						||
| 
								 | 
							
								    stream_hash_tbl_del(str);
							 | 
						||
| 
								 | 
							
								    /* delete from swq streamlist */
							 | 
						||
| 
								 | 
							
								    mac_swsch_del_stream(str);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#if PLC_SUPPORT_CCO_ROLE
							 | 
						||
| 
								 | 
							
								    nid_t nid;
							 | 
						||
| 
								 | 
							
								    vdev_get_nid(get_vdev_ptr(peer->pdev_id, peer->vdev_id), &nid);
							 | 
						||
| 
								 | 
							
								    iot_printf("%s,vid:%d, str:0x%x, nid: 0x%x, tei:%d, lid:%d, "
							 | 
						||
| 
								 | 
							
								        "is_tx:%d, is_rf:%d\n", __FUNCTION__, peer->vdev_id,
							 | 
						||
| 
								 | 
							
								        str, nid, peer->tei, stream->lid, stream->is_tx, stream->is_rf);
							 | 
						||
| 
								 | 
							
								#endif
							 | 
						||
| 
								 | 
							
								    /* destroy stream */
							 | 
						||
| 
								 | 
							
								    if (stream->is_tx) {
							 | 
						||
| 
								 | 
							
								        mac_tx_stream_ctxt_deinit(str);
							 | 
						||
| 
								 | 
							
								    } else {
							 | 
						||
| 
								 | 
							
								        reorder_buf_free(&stream->msdu.rx.reorder_buf);
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								    /* stream cnt--*/
							 | 
						||
| 
								 | 
							
								    vdev->stream_cnt--;
							 | 
						||
| 
								 | 
							
								    if (!stream->is_tx) {
							 | 
						||
| 
								 | 
							
								        vdev->rx_stream_cnt--;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								    mac_desc_free(&g_mac_desc_eng, PLC_MAC_STREAM_POOL, stream);
							 | 
						||
| 
								 | 
							
								    return ERR_OK;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								uint32_t is_stream_empty(mac_stream_t *stream)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								    if (stream->is_tx == 0) {
							 | 
						||
| 
								 | 
							
								        /* is RX stream */
							 | 
						||
| 
								 | 
							
								        if (stream->msdu.rx.reorder_buf.pb_rdy_cnt != 0) {
							 | 
						||
| 
								 | 
							
								            return 0;
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								    } else {
							 | 
						||
| 
								 | 
							
								       /* is TX stream */
							 | 
						||
| 
								 | 
							
								        if (stream->msdu.tx.mac_frame_num != 0 || \
							 | 
						||
| 
								 | 
							
								            (stream->msdu.tx.cur_tx_msdu != NULL && \
							 | 
						||
| 
								 | 
							
								            stream->msdu.tx.cur_tx_msdu->in_hwq != 0)) {
							 | 
						||
| 
								 | 
							
								            return 0;
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								    return 1;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								void mac_stream_exhausted_dump(mac_peer_t *peer)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								    uint8_t idx;
							 | 
						||
| 
								 | 
							
								    mac_vdev_t *vdev;
							 | 
						||
| 
								 | 
							
								    mac_stream_exhausted_info_t str_dump = {0};
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    str_dump.cur_ts = os_boot_time32();
							 | 
						||
| 
								 | 
							
								    os_mem_cpy(&str_dump.peer, peer, sizeof(*peer));
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    for (idx = 0; idx < MAX_VDEV_NUM; idx++) {
							 | 
						||
| 
								 | 
							
								        vdev = get_vdev_ptr(0, idx);
							 | 
						||
| 
								 | 
							
								        str_dump.vdev_info[idx].peer_cnt = vdev->peer_cnt;
							 | 
						||
| 
								 | 
							
								        str_dump.vdev_info[idx].proxy_peer_cnt = vdev->proxy_peer_cnt;
							 | 
						||
| 
								 | 
							
								        str_dump.vdev_info[idx].stream_cnt = vdev->stream_cnt;
							 | 
						||
| 
								 | 
							
								        str_dump.vdev_info[idx].rx_stream_cnt = vdev->rx_stream_cnt;
							 | 
						||
| 
								 | 
							
								        str_dump.vdev_info[idx].stream_overflow_cnt = vdev->stream_overflow_cnt;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    IOT_ASSERT_DUMP(0, (uint32_t *)&str_dump,
							 | 
						||
| 
								 | 
							
								        sizeof(str_dump) / sizeof(uint32_t));
							 | 
						||
| 
								 | 
							
								}
							 |