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

252 lines
7.1 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_rf_hwq_mgr.h"
#include "iot_config.h"
#if HPLC_RF_DEV_SUPPORT
#include "mac_rf_txq_hw.h"
#endif
#include "plc_utils.h"
#include "plc_protocol.h"
#include "mac_desc_engine.h"
#include "iot_errno.h"
#include "iot_io.h"
#include "mac_tx_hw.h"
#include "hw_war.h"
#include "mac_rf_tx_hw.h"
#if HPLC_RF_DEV_SUPPORT
/* init the rf hwq ctxt */
void mac_rf_q_init(mac_rf_queue_ctxt_t *queue)
{
IOT_ASSERT(queue);
for (uint32_t i = 0; i < MAX_MAC_RF_QUE_NUM; i++) {
queue->hwq_map[i] = (uint8_t)INV_MAC_RF_HWQ_ID;
}
for (uint32_t i = 0; i < MAX_MAC_RF_QUE_NUM; i++) {
/* init queue */
queue->last_desc[i] = NULL;
queue->cur_hdl_desc[i] = NULL;
queue->q_depth[i] = 0;
}
queue->last_hwq_id = 0;
}
void mac_rf_enable_all_csma_hwqid()
{
uint32_t ret;
rf_tx_dummy_node *dummy_node;
mac_rf_pdev_t *rf_pdev = get_rf_pdev_ptr(PLC_PDEV_ID, RF_PDEV_ID);
mac_rf_queue_ctxt_t *tx_ctxt = &rf_pdev->hwq_hdl;
for (uint32_t hwq_id = MAC_RF_QUE_CSMA_0; hwq_id < MAX_ENABLE_CSMA_HWQ;
hwq_id++) {
if (tx_ctxt->cur_hdl_desc[hwq_id] == NULL) {
ret = mac_desc_get(&g_mac_desc_eng, PLC_TX_DUMMY_NODE_POOL,
(void**)&dummy_node);
IOT_ASSERT(ret == 0);
/* fill dummy */
mac_rf_tx_mpdu_fill_dummy(dummy_node);
mac_rf_tx_hw_mpdu(tx_ctxt, hwq_id, (rf_tx_mpdu_start *)dummy_node);
}
}
}
/* get the real hwq mapping id
* @mac_que - sw queue that designated
* return - the real hwq id that mapping to MAC HW if allocated
* INV_MAC_RF_HWQ_ID if not allocated
*/
uint8_t mac_rf_q_get_hwqid(mac_rf_queue_ctxt_t *queue, mac_rf_queue_t qtype)
{
IOT_ASSERT(queue && qtype < MAX_MAC_RF_QUE_NUM);
/* if sch mode */
return queue->hwq_map[qtype];
}
/* alloc a hwq from mac queue type */
uint8_t mac_rf_q_alloc_hwq(mac_rf_queue_ctxt_t *queue, mac_rf_queue_t qtype)
{
IOT_ASSERT(queue && qtype < MAX_MAC_RF_QUE_NUM);
uint8_t qid;
/* check if already allocated,
* TODO: handle the hwq reuse case,
* that is multi-swq share the same hwq
*/
qid = mac_rf_q_get_hwqid(queue, qtype);
IOT_ASSERT(qid == INV_MAC_RF_HWQ_ID);
/* start alloc a new hwq */
qid = queue->last_hwq_id;
IOT_ASSERT(qid < MAX_MAC_RF_TXQ_NUM);
switch (qtype) {
case MAC_RF_QUE_BCN:
case MAC_RF_QUE_TDMA:
/* for tdma queue, cap is not used, fill 0 */
mac_rf_txq_cfg(qid, 0, 0);
break;
case MAC_RF_QUE_CSMA_0:
mac_rf_txq_cfg(qid, 0, 1);
break;
case MAC_RF_QUE_CSMA_1:
mac_rf_txq_cfg(qid, 1, 1);
break;
case MAC_RF_QUE_CSMA_2:
mac_rf_txq_cfg(qid, 2, 1);
break;
case MAC_RF_QUE_CSMA_3:
mac_rf_txq_cfg(qid, 3, 1);
break;
case MAC_RF_QUE_CSMA_DBG:
mac_rf_txq_cfg(qid, 4, 1);
break;
case MAC_RF_QUE_BCSMA:
/* for SG, BCSMA only allow one LID, and
* this LID usually > 3, so the
* cap should be set higher priority,
* fill 3 here.
*/
mac_rf_txq_cfg(qid, 3, 1);
break;
default:
IOT_ASSERT(0);
}
/* record the mapping, and increase the last id */
queue->hwq_map[qtype] = (uint8_t)qid;
queue->last_hwq_id++;
//alloc_done:
return qid;
}
mac_rf_queue_t mac_rf_q_get_swq_type(uint32_t bcn_region_type,
lid_t lid, uint8_t is_dbg_tx)
{
switch (bcn_region_type) {
case PLC_BCN_REGION_BCN:
return MAC_RF_QUE_BCN;
break;
case PLC_BCN_REGION_CSMA:
IOT_ASSERT(lid <= LID_CSMA_CAP3);
if (is_dbg_tx) {
return MAC_RF_QUE_CSMA_DBG;
}
#if ENA_RF_ONLY_ONE_CSMA_HWQ
/* rf csma just one hwq enable */
lid = LID_CSMA_CAP0;
#endif
return MAC_RF_QUE_CSMA_0 + lid;
break;
case PLC_BCN_REGION_TDMA:
IOT_ASSERT(lid >= LID_TDMA_START &&
lid <= LID_TDMA_END);
return MAC_RF_QUE_TDMA;
break;
case PLC_BCN_REGION_BCSMA:
IOT_ASSERT(lid >= LID_BCSMA_START &&
lid <= LID_BCSMA_END);
return MAC_RF_QUE_BCSMA;
break;
default:
IOT_ASSERT(0);
}
/* should not reach here */
return MAX_MAC_RF_QUE_NUM;
}
uint32_t mac_rf_q_get_swqid_from_lid(mac_rf_queue_ctxt_t *queue,
lid_t lid, uint8_t is_dbg_tx)
{
(void)queue;
uint32_t bcn_region_type;
mac_rf_queue_t swq_id;
/* calulate hwqid */
if (lid <= LID_CSMA_CAP3) {
/* csma */
bcn_region_type = PLC_BCN_REGION_CSMA;
} else if (lid >= LID_BCSMA_START && lid <= LID_BCSMA_END) {
/* tdma or bcsma */
bcn_region_type = PLC_BCN_REGION_BCSMA;
} else if (lid >= LID_TDMA_START && lid <= LID_TDMA_END) {
/* tdma */
bcn_region_type = PLC_BCN_REGION_TDMA;
} else {
/* unknown lid type */
bcn_region_type = PLC_BCN_REGION_CSMA;
IOT_ASSERT(0);
}
swq_id = mac_rf_q_get_swq_type(bcn_region_type, lid, is_dbg_tx);
/* check if swq type is support */
if (swq_id == MAX_MAC_RF_QUE_NUM) {
/* swq type error */
IOT_ASSERT(0);
}
return swq_id;
}
uint32_t mac_rf_q_create_hwqid_from_swqid(mac_rf_queue_ctxt_t *queue,
mac_rf_queue_t swq_id)
{
uint32_t hwqid;
/* check if the hwq already enabled */
hwqid = mac_rf_q_get_hwqid(queue, swq_id);
if (hwqid == INV_MAC_HWQ_ID) {
/* hw queue is not enabled, try to alloc it */
hwqid = mac_rf_q_alloc_hwq(queue, swq_id);
}
return hwqid;
}
uint32_t mac_rf_block_all_tx_ena(mac_rf_queue_ctxt_t *tx_ctxt, uint32_t ena)
{
IOT_ASSERT(tx_ctxt);
ena = (ena == 0) ? 0 : 1;
if (tx_ctxt->is_block_all_tx == ena) {
return ERR_EXIST;
}
tx_ctxt->is_block_all_tx = (uint8_t)ena;
for (uint8_t qid = 0; qid < tx_ctxt->last_hwq_id; qid++) {
if (ena) {
/* disable all hwq to block hw tx */
mac_rf_txq_enable(qid, NULL);
} else {
/* recover and ena hwq*/
if (tx_ctxt->q_depth[qid] != 0) {
IOT_ASSERT(tx_ctxt->cur_hdl_desc[qid]);
mac_rf_txq_enable(qid, tx_ctxt->cur_hdl_desc[qid]);
}
}
}
return ERR_OK;
}
uint32_t mac_rf_is_block_all_tx(mac_rf_queue_ctxt_t *tx_ctxt)
{
IOT_ASSERT(tx_ctxt);
return tx_ctxt->is_block_all_tx;
}
#endif