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
 |