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

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;
}