252 lines
7.1 KiB
C
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
|