364 lines
12 KiB
C
Executable File
364 lines
12 KiB
C
Executable File
/****************************************************************************
|
|
|
|
Copyright(c) 2019 by Aerospace C.Power (Chongqing) Microelectronics. ALL RIGHTS RESERVED.
|
|
|
|
This Information is proprietary to Aerospace C.Power (Chongqing) Microelectronics and MAY NOT
|
|
be copied by any method or incorporated into another program without
|
|
the express written consent of Aerospace C.Power. This Information or any portion
|
|
thereof remains the property of Aerospace C.Power. The Information contained herein
|
|
is believed to be accurate and Aerospace C.Power assumes no responsibility or
|
|
liability for its use in any way and conveys no license or title under
|
|
any patent or copyright and makes no representation or warranty that this
|
|
Information is free from patent or copyright infringement.
|
|
|
|
****************************************************************************/
|
|
|
|
#include "iot_config.h"
|
|
#include "mac_desc_engine.h"
|
|
#include "iot_errno.h"
|
|
#include "mac_msdu.h"
|
|
#include "mac_peer.h"
|
|
#include "mac_stream.h"
|
|
#include "rx_pb_reorder.h"
|
|
#include "command_list.h"
|
|
#include "iot_io_api.h"
|
|
|
|
#include "mac_pdev.h"
|
|
#include "iot_dbglog_api.h"
|
|
#include "iot_dbglog_parser.h"
|
|
|
|
/* 30 minutes period, uint 10 mimutes */
|
|
#define MAC_DESC_PERIOD_30_MIN 3
|
|
|
|
mac_desc_engine_t g_mac_desc_eng;
|
|
token_num_t g_mac_token_bucket[TOKEN_BUCKET_IDX_MAX];
|
|
static uint8_t g_mac_desc_period_30_min_cnt = 0;
|
|
|
|
#if HPLC_RF_DEV_SUPPORT
|
|
token_num_t g_rf_mac_token_bucket[TOKEN_BUCKET_IDX_MAX];
|
|
#endif
|
|
|
|
const mac_desc_pool_cfg_t g_def_desc_pool_cfg[MAX_PLC_DESC_POOL_NUM] = {
|
|
/* PLC_MAC_MSDU_POOL */
|
|
{ PLC_MAC_MSDU_POOL_SIZE + RF_MAC_MSDU_POOL_SIZE, sizeof(mac_msdu_t) },
|
|
/* PLC_MAC_PEER_POOL */
|
|
{ PLC_MAC_PEER_POOL_SIZE + RF_MAC_PEER_POOL_SIZE, sizeof(mac_peer_t) },
|
|
/* PLC_MAC_STREAM_POOL */
|
|
{ PLC_MAC_STREAM_POOL_SIZE + RF_MAC_STREAM_POOL_SIZE, sizeof(mac_stream_t)},
|
|
/* PLC_TX_MPDU_START_POOL */
|
|
{ PLC_TX_MPDU_START_POOL_SIZE + RF_TX_MPDU_START_POOL_SIZE,
|
|
sizeof(tx_mpdu_start)
|
|
},
|
|
/* PLC_TX_MPDU_END_POOL */
|
|
{ PLC_TX_MPDU_END_POOL_SIZE + RF_TX_MPDU_END_POOL_SIZE,
|
|
sizeof(tx_mpdu_end)
|
|
},
|
|
/* PLC_TX_PB_START_POOL */
|
|
{ PLC_TX_PB_POOL_SIZE + RF_TX_PB_POOL_SIZE, sizeof(tx_pb_start) },
|
|
/* PLC_RX_PB_DESC_POOL */
|
|
{ PLC_RX_PB_POOL_SIZE + RF_RX_PB_POOL_SIZE, sizeof(pb_buf_list_t) },
|
|
/*PLC_SCHED_CMD_LIST_POOL*/
|
|
{ PLC_SCHED_CMD_LIST_POOL_SIZE + RF_SCHED_CMD_LIST_POOL_SIZE,
|
|
sizeof(hw_sched_cmd_list_t)
|
|
},
|
|
/* PLC_TX_DUMMY_POOL */
|
|
{ PLC_TX_DUMMY_POOL_SIZE + RF_TX_DUMMY_POOL_SIZE,
|
|
sizeof(tx_dummy_node)
|
|
},
|
|
/*PLC_MAC_MSDU_FRAME_POOL*/
|
|
{ PLC_MAC_MSDU_FRAME_POOL_SIZE + RF_MAC_MSDU_FRAME_POOL_SIZE,
|
|
sizeof(mac_msdu_frame_t)
|
|
},
|
|
};
|
|
|
|
uint32_t mac_desc_engine_init(mac_desc_engine_t *desc_eng, \
|
|
mac_desc_pool_cfg_t *cfg)
|
|
{
|
|
uint32_t ret;
|
|
if (desc_eng == NULL) {
|
|
return ERR_INVAL;
|
|
}
|
|
/* if cfg NULL, use default */
|
|
if (cfg == NULL) {
|
|
cfg = (mac_desc_pool_cfg_t *)&g_def_desc_pool_cfg[0];
|
|
}
|
|
{
|
|
#if PLC_MEM_ALLOC_STAT
|
|
uint32_t total_bytes = 0;
|
|
#endif
|
|
for (int i = 0; i < MAX_PLC_DESC_POOL_NUM; i++) {
|
|
ret = iot_mem_pool_init(PLC_MAC_DESC_ENGINE_MID,
|
|
cfg[i].desc_num,
|
|
cfg[i].desc_size,
|
|
&desc_eng->mem_pool[i], 0);
|
|
IOT_ASSERT(ret == 0);
|
|
desc_eng->used[i] = 0;
|
|
desc_eng->mutex[i] = os_create_mutex(PLC_MAC_DESC_ENGINE_MID);
|
|
desc_eng->free_num_min[i] = desc_eng->mem_pool[i].num;
|
|
#if PLC_MEM_ALLOC_STAT
|
|
{
|
|
/* calculate the desc memory usage */
|
|
total_bytes += cfg[i].desc_num * cfg[i].desc_size;
|
|
iot_printf("__desc__%d: num %d x size %d = %d bytes \n", \
|
|
i, cfg[i].desc_num,
|
|
cfg[i].desc_size, cfg[i].desc_num * cfg[i].desc_size);
|
|
}
|
|
#endif
|
|
}
|
|
#if PLC_MEM_ALLOC_STAT
|
|
iot_printf("totally: %d bytes\n", total_bytes);
|
|
#endif
|
|
#if PLC_MEM_ALLOC_STAT > 1
|
|
desc_eng->desc_req_cnt = 0;
|
|
#endif
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
void mac_desc_info_dump_force(mac_desc_engine_t *desc_eng)
|
|
{
|
|
iot_dbglog_input(PLC_MAC_DESC_ENGINE_MID, DBGLOG_ERR,
|
|
IOT_MAC_DESC1_ID, 8,
|
|
desc_eng->used[PLC_MAC_MSDU_POOL],
|
|
(desc_eng->mem_pool[PLC_MAC_MSDU_POOL].num << 16 |
|
|
desc_eng->free_num_min[PLC_MAC_MSDU_POOL]),
|
|
desc_eng->used[PLC_MAC_PEER_POOL],
|
|
(desc_eng->mem_pool[PLC_MAC_PEER_POOL].num << 16 |
|
|
desc_eng->free_num_min[PLC_MAC_PEER_POOL]),
|
|
desc_eng->used[PLC_MAC_STREAM_POOL],
|
|
(desc_eng->mem_pool[PLC_MAC_STREAM_POOL].num << 16 |
|
|
desc_eng->free_num_min[PLC_MAC_STREAM_POOL]),
|
|
desc_eng->used[PLC_TX_MPDU_START_POOL],
|
|
(desc_eng->mem_pool[PLC_TX_MPDU_START_POOL].num << 16 |
|
|
desc_eng->free_num_min[PLC_TX_MPDU_START_POOL]));
|
|
|
|
iot_dbglog_input(PLC_MAC_DESC_ENGINE_MID, DBGLOG_ERR,
|
|
IOT_MAC_DESC2_ID, 8,
|
|
desc_eng->used[PLC_TX_MPDU_END_POOL],
|
|
(desc_eng->mem_pool[PLC_TX_MPDU_END_POOL].num << 16 |
|
|
desc_eng->free_num_min[PLC_TX_MPDU_END_POOL]),
|
|
desc_eng->used[PLC_TX_PB_START_POOL],
|
|
(desc_eng->mem_pool[PLC_TX_PB_START_POOL].num << 16 |
|
|
desc_eng->free_num_min[PLC_TX_PB_START_POOL]),
|
|
desc_eng->used[PLC_RX_PB_DESC_POOL],
|
|
(desc_eng->mem_pool[PLC_RX_PB_DESC_POOL].num << 16 |
|
|
desc_eng->free_num_min[PLC_RX_PB_DESC_POOL]),
|
|
desc_eng->used[PLC_SCHED_CMD_LIST_POOL],
|
|
(desc_eng->mem_pool[PLC_SCHED_CMD_LIST_POOL].num << 16 |
|
|
desc_eng->free_num_min[PLC_SCHED_CMD_LIST_POOL]));
|
|
|
|
iot_dbglog_input(PLC_MAC_DESC_ENGINE_MID, DBGLOG_ERR,
|
|
IOT_MAC_DESC3_ID, 4,
|
|
desc_eng->used[PLC_TX_DUMMY_NODE_POOL],
|
|
(desc_eng->mem_pool[PLC_TX_DUMMY_NODE_POOL].num << 16 |
|
|
desc_eng->free_num_min[PLC_TX_DUMMY_NODE_POOL]),
|
|
desc_eng->used[PLC_MAC_MSDU_FRAME_POOL],
|
|
(desc_eng->mem_pool[PLC_MAC_MSDU_FRAME_POOL].num << 16 |
|
|
desc_eng->free_num_min[PLC_MAC_MSDU_FRAME_POOL]));
|
|
}
|
|
|
|
void mac_desc_info_dump(mac_desc_engine_t *desc_eng)
|
|
{
|
|
if (++g_mac_desc_period_30_min_cnt >= MAC_DESC_PERIOD_30_MIN) {
|
|
mac_desc_info_dump_force(desc_eng);
|
|
g_mac_desc_period_30_min_cnt = 0;
|
|
}
|
|
}
|
|
|
|
/* alloc a desc as requested type */
|
|
uint32_t mac_desc_get(mac_desc_engine_t *desc_eng, \
|
|
mac_desc_pool_type_t desc_type, \
|
|
void **desc_ptr)
|
|
{
|
|
if (desc_eng == NULL || desc_type >= MAX_PLC_DESC_POOL_NUM \
|
|
|| desc_ptr == NULL) {
|
|
IOT_ASSERT(0);
|
|
return ERR_INVAL;
|
|
}
|
|
*desc_ptr = iot_mem_pool_alloc(&desc_eng->mem_pool[desc_type]);
|
|
if (*desc_ptr == NULL) {
|
|
#if DEBUG_RX_PB_CNT_NOT_ENOUGH
|
|
mac_desc_info_dump_force(desc_eng);
|
|
g_mac_desc_period_30_min_cnt = 0;
|
|
#endif
|
|
|
|
return ERR_NOMEM;
|
|
}
|
|
|
|
if (desc_eng->free_num_min[desc_type] >
|
|
desc_eng->mem_pool[desc_type].free_num) {
|
|
desc_eng->free_num_min[desc_type] =
|
|
(uint16_t)desc_eng->mem_pool[desc_type].free_num;
|
|
}
|
|
|
|
/* TODO: for some type, need zero */
|
|
switch (desc_type) {
|
|
case PLC_MAC_PEER_POOL:
|
|
case PLC_MAC_STREAM_POOL:
|
|
case PLC_RX_PB_DESC_POOL:
|
|
case PLC_MAC_MSDU_FRAME_POOL:
|
|
{
|
|
/* init at mac_create_peer() */
|
|
/* mac_create_stream() */
|
|
/* pb_buf_list_init() */
|
|
/* mac_frame_list_init() */
|
|
break;
|
|
}
|
|
case PLC_TX_DUMMY_NODE_POOL:
|
|
{
|
|
tx_dummy_node *dummy = *desc_ptr;
|
|
dummy->tx_done = 0;
|
|
dummy->next = 0;
|
|
break;
|
|
}
|
|
case PLC_SCHED_CMD_LIST_POOL:
|
|
{
|
|
/* no need to zero */
|
|
break;
|
|
}
|
|
default:
|
|
{
|
|
/* zero by default */
|
|
os_mem_set(*desc_ptr, 0, \
|
|
desc_eng->mem_pool[desc_type].align_block_word_size << 2);
|
|
}
|
|
}
|
|
|
|
os_acquire_mutex(desc_eng->mutex[desc_type]);
|
|
desc_eng->used[desc_type]++;
|
|
os_release_mutex(desc_eng->mutex[desc_type]);
|
|
|
|
#if PLC_MEM_ALLOC_STAT > 1
|
|
if ((++desc_eng->desc_req_cnt & DESC_STAT_DISPLAY_FREQ) \
|
|
== DESC_STAT_DISPLAY_FREQ)
|
|
{
|
|
uint32_t total, used;
|
|
char c_str_buf[128] = { 0 };
|
|
int32_t idx = 0;
|
|
for (int i = 0; i < MAX_PLC_DESC_POOL_NUM; i++) {
|
|
total = desc_eng->mem_pool[i].num;
|
|
used = total - desc_eng->mem_pool[i].free_num;
|
|
idx += iot_snprintf(c_str_buf + idx, \
|
|
sizeof(c_str_buf) - idx, \
|
|
"d%d:%d/%d;", i, used, total);
|
|
}
|
|
iot_printf("%s\n", c_str_buf);
|
|
}
|
|
#endif
|
|
|
|
return 0;
|
|
}
|
|
|
|
uint32_t mac_desc_free(mac_desc_engine_t *desc_eng, \
|
|
mac_desc_pool_type_t desc_type, void *desc_ptr)
|
|
{
|
|
uint32_t ret;
|
|
if (desc_eng == NULL || desc_ptr == NULL \
|
|
|| desc_type >= MAX_PLC_DESC_POOL_NUM) {
|
|
IOT_ASSERT(0);
|
|
return ERR_INVAL;
|
|
}
|
|
ret = iot_mem_pool_free(&desc_eng->mem_pool[desc_type], \
|
|
desc_ptr);
|
|
if (ret == 0) {
|
|
os_acquire_mutex(desc_eng->mutex[desc_type]);
|
|
desc_eng->used[desc_type]--;
|
|
os_release_mutex(desc_eng->mutex[desc_type]);
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
void mac_token_bucket_init()
|
|
{
|
|
/* TDMA 1,BCSMA 1 */
|
|
g_mac_token_bucket[BCSMA_TOKEN_BUCKET_IDX] = PLC_BCSMA_TOKEN_NUM;
|
|
g_mac_token_bucket[TDMA_TOKEN_BUCKET_IDX] = PLC_TDMA_TOKEN_NUM;
|
|
|
|
/* TODO: we need to consider the tx/rx buffer cnt
|
|
* also, sometimes the buffer maybe not enough
|
|
* if the MSDU are the long buffer cnt
|
|
* currently assume 3/4 MSDU_FRAME_POOL_SIZE
|
|
*/
|
|
|
|
/* 4 csma token buckets: 2:3:3:4 */
|
|
#define DIVISOR 12
|
|
IOT_ASSERT(PLC_MAC_CSMA_TOKEN_NUM >= DIVISOR);
|
|
|
|
#if USE_SHARED_CSMA_TOKEN
|
|
/* in shared case, all token shared csma0, resv csma3 */
|
|
g_mac_token_bucket[CSMA3_TOKEN_BUCKET_IDX] = \
|
|
(PLC_MAC_CSMA_TOKEN_NUM / DIVISOR) * 0;
|
|
g_mac_token_bucket[CSMA2_TOKEN_BUCKET_IDX] = \
|
|
(PLC_MAC_CSMA_TOKEN_NUM / DIVISOR) * 0;
|
|
g_mac_token_bucket[CSMA1_TOKEN_BUCKET_IDX] = \
|
|
(PLC_MAC_CSMA_TOKEN_NUM / DIVISOR) * 0;
|
|
g_mac_token_bucket[CSMA0_TOKEN_BUCKET_IDX] = \
|
|
PLC_MAC_CSMA_TOKEN_NUM - \
|
|
g_mac_token_bucket[CSMA3_TOKEN_BUCKET_IDX] - \
|
|
g_mac_token_bucket[CSMA2_TOKEN_BUCKET_IDX] - \
|
|
g_mac_token_bucket[CSMA1_TOKEN_BUCKET_IDX];
|
|
#else
|
|
g_mac_token_bucket[CSMA0_TOKEN_BUCKET_IDX] = \
|
|
(PLC_MAC_CSMA_TOKEN_NUM /DIVISOR)*2;
|
|
g_mac_token_bucket[CSMA1_TOKEN_BUCKET_IDX] = \
|
|
(PLC_MAC_CSMA_TOKEN_NUM /DIVISOR)*3;
|
|
g_mac_token_bucket[CSMA2_TOKEN_BUCKET_IDX] = \
|
|
(PLC_MAC_CSMA_TOKEN_NUM /DIVISOR)*3;
|
|
g_mac_token_bucket[CSMA3_TOKEN_BUCKET_IDX] = \
|
|
PLC_MAC_CSMA_TOKEN_NUM - \
|
|
g_mac_token_bucket[CSMA0_TOKEN_BUCKET_IDX] - \
|
|
g_mac_token_bucket[CSMA1_TOKEN_BUCKET_IDX] - \
|
|
g_mac_token_bucket[CSMA2_TOKEN_BUCKET_IDX];
|
|
#endif
|
|
|
|
IOT_ASSERT(PLC_MAC_MSDU_FRAME_POOL_SIZE >= \
|
|
g_mac_token_bucket[CSMA0_TOKEN_BUCKET_IDX] + \
|
|
g_mac_token_bucket[CSMA1_TOKEN_BUCKET_IDX] + \
|
|
g_mac_token_bucket[CSMA2_TOKEN_BUCKET_IDX] + \
|
|
g_mac_token_bucket[CSMA3_TOKEN_BUCKET_IDX] + \
|
|
g_mac_token_bucket[BCSMA_TOKEN_BUCKET_IDX] + \
|
|
g_mac_token_bucket[TDMA_TOKEN_BUCKET_IDX]);
|
|
|
|
#if HPLC_RF_DEV_SUPPORT
|
|
/* TDMA ,BCSMA */
|
|
g_rf_mac_token_bucket[BCSMA_TOKEN_BUCKET_IDX] = RF_BCSMA_TOKEN_NUM;
|
|
g_rf_mac_token_bucket[TDMA_TOKEN_BUCKET_IDX] = RF_TDMA_TOKEN_NUM;
|
|
|
|
#if USE_SHARED_CSMA_TOKEN
|
|
/* in shared case, all token shared csma0, resv csma3 */
|
|
g_rf_mac_token_bucket[CSMA3_TOKEN_BUCKET_IDX] = 0;
|
|
g_rf_mac_token_bucket[CSMA2_TOKEN_BUCKET_IDX] = 0;
|
|
g_rf_mac_token_bucket[CSMA1_TOKEN_BUCKET_IDX] = 0;
|
|
g_rf_mac_token_bucket[CSMA0_TOKEN_BUCKET_IDX] = RF_MAC_CSMA_TOKEN_NUM
|
|
- g_mac_token_bucket[CSMA3_TOKEN_BUCKET_IDX]
|
|
- g_mac_token_bucket[CSMA2_TOKEN_BUCKET_IDX]
|
|
- g_mac_token_bucket[CSMA1_TOKEN_BUCKET_IDX];
|
|
#else /* USE_SHARED_CSMA_TOKEN */
|
|
/* TODO: add code */
|
|
IOT_ASSERT(0);
|
|
#endif /* USE_SHARED_CSMA_TOKEN */
|
|
#endif /* HPLC_RF_DEV_SUPPORT */
|
|
}
|
|
|
|
void mac_check_peer_stream_desc()
|
|
{
|
|
uint32_t peer_used = g_mac_desc_eng.used[PLC_MAC_PEER_POOL];
|
|
uint32_t stream_used = g_mac_desc_eng.used[PLC_MAC_STREAM_POOL];
|
|
|
|
/* vdev and reduce vdev need self/bcast peer, always need 4 peer */
|
|
if (peer_used > 4 || stream_used != 0) {
|
|
uint32_t data_dump[3];
|
|
for (uint32_t vdev_id = 0; vdev_id < MAX_VDEV_NUM; vdev_id++) {
|
|
mac_vdev_t *vdev = get_vdev_ptr(0, vdev_id);
|
|
data_dump[vdev_id] = vdev->peer_cnt << 16 | vdev->stream_cnt;
|
|
}
|
|
iot_printf("%s, pr_u:%d, sr_u:%d, \n", \
|
|
__FUNCTION__, peer_used, stream_used);
|
|
data_dump[2] = peer_used << 16 | stream_used;
|
|
IOT_ASSERT_DUMP(0, data_dump, 3 * sizeof(uint32_t));
|
|
}
|
|
return;
|
|
}
|
|
|
|
|