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
							 |