1232 lines
		
	
	
		
			42 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			1232 lines
		
	
	
		
			42 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.
 | 
						|
 | 
						|
****************************************************************************/
 | 
						|
 | 
						|
/* os shim includes */
 | 
						|
#include "os_types.h"
 | 
						|
#include "os_mem.h"
 | 
						|
#include "os_timer.h"
 | 
						|
 | 
						|
/* common includes */
 | 
						|
#include "iot_module.h"
 | 
						|
#include "iot_errno.h"
 | 
						|
#include "iot_utils.h"
 | 
						|
#include "iot_io.h"
 | 
						|
#include "iot_config.h"
 | 
						|
 | 
						|
/* mac module internal includes */
 | 
						|
#include "mac_vdev.h"
 | 
						|
#include "mac_sched.h"
 | 
						|
#include "mac_sched_hw.h"
 | 
						|
#include "command_list.h"
 | 
						|
#include "mac_desc_engine.h"
 | 
						|
#include "mac_hwq_mgr.h"
 | 
						|
#include "mac_pdev.h"
 | 
						|
#include "mac.h"
 | 
						|
#include "plc_beacon.h"
 | 
						|
#include "hw_war.h"
 | 
						|
#include "mac_cert_test.h"
 | 
						|
 | 
						|
#include "mac_rf_pdev.h"
 | 
						|
#include "mac_rf_vdev.h"
 | 
						|
#include "mac_rf_sched.h"
 | 
						|
#include "mac_rf_tx_hw.h"
 | 
						|
#if HPLC_RF_DEV_SUPPORT
 | 
						|
#include "mac_rf_sched_hw.h"
 | 
						|
#include "mac_rf_isr.h"
 | 
						|
#endif
 | 
						|
 | 
						|
/* public api includes */
 | 
						|
#include "plc_fr.h"
 | 
						|
#include "mac_bcm_api.h"
 | 
						|
#include "mac_dsr.h"
 | 
						|
#include "mpdu_header.h"
 | 
						|
#include "iot_bitops_api.h"
 | 
						|
 | 
						|
#if HW_PLATFORM != HW_PLATFORM_SIMU
 | 
						|
 | 
						|
/* csma region pkt tx may be overlapped with next region due to HW issue.
 | 
						|
 * reserve some gap in the end of the csma region of each beacon period.
 | 
						|
 * unit is 1ms
 | 
						|
 */
 | 
						|
#define MAC_RF_SCHED_CSMA_GAP_MS           40
 | 
						|
 | 
						|
#else /* HW_PLATFORM != HW_PLATFORM_SIMU */
 | 
						|
 | 
						|
#define MAC_RF_SCHED_CSMA_GAP_MS           0
 | 
						|
 | 
						|
#endif /* HW_PLATFORM != HW_PLATFORM_SIMU */
 | 
						|
 | 
						|
/* if there is big hole between current ntb and start ntb of network beacon
 | 
						|
 * period. try to insert csma region into the hole to improve bandwidth
 | 
						|
 * utilization.
 | 
						|
 * if the whole equal or larged than this value, local device should insert
 | 
						|
 * the csma region. the unit is 1 ntb.
 | 
						|
 */
 | 
						|
#define MAC_RF_SCHED_INSERT_CSMA_TH        MAC_MS_TO_NTB(600)
 | 
						|
 | 
						|
/* if there is big hole between current ntb and start ntb of network beacon
 | 
						|
 * period. the amount of time reserved for software to be allocated time slot.
 | 
						|
 */
 | 
						|
#define MAC_RF_SCHED_PREPARE_CSMA_RESV_MS  40
 | 
						|
 | 
						|
/* define the supported minimum duration for command list.
 | 
						|
 * the unit is 1ms.
 | 
						|
 */
 | 
						|
#define MAC_RF_SCHED_CMD_LIST_DUR_MIN      500
 | 
						|
 | 
						|
/* define the max of rf slot dur, unit 1ms */
 | 
						|
#define MAC_RF_MAX_SLOT_DUR                15000
 | 
						|
 | 
						|
/* define rf slot dur, unit 1ms */
 | 
						|
#define MAC_RF_SLOT_DUR                    500
 | 
						|
 | 
						|
/* define minimum rf bc slot dur, unit 1ms */
 | 
						|
#define MAC_RF_BC_SLOT_DUR_MIN             30
 | 
						|
 | 
						|
/* scheulder context */
 | 
						|
typedef struct _mac_rf_sched_ctx {
 | 
						|
    /* current command list queue in use */
 | 
						|
    hw_sched_cmd_list_t *curr_hw_cmd_list;
 | 
						|
    /* command list queue */
 | 
						|
    hw_sched_cmd_list_t *hw_cmd_list[HW_SCHED_QUEUE_DEPTH];
 | 
						|
    /* command list queue count */
 | 
						|
    uint8_t hw_cmd_list_cnt;
 | 
						|
    /* command list queue pos of the next free slot */
 | 
						|
    uint8_t hw_cmd_list_pos;
 | 
						|
} mac_rf_sched_ctx_t;
 | 
						|
 | 
						|
#if HPLC_RF_DEV_SUPPORT
 | 
						|
 | 
						|
#if MAC_RF_SCHED_DEBUG
 | 
						|
 | 
						|
static void mac_rf_sched_dump(hw_sched_cmd_list_t *cl, uint16_t cnt)
 | 
						|
{
 | 
						|
    uint16_t i;
 | 
						|
 | 
						|
    iot_printf("%s total %lu, recusive %lu ----------------------\n",
 | 
						|
        __FUNCTION__, cnt, cl->recursive);
 | 
						|
    for (i = 0; i < cnt; i++) {
 | 
						|
        iot_printf("rf end offset - %lu, q_bm %x\n",
 | 
						|
            cl->cmd[i].rf_end_t, cl->cmd[i].rf_tx_q_en_bm);
 | 
						|
    }
 | 
						|
    iot_printf("------------------------------------------------------\n");
 | 
						|
}
 | 
						|
 | 
						|
#else /* MAC_SCHED_DEBUG */
 | 
						|
 | 
						|
#define mac_rf_sched_dump(cl, cnt)
 | 
						|
 | 
						|
#endif /* MAC_SCHED_DEBUG */
 | 
						|
 | 
						|
/* get wide band beacon queue bitmap according to appointed phase */
 | 
						|
static uint32_t mac_rf_sched_get_wb_bc_q(mac_rf_vdev_t *rf_vdev)
 | 
						|
{
 | 
						|
    uint32_t ret = 0;
 | 
						|
    IOT_ASSERT(rf_vdev);
 | 
						|
 | 
						|
    mac_rf_pdev_t *rf_pdev = get_rf_pdev_ptr(PLC_PDEV_ID, rf_vdev->ref_pdev_id);
 | 
						|
    IOT_ASSERT(rf_pdev);
 | 
						|
 | 
						|
    mac_rf_queue_ctxt_t *queue = &rf_pdev->hwq_hdl;
 | 
						|
 | 
						|
    ret = 1 << mac_rf_q_get_hwqid(queue, MAC_RF_QUE_BCN);
 | 
						|
 | 
						|
    return ret;
 | 
						|
}
 | 
						|
 | 
						|
/* get csma queue bitmap according to appointed phase */
 | 
						|
static uint32_t mac_rf_sched_get_csma_q(mac_rf_vdev_t *rf_vdev)
 | 
						|
{
 | 
						|
    uint32_t ret = 0;
 | 
						|
    IOT_ASSERT(rf_vdev);
 | 
						|
 | 
						|
    mac_rf_pdev_t *rf_pdev = get_rf_pdev_ptr(PLC_PDEV_ID, rf_vdev->ref_pdev_id);
 | 
						|
    IOT_ASSERT(rf_pdev);
 | 
						|
 | 
						|
    mac_rf_queue_ctxt_t *queue = &rf_pdev->hwq_hdl;
 | 
						|
 | 
						|
    ret = 1 << mac_rf_q_get_hwqid(queue, MAC_RF_QUE_CSMA_0);
 | 
						|
#if !ENA_RF_ONLY_ONE_CSMA_HWQ
 | 
						|
    /* rf csma just one hwq enable */
 | 
						|
    ret |= 1 << mac_rf_q_get_hwqid(queue, MAC_RF_QUE_CSMA_1);
 | 
						|
    ret |= 1 << mac_rf_q_get_hwqid(queue, MAC_RF_QUE_CSMA_2);
 | 
						|
    ret |= 1 << mac_rf_q_get_hwqid(queue, MAC_RF_QUE_CSMA_3);
 | 
						|
#if PLC_SUPPORT_DBG_PKT_MODE
 | 
						|
    ret |= 1 << mac_rf_q_get_hwqid(queue, MAC_RF_QUE_CSMA_DBG);
 | 
						|
#endif
 | 
						|
#endif
 | 
						|
 | 
						|
    return ret;
 | 
						|
}
 | 
						|
 | 
						|
/* get tdma queue bitmap according to appointed phase */
 | 
						|
uint32_t mac_rf_sched_get_tdma_q(mac_rf_vdev_t *rf_vdev)
 | 
						|
{
 | 
						|
    uint32_t ret = 0;
 | 
						|
    IOT_ASSERT(rf_vdev);
 | 
						|
 | 
						|
    mac_rf_pdev_t *rf_pdev = get_rf_pdev_ptr(PLC_PDEV_ID, rf_vdev->ref_pdev_id);
 | 
						|
    IOT_ASSERT(rf_pdev);
 | 
						|
 | 
						|
    mac_rf_queue_ctxt_t *queue = &rf_pdev->hwq_hdl;
 | 
						|
 | 
						|
    ret = 1 << mac_rf_q_get_hwqid(queue, MAC_RF_QUE_TDMA);
 | 
						|
 | 
						|
    return ret;
 | 
						|
}
 | 
						|
 | 
						|
/* get dedicated csma queue bitmap according to appointed phase */
 | 
						|
static uint32_t mac_rf_sched_get_dcsma_q(mac_rf_vdev_t *rf_vdev)
 | 
						|
{
 | 
						|
    uint32_t ret = 0;
 | 
						|
    IOT_ASSERT(rf_vdev);
 | 
						|
 | 
						|
    mac_rf_pdev_t *rf_pdev = get_rf_pdev_ptr(PLC_PDEV_ID, rf_vdev->ref_pdev_id);
 | 
						|
    IOT_ASSERT(rf_pdev);
 | 
						|
 | 
						|
    mac_rf_queue_ctxt_t *queue = &rf_pdev->hwq_hdl;
 | 
						|
 | 
						|
    ret = 1 << mac_rf_q_get_hwqid(queue, MAC_RF_QUE_BCSMA);
 | 
						|
 | 
						|
    return ret;
 | 
						|
}
 | 
						|
 | 
						|
static uint32_t mac_rf_sched_get_dbg_q(mac_rf_vdev_t *rf_vdev)
 | 
						|
{
 | 
						|
    uint32_t ret = 0;
 | 
						|
    IOT_ASSERT(rf_vdev);
 | 
						|
 | 
						|
    mac_rf_pdev_t *rf_pdev = get_rf_pdev_ptr(PLC_PDEV_ID, rf_vdev->ref_pdev_id);
 | 
						|
    IOT_ASSERT(rf_pdev);
 | 
						|
 | 
						|
    mac_rf_queue_ctxt_t *queue = &rf_pdev->hwq_hdl;
 | 
						|
 | 
						|
    ret = 1 << mac_rf_q_get_hwqid(queue, MAC_RF_QUE_CSMA_DBG);
 | 
						|
 | 
						|
    return ret;
 | 
						|
}
 | 
						|
 | 
						|
static hw_sched_cmd_list_t *mac_rf_sched_alloc_cmd_list(mac_rf_vdev_t *rf_vdev)
 | 
						|
{
 | 
						|
    mac_rf_sched_ctx_t *ctx = rf_vdev->rf_sched_ctx;
 | 
						|
    hw_sched_cmd_list_t *cl = NULL;
 | 
						|
 | 
						|
    IOT_ASSERT(ctx->hw_cmd_list_cnt <= HW_SCHED_QUEUE_DEPTH);
 | 
						|
 | 
						|
    if (ctx->hw_cmd_list_cnt < HW_SCHED_QUEUE_DEPTH) {
 | 
						|
        /* free command list vailable, allocate new one */
 | 
						|
        if (ctx->hw_cmd_list[ctx->hw_cmd_list_pos] == NULL) {
 | 
						|
            mac_desc_get(&g_mac_desc_eng, PLC_SCHED_CMD_LIST_POOL,
 | 
						|
                (void **)&cl);
 | 
						|
            ctx->hw_cmd_list[ctx->hw_cmd_list_pos] = cl;
 | 
						|
        } else {
 | 
						|
            cl = ctx->hw_cmd_list[ctx->hw_cmd_list_pos];
 | 
						|
        }
 | 
						|
 | 
						|
        ctx->hw_cmd_list_pos++;
 | 
						|
        if (ctx->hw_cmd_list_pos == HW_SCHED_QUEUE_DEPTH)
 | 
						|
            ctx->hw_cmd_list_pos = 0;
 | 
						|
        ctx->hw_cmd_list_cnt++;
 | 
						|
    } else {
 | 
						|
        /* check if any command list returned from HW */
 | 
						|
        if (mac_rf_sched_get_cmd_list_cnt(rf_vdev) >= HW_SCHED_QUEUE_DEPTH) {
 | 
						|
            //TODO: dbg for hw sched
 | 
						|
            os_mem_cpy(ctx->hw_cmd_list[0]->cmd, ctx->hw_cmd_list[1], 20);
 | 
						|
            IOT_ASSERT_DUMP(0, (uint32_t *)ctx->hw_cmd_list[0], 10);
 | 
						|
        }
 | 
						|
        /* re-use the previos command list returned from HW */
 | 
						|
        cl = ctx->hw_cmd_list[ctx->hw_cmd_list_pos];
 | 
						|
        ctx->hw_cmd_list_pos++;
 | 
						|
        if (ctx->hw_cmd_list_pos == HW_SCHED_QUEUE_DEPTH)
 | 
						|
            ctx->hw_cmd_list_pos = 0;
 | 
						|
    }
 | 
						|
    IOT_ASSERT(cl);
 | 
						|
    os_mem_set(cl, 0, sizeof(*cl));
 | 
						|
 | 
						|
#if MAC_RF_SCHED_DEBUG
 | 
						|
 | 
						|
    iot_printf("%s allocate %p\n", __FUNCTION__, cl->cmd);
 | 
						|
 | 
						|
#endif
 | 
						|
 | 
						|
    return cl;
 | 
						|
}
 | 
						|
 | 
						|
static void mac_rf_sched_free_cmd_list(mac_rf_vdev_t *vdev)
 | 
						|
{
 | 
						|
    mac_rf_sched_ctx_t *ctx = vdev->rf_sched_ctx;
 | 
						|
 | 
						|
    ctx->hw_cmd_list_cnt = 0;
 | 
						|
    ctx->hw_cmd_list_pos = 0;
 | 
						|
}
 | 
						|
 | 
						|
/* load command list into the HW scheduler, return 1 if the command list
 | 
						|
 * is already done.
 | 
						|
 */
 | 
						|
static uint32_t mac_rf_sched_load_cmd_list(mac_rf_vdev_t *rf_vdev,
 | 
						|
    hw_sched_cmd_list_t *cl)
 | 
						|
{
 | 
						|
    uint32_t cnt, curr_dur, left_dur;
 | 
						|
    hw_sched_cmd_t *start_cmd, *end_cmd, *last_cmd, *prev_cmd = NULL;
 | 
						|
 | 
						|
    if (cl->next_idx == cl->total_cnt) {
 | 
						|
        /* current command list is done */
 | 
						|
        return  1;
 | 
						|
    }
 | 
						|
 | 
						|
    IOT_ASSERT(cl->next_idx < cl->total_cnt);
 | 
						|
 | 
						|
    /* set start ntb of next beacon period */
 | 
						|
    mac_rf_sched_set_bp_start_ntb(rf_vdev, cl->start_ntb);
 | 
						|
 | 
						|
    /* calculate how many commands can be push into the HW scheduler */
 | 
						|
    cnt = cl->total_cnt - cl->next_idx;
 | 
						|
    cnt = min(cnt, HW_SHCED_CMD_DEPTH);
 | 
						|
    start_cmd = cl->cmd + cl->next_idx;
 | 
						|
    if (cl->next_idx) {
 | 
						|
        prev_cmd = start_cmd - 1;
 | 
						|
    }
 | 
						|
    end_cmd = start_cmd + (cnt - 1);
 | 
						|
    last_cmd = cl->cmd + (cl->total_cnt - 1);
 | 
						|
    /* push commands into the HW */
 | 
						|
    mac_rf_sched_set_bp_cmd_list(rf_vdev, start_cmd, (uint16_t)cnt);
 | 
						|
 | 
						|
    if (prev_cmd) {
 | 
						|
        curr_dur = end_cmd->rf_end_t - prev_cmd->rf_end_t;
 | 
						|
    } else {
 | 
						|
        curr_dur = end_cmd->rf_end_t;
 | 
						|
    }
 | 
						|
    if (last_cmd != end_cmd) {
 | 
						|
        /* reduce current command list duration to make sure enough
 | 
						|
         * duration left for the last command list.
 | 
						|
         */
 | 
						|
        left_dur = last_cmd->rf_end_t - end_cmd->rf_end_t;
 | 
						|
        while (left_dur < MAC_MS_TO_NTB(MAC_RF_SCHED_CMD_LIST_DUR_MIN)) {
 | 
						|
            end_cmd--;
 | 
						|
            cnt--;
 | 
						|
            IOT_ASSERT(end_cmd > start_cmd);
 | 
						|
            left_dur = last_cmd->rf_end_t - end_cmd->rf_end_t;
 | 
						|
        }
 | 
						|
        if (prev_cmd) {
 | 
						|
            curr_dur = end_cmd->rf_end_t - prev_cmd->rf_end_t;
 | 
						|
        } else {
 | 
						|
            curr_dur = end_cmd->rf_end_t;
 | 
						|
        }
 | 
						|
    }
 | 
						|
    IOT_ASSERT(curr_dur >= MAC_MS_TO_NTB(MAC_RF_SCHED_CMD_LIST_DUR_MIN));
 | 
						|
    /* set command list duration */
 | 
						|
    mac_rf_sched_set_bp_dur(rf_vdev, MAC_NTB_TO_MS(end_cmd->rf_end_t));
 | 
						|
#if MAC_RF_SCHED_DEBUG
 | 
						|
    iot_printf("%s %lu start offset %lu, end offset %lu\n", __FUNCTION__,
 | 
						|
        cl->total_cnt, prev_cmd ? prev_cmd->rf_end_t : 0,
 | 
						|
        end_cmd->rf_end_t);
 | 
						|
#endif
 | 
						|
 | 
						|
    /* trigger new beacon period */
 | 
						|
    mac_rf_sched_trigger_bp(rf_vdev);
 | 
						|
 | 
						|
    cl->next_idx += cnt;
 | 
						|
 | 
						|
    return 0;
 | 
						|
}
 | 
						|
 | 
						|
/* switch the units of offset from ms to ntb */
 | 
						|
void mac_rf_sched_offset_switch(hw_sched_cmd_list_t *cl, uint16_t cnt)
 | 
						|
{
 | 
						|
#if HW_PLATFORM != HW_PLATFORM_SIMU
 | 
						|
    for (uint32_t i = 0; i < cnt; i++) {
 | 
						|
        cl->cmd[i].rf_end_t = MAC_MS_TO_NTB(cl->cmd[i].rf_end_t);
 | 
						|
    }
 | 
						|
#else
 | 
						|
    (void)cl;
 | 
						|
    (void)cnt;
 | 
						|
#endif
 | 
						|
}
 | 
						|
 | 
						|
#if (PLC_SUPPORT_CCO_ROLE)
 | 
						|
 | 
						|
/* cco role device need to take care of both phase and band config */
 | 
						|
void mac_rf_sched_cco_set(mac_rf_vdev_t *rf_vdev, mac_bc_time_slot_t *ts,
 | 
						|
    uint64_t start_ntb64, uint64_t next_start_ntb64)
 | 
						|
{
 | 
						|
    uint16_t i, cnt = 0;
 | 
						|
    uint32_t start_offset = 0, judge_ntb = 0;
 | 
						|
    hw_sched_cmd_list_t *cl = NULL;
 | 
						|
 | 
						|
    IOT_ASSERT(rf_vdev);
 | 
						|
    mac_rf_sched_ctx_t *ctx = rf_vdev->rf_sched_ctx;
 | 
						|
    hw_sched_cmd_t *cmd;
 | 
						|
 | 
						|
    cl = mac_rf_sched_alloc_cmd_list(rf_vdev);
 | 
						|
    IOT_ASSERT(cl);
 | 
						|
    ctx->curr_hw_cmd_list = cl;
 | 
						|
    cmd = cl->cmd;
 | 
						|
 | 
						|
    cl->alloc_ntb = mac_rf_sched_get_ntb(rf_vdev);
 | 
						|
    cl->caller = 1;
 | 
						|
 | 
						|
    cl->start_ntb = iot_uint64_lower32(start_ntb64);
 | 
						|
    cl->start_ntb_h = iot_uint64_higher32(start_ntb64);
 | 
						|
 | 
						|
    /* prepare central beacon slot */
 | 
						|
    uint32_t rf_start_offset = start_offset;
 | 
						|
    // TODO: need to support CCO not simultaneously tx hplc and rf package.
 | 
						|
    /* rf beacon slot */
 | 
						|
    if (ts->rf_std_tx) {
 | 
						|
        rf_start_offset += ts->rf_bc_slot_dur;
 | 
						|
    } else {
 | 
						|
        rf_start_offset += ts->bc_slot_dur;
 | 
						|
    }
 | 
						|
    cmd->rf_end_t = rf_start_offset;
 | 
						|
    cmd->rf_tx_q_en_bm = mac_rf_sched_get_wb_bc_q(rf_vdev);
 | 
						|
 | 
						|
    /* calculate center beacon slot */
 | 
						|
    start_offset += ts->cco_bc_cnt * ts->bc_slot_dur;
 | 
						|
 | 
						|
    /* prepere proxy and discovery beacon slot */
 | 
						|
    if (ts->non_cco_bc_info.bc_cnt) {
 | 
						|
        start_offset += ts->non_cco_bc_info.bc_cnt * ts->bc_slot_dur;
 | 
						|
    }
 | 
						|
 | 
						|
    /* ensure standard rf slot does not overlap with CSMA slot */
 | 
						|
    if (start_offset > rf_start_offset) {
 | 
						|
        /* new cmd */
 | 
						|
        cnt++;
 | 
						|
        cmd++;
 | 
						|
 | 
						|
        cmd->rf_end_t = start_offset;
 | 
						|
    } else if (start_offset < rf_start_offset) {
 | 
						|
        iot_printf("waring rf beacon slot overlap with CSMA slot. "
 | 
						|
            "TDMA slot:%lu, rf beacon slot:%lu\n",
 | 
						|
            start_offset, rf_start_offset);
 | 
						|
        cmd->rf_end_t = start_offset;
 | 
						|
    }
 | 
						|
 | 
						|
    /* new cmd */
 | 
						|
    cnt++;
 | 
						|
    cmd++;
 | 
						|
 | 
						|
    /* prepare tdma slot */
 | 
						|
    if (ts->tdma_slot_dur) {
 | 
						|
        /* prepare tdma for cco device */
 | 
						|
        for (i = 0; i < ts->cco_bc_cnt; i++) {
 | 
						|
            start_offset += ts->tdma_slot_dur;
 | 
						|
        }
 | 
						|
        cmd->rf_end_t = start_offset;
 | 
						|
        cmd->rf_tx_q_en_bm = mac_rf_sched_get_tdma_q(rf_vdev);
 | 
						|
        cnt++;
 | 
						|
        cmd++;
 | 
						|
        /* prepare tdma for pco and sta device */
 | 
						|
        if (ts->non_cco_bc_info.bc_cnt) {
 | 
						|
            start_offset += ts->tdma_slot_dur * ts->non_cco_bc_info.bc_cnt;
 | 
						|
            cmd->rf_end_t = start_offset;
 | 
						|
            cnt++;
 | 
						|
            cmd++;
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    /* prepare csma slot */
 | 
						|
    judge_ntb = start_offset;
 | 
						|
    for (i = 0; i < ts->csma_info.phase_cnt; i++) {
 | 
						|
        start_offset += ts->csma_info.slot_dur[i];
 | 
						|
    }
 | 
						|
    /* judge csma exist */
 | 
						|
    if (judge_ntb != start_offset) {
 | 
						|
        cmd->rf_tx_q_en_bm = mac_rf_sched_get_csma_q(rf_vdev);
 | 
						|
        cmd->rf_end_t = start_offset - MAC_RF_SCHED_CSMA_GAP_MS;
 | 
						|
        cnt++;
 | 
						|
        cmd++;
 | 
						|
        if (MAC_RF_SCHED_CSMA_GAP_MS) {
 | 
						|
            cmd->rf_end_t = start_offset;
 | 
						|
            cnt++;
 | 
						|
            cmd++;
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    /* prepare dedicated csma slot */
 | 
						|
    judge_ntb = start_offset;
 | 
						|
    for (i = 0; i < ts->d_csma_info.phase_cnt; i++) {
 | 
						|
        start_offset += ts->d_csma_info.slot_dur[i];
 | 
						|
    }
 | 
						|
    /* judge dcsma exist */
 | 
						|
    if (judge_ntb != start_offset) {
 | 
						|
        cmd->rf_tx_q_en_bm = mac_rf_sched_get_dcsma_q(rf_vdev);
 | 
						|
        cmd->rf_end_t = start_offset - MAC_RF_SCHED_CSMA_GAP_MS;
 | 
						|
        cnt++;
 | 
						|
        cmd++;
 | 
						|
        if (MAC_RF_SCHED_CSMA_GAP_MS) {
 | 
						|
            cmd->rf_end_t = start_offset;
 | 
						|
            cnt++;
 | 
						|
            cmd++;
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    uint64_t tmp_ntb = next_start_ntb64 - start_ntb64;
 | 
						|
    IOT_ASSERT(iot_uint64_higher32(tmp_ntb) == 0);
 | 
						|
    uint32_t end_offset = MAC_NTB_TO_MS(iot_uint64_lower32(tmp_ntb));
 | 
						|
    /* if there is a hole form the current config beacon peirod to
 | 
						|
     * next beacon period
 | 
						|
     */
 | 
						|
    if (end_offset > start_offset) {
 | 
						|
        start_offset = end_offset;
 | 
						|
        cmd->rf_tx_q_en_bm = mac_rf_sched_get_csma_q(rf_vdev);
 | 
						|
        cmd->rf_end_t = start_offset;
 | 
						|
        cnt++;
 | 
						|
        cmd++;
 | 
						|
 | 
						|
    }
 | 
						|
    uint32_t hole_offset, hole_csma_cnt, hole_remain, more = 0;
 | 
						|
    uint64_t cur_ntb = mac_rf_sched_get_ntb64(rf_vdev);
 | 
						|
    /* if there is a hole from current ntb to the current beacon period */
 | 
						|
    if ((cur_ntb + MAC_RF_SCHED_INSERT_CSMA_TH) < start_ntb64) {
 | 
						|
        tmp_ntb = start_ntb64 - cur_ntb;
 | 
						|
        iot_printf("%s insert csma %lu ms into hole from %lu to %lu\n",
 | 
						|
            __FUNCTION__, MAC_NTB_TO_MS((uint32_t)tmp_ntb),
 | 
						|
            iot_uint64_lower32(cur_ntb),
 | 
						|
            iot_uint64_lower32(start_ntb64));
 | 
						|
        hole_offset = (uint32_t)MAC_NTB_TO_MS(tmp_ntb) -
 | 
						|
            MAC_RF_SCHED_PREPARE_CSMA_RESV_MS - MAC_RF_SCHED_CSMA_GAP_MS;
 | 
						|
        i = 0;
 | 
						|
        start_offset = 0;
 | 
						|
        if (hole_offset > MAC_RF_MAX_SLOT_DUR) {
 | 
						|
            hole_csma_cnt = hole_offset / MAC_RF_MAX_SLOT_DUR;
 | 
						|
            hole_remain = hole_offset % MAC_RF_MAX_SLOT_DUR;
 | 
						|
            if (hole_remain > MAC_RF_SLOT_DUR) {
 | 
						|
                more = 1;
 | 
						|
            }
 | 
						|
            /* try to insert csma command put as many as possible */
 | 
						|
            IOT_ASSERT(hole_csma_cnt + more + 1 < HW_SCHED_CMD_MAX_CNT);
 | 
						|
            os_mem_move(&cl->cmd[hole_csma_cnt + more + 1], &cl->cmd[0],
 | 
						|
                sizeof(cl->cmd[0]) * cnt);
 | 
						|
            cmd = cl->cmd;
 | 
						|
            while (i < hole_csma_cnt) {
 | 
						|
                cmd->rf_tx_q_en_bm = mac_rf_sched_get_csma_q(rf_vdev);
 | 
						|
                start_offset += MAC_RF_MAX_SLOT_DUR;
 | 
						|
                cmd->rf_end_t = start_offset;
 | 
						|
                cnt++;
 | 
						|
                cmd++;
 | 
						|
                i++;
 | 
						|
            }
 | 
						|
            if (hole_remain > MAC_RF_SLOT_DUR) {
 | 
						|
                cmd->rf_tx_q_en_bm = mac_rf_sched_get_csma_q(rf_vdev);
 | 
						|
                start_offset += hole_remain;
 | 
						|
                cmd->rf_end_t = start_offset;
 | 
						|
                cnt++;
 | 
						|
                cmd++;
 | 
						|
                i++;
 | 
						|
            } else {
 | 
						|
                cmd--;
 | 
						|
                start_offset += hole_remain;
 | 
						|
                cmd->rf_end_t = start_offset;
 | 
						|
                cmd++;
 | 
						|
            }
 | 
						|
        } else {
 | 
						|
            /* try to insert csma command put as many as possible */
 | 
						|
            os_mem_move(&cl->cmd[2], &cl->cmd[0], sizeof(cl->cmd[0]) * cnt);
 | 
						|
            cmd = cl->cmd;
 | 
						|
            cmd->rf_tx_q_en_bm = mac_rf_sched_get_csma_q(rf_vdev);
 | 
						|
            start_offset += hole_offset;
 | 
						|
            cmd->rf_end_t = start_offset;
 | 
						|
            cnt++;
 | 
						|
            cmd++;
 | 
						|
            i++;
 | 
						|
        }
 | 
						|
        /* disable tx for the last csma command before beacon region.
 | 
						|
         * see MAC_SCHED_CSMA_GAP_MS for more info.
 | 
						|
         */
 | 
						|
        start_offset += MAC_RF_SCHED_CSMA_GAP_MS;
 | 
						|
        cmd->rf_end_t = start_offset;
 | 
						|
        cmd->rf_tx_q_en_bm = 0;
 | 
						|
        cnt++;
 | 
						|
        cmd++;
 | 
						|
        i++;
 | 
						|
        /* fix the end offset of following commands */
 | 
						|
        for (; i < cnt; i++) {
 | 
						|
            cmd->rf_end_t += start_offset;
 | 
						|
            cmd++;
 | 
						|
        }
 | 
						|
        cl->start_ntb -= (uint32_t)(tmp_ntb -
 | 
						|
            MAC_MS_TO_NTB(MAC_RF_SCHED_PREPARE_CSMA_RESV_MS));
 | 
						|
    }
 | 
						|
 | 
						|
    IOT_ASSERT(cnt <= HW_SCHED_CMD_MAX_CNT);
 | 
						|
 | 
						|
    cl->total_cnt = cnt;
 | 
						|
    mac_rf_sched_dump(cl, cnt);
 | 
						|
 | 
						|
    mac_rf_sched_offset_switch(cl, cnt);
 | 
						|
    mac_rf_sched_load_cmd_list(rf_vdev, cl);
 | 
						|
    mac_rf_sched_enable_bp(rf_vdev, 1);
 | 
						|
}
 | 
						|
 | 
						|
void mac_rf_sched_cco_bc_alert(mac_rf_vdev_t *rf_vdev, uint8_t cco_started)
 | 
						|
{
 | 
						|
    uint64_t tmp;
 | 
						|
    if (!cco_started) {
 | 
						|
        tmp = mac_rf_sched_get_ntb64(rf_vdev) +
 | 
						|
            MAC_MS_TO_NTB(MAC_BP_AHEAD_ALERT_DUR);
 | 
						|
        /* rf schedule set csma only */
 | 
						|
        mac_rf_sched_set_csma_only(rf_vdev, tmp, 0);
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
#else /* PLC_SUPPORT_CCO_ROLE */
 | 
						|
 | 
						|
/* cco role device need to take care of both phase and band config */
 | 
						|
void mac_rf_sched_cco_set(mac_rf_vdev_t *rf_vdev, mac_bc_time_slot_t *ts,
 | 
						|
    uint64_t start_ntb64, uint64_t next_start_ntb64)
 | 
						|
{
 | 
						|
    (void)rf_vdev;
 | 
						|
    (void)ts;
 | 
						|
    (void)start_ntb64;
 | 
						|
    (void)next_start_ntb64;
 | 
						|
    IOT_ASSERT(0);
 | 
						|
}
 | 
						|
 | 
						|
void mac_rf_sched_cco_bc_alert(mac_rf_vdev_t *rf_vdev, uint8_t cco_started)
 | 
						|
{
 | 
						|
    (void)rf_vdev;
 | 
						|
    (void)cco_started;
 | 
						|
}
 | 
						|
 | 
						|
#endif /* PLC_SUPPORT_CCO_ROLE */
 | 
						|
 | 
						|
/* sta device need to take care of band config */
 | 
						|
uint32_t mac_rf_sched_sta_set(mac_rf_vdev_t *rf_vdev, mac_bc_time_slot_t *ts,
 | 
						|
    uint32_t start_ntb, uint8_t need_early_stop)
 | 
						|
{
 | 
						|
    uint16_t i, j, cnt = 0;
 | 
						|
    uint8_t new_cmd_required = 0, csma_is_exist = 0;
 | 
						|
    uint32_t start_offset = 0, rf_start_offset = 0, judge_ntb = 0;
 | 
						|
    hw_sched_cmd_list_t *cl = NULL;
 | 
						|
    uint32_t rf_bc_slot_dur = ts->rf_bc_slot_dur;
 | 
						|
    /* clear flag every time  */
 | 
						|
    rf_vdev->bcsma_slot_exist = 0;
 | 
						|
 | 
						|
    IOT_ASSERT(rf_vdev);
 | 
						|
    mac_rf_sched_ctx_t *ctx = rf_vdev->rf_sched_ctx;
 | 
						|
    hw_sched_cmd_t *cmd;
 | 
						|
    uint32_t sta_tx_type = BEACON_TX_ONLY_HPLC;
 | 
						|
    tei_t self_tei = rf_vdev_get_tei(rf_vdev);
 | 
						|
 | 
						|
    cl = mac_rf_sched_alloc_cmd_list(rf_vdev);
 | 
						|
    IOT_ASSERT(cl);
 | 
						|
    ctx->curr_hw_cmd_list = cl;
 | 
						|
    cl->start_ntb = start_ntb;
 | 
						|
    cmd = cl->cmd;
 | 
						|
 | 
						|
    //TODO: dbg for hw sched
 | 
						|
    cl->alloc_ntb = mac_rf_sched_get_ntb(rf_vdev);
 | 
						|
    cl->caller = 2;
 | 
						|
 | 
						|
    /* prepare central beacon slot */
 | 
						|
    if (ts->bc_slot_dur) {
 | 
						|
        start_offset += ts->bc_slot_dur * ts->cco_bc_cnt;
 | 
						|
        cmd->rf_end_t = start_offset;
 | 
						|
        new_cmd_required = 1;
 | 
						|
 | 
						|
        /* check rf bc slot duration */
 | 
						|
        if (rf_bc_slot_dur < MAC_RF_BC_SLOT_DUR_MIN) {
 | 
						|
            /* align with bc slot */
 | 
						|
            rf_bc_slot_dur = iot_ceil(MAC_RF_BC_SLOT_DUR_MIN, ts->bc_slot_dur) *
 | 
						|
                ts->bc_slot_dur;
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    if (!ts->non_cco_bc_info.tei_valid || (self_tei == PLC_TEI_INVAL)) {
 | 
						|
        /* if non bc cnt is not 0, need occupied */
 | 
						|
        if (ts->non_cco_bc_info.bc_cnt) {
 | 
						|
            start_offset += ts->bc_slot_dur * ts->non_cco_bc_info.bc_cnt;
 | 
						|
            cmd->rf_end_t = start_offset;
 | 
						|
            new_cmd_required = 1;
 | 
						|
        }
 | 
						|
        goto bc_done;
 | 
						|
    }
 | 
						|
 | 
						|
    /* prepere proxy and discovery beacon slot */
 | 
						|
    for (i = 0; i < ts->non_cco_bc_info.bc_cnt; i++) {
 | 
						|
        if (ts->non_cco_bc_info.sta[i].tei == self_tei) {
 | 
						|
            uint16_t tx_flag = ts->non_cco_bc_info.sta[i].tx_flag;
 | 
						|
            sta_tx_type = (uint32_t)tx_flag;
 | 
						|
            /* we think the normal process must be that BEACON_TX_HPLC_RF
 | 
						|
             * or BEACON_TX_HPLC_SIMPLE_RF comes first. otherwise it is an
 | 
						|
             * abnormal slot configuration, we just config slot, do not
 | 
						|
             * enable hwq_bitmap.
 | 
						|
             * NOTE: if BEACON_TX_ONLY_HPLC comes first, the next slot is
 | 
						|
             * BEACON_TX_ONLY_RF, and tei is same. we think that this case is a
 | 
						|
             * BEACON_TX_HPLC_RF. enable hwq_bitmap according to the case of
 | 
						|
             * BEACON_TX_HPLC_RF.
 | 
						|
             * if BEACON_TX_ONLY_RF comes first, maybe cco just want sta to send
 | 
						|
             * rf beacon, we also enable hwq_bitmap.
 | 
						|
             */
 | 
						|
            switch (tx_flag) {
 | 
						|
            case BEACON_TX_ONLY_HPLC:
 | 
						|
            {
 | 
						|
                start_offset += ts->bc_slot_dur;
 | 
						|
                cmd->rf_end_t = start_offset;
 | 
						|
 | 
						|
                j = i + 1;
 | 
						|
                /* judge i + 1 slot */
 | 
						|
                if (j < ts->non_cco_bc_info.bc_cnt) {
 | 
						|
                    tx_flag = ts->non_cco_bc_info.sta[j].tx_flag;
 | 
						|
                    if (ts->non_cco_bc_info.sta[j].tei == self_tei && tx_flag ==
 | 
						|
                        BEACON_TX_ONLY_RF) {
 | 
						|
                        sta_tx_type = BEACON_TX_HPLC_RF;
 | 
						|
                        /* new cmd */
 | 
						|
                        cnt++;
 | 
						|
                        cmd++;
 | 
						|
                        cmd->rf_tx_q_en_bm =
 | 
						|
                            mac_rf_sched_get_wb_bc_q(rf_vdev);
 | 
						|
                        start_offset += ts->bc_slot_dur;
 | 
						|
                        cmd->rf_end_t = start_offset;
 | 
						|
 | 
						|
                        for (j = j + 1; j < ts->non_cco_bc_info.bc_cnt; j++) {
 | 
						|
                            tx_flag = ts->non_cco_bc_info.sta[j].tx_flag;
 | 
						|
                            if (ts->non_cco_bc_info.sta[j].tei == self_tei &&
 | 
						|
                                tx_flag == BEACON_TX_ONLY_RF) {
 | 
						|
                                start_offset += ts->bc_slot_dur;
 | 
						|
                                cmd->rf_end_t = start_offset;
 | 
						|
                            } else {
 | 
						|
                                break;
 | 
						|
                            }
 | 
						|
                        }
 | 
						|
                        if (j < ts->non_cco_bc_info.bc_cnt) {
 | 
						|
                            /* new cmd */
 | 
						|
                            cnt++;
 | 
						|
                            cmd++;
 | 
						|
                        }
 | 
						|
                    }
 | 
						|
                }
 | 
						|
 | 
						|
                if (j < ts->non_cco_bc_info.bc_cnt) {
 | 
						|
                    for (; j < ts->non_cco_bc_info.bc_cnt; j++) {
 | 
						|
                        tx_flag = ts->non_cco_bc_info.sta[j].tx_flag;
 | 
						|
                        if (ts->non_cco_bc_info.sta[j].tei == self_tei) {
 | 
						|
                            iot_printf("%s warning, hplc only err tei:%lu, "
 | 
						|
                            "type:%lu, st pos:%lu, cur pos:%lu\n",
 | 
						|
                            __FUNCTION__, ts->non_cco_bc_info.sta[j].tei,
 | 
						|
                            ts->non_cco_bc_info.sta[j].tx_flag, i, j);
 | 
						|
                        }
 | 
						|
                        start_offset += ts->bc_slot_dur;
 | 
						|
                        cmd->rf_end_t = start_offset;
 | 
						|
                    }
 | 
						|
                }
 | 
						|
                new_cmd_required = 1;
 | 
						|
                break;
 | 
						|
            }
 | 
						|
            case BEACON_TX_ONLY_RF:
 | 
						|
            {
 | 
						|
                /* normally, this type does not come first */
 | 
						|
                iot_printf("%s warning abnomal type:%lu, tei:%lu, pos:%lu\n",
 | 
						|
                    __FUNCTION__, tx_flag,
 | 
						|
                    ts->non_cco_bc_info.sta[i].tei, i);
 | 
						|
 | 
						|
                /* new cmd */
 | 
						|
                cnt++;
 | 
						|
                cmd++;
 | 
						|
 | 
						|
                start_offset += ts->bc_slot_dur;
 | 
						|
                cmd->rf_end_t = start_offset;
 | 
						|
                cmd->rf_tx_q_en_bm = mac_rf_sched_get_wb_bc_q(rf_vdev);
 | 
						|
 | 
						|
                for (j = i + 1; j < ts->non_cco_bc_info.bc_cnt; j++) {
 | 
						|
                    tx_flag = ts->non_cco_bc_info.sta[j].tx_flag;
 | 
						|
                    if ((BEACON_TX_ONLY_RF != tx_flag) ||
 | 
						|
                        (ts->non_cco_bc_info.sta[j].tei != self_tei)) {
 | 
						|
                        break;
 | 
						|
                    }
 | 
						|
                    start_offset += ts->bc_slot_dur;
 | 
						|
                    cmd->rf_end_t = start_offset;
 | 
						|
                }
 | 
						|
 | 
						|
                if (j < ts->non_cco_bc_info.bc_cnt) {
 | 
						|
                    cnt++;
 | 
						|
                    cmd++;
 | 
						|
                    start_offset += ts->bc_slot_dur *
 | 
						|
                        (ts->non_cco_bc_info.bc_cnt - j);
 | 
						|
                    cmd->rf_end_t = start_offset;
 | 
						|
                }
 | 
						|
                new_cmd_required = 1;
 | 
						|
                break;
 | 
						|
            }
 | 
						|
            case BEACON_TX_HPLC_RF:
 | 
						|
            case BEACON_TX_HPLC_RF_SYNC:
 | 
						|
            {
 | 
						|
                if (tx_flag == BEACON_TX_HPLC_RF) {
 | 
						|
                    /* send rf package after the current slot ends */
 | 
						|
                    start_offset += ts->bc_slot_dur;
 | 
						|
                    cmd->rf_end_t = start_offset;
 | 
						|
 | 
						|
                    /* new cmd */
 | 
						|
                    cnt++;
 | 
						|
                    cmd++;
 | 
						|
 | 
						|
                    cmd->rf_tx_q_en_bm = mac_rf_sched_get_wb_bc_q(rf_vdev);
 | 
						|
                    rf_start_offset = start_offset;
 | 
						|
                    rf_start_offset += rf_bc_slot_dur;
 | 
						|
                    cmd->rf_end_t = rf_start_offset;
 | 
						|
                } else {
 | 
						|
                    /* new cmd */
 | 
						|
                    cnt++;
 | 
						|
                    cmd++;
 | 
						|
 | 
						|
                    cmd->rf_tx_q_en_bm = mac_rf_sched_get_wb_bc_q(rf_vdev);
 | 
						|
                    rf_start_offset = start_offset;
 | 
						|
                    rf_start_offset += rf_bc_slot_dur;
 | 
						|
                    cmd->rf_end_t = rf_start_offset;
 | 
						|
                    start_offset += ts->bc_slot_dur;
 | 
						|
                }
 | 
						|
                new_cmd_required = 1;
 | 
						|
 | 
						|
                /* check that the time slot is correct */
 | 
						|
                for (j = i + 1; j < ts->non_cco_bc_info.bc_cnt; j++) {
 | 
						|
                    tx_flag = ts->non_cco_bc_info.sta[j].tx_flag;
 | 
						|
                    if (ts->non_cco_bc_info.sta[j].tei == self_tei) {
 | 
						|
                        if (BEACON_TX_ONLY_RF != tx_flag) {
 | 
						|
                            iot_printf("%s warning tx std bcn abnormal "
 | 
						|
                                "tei:%lu, type:%lu, std pos:%lu, "
 | 
						|
                                "cur pos:%lu\n",
 | 
						|
                                __FUNCTION__,
 | 
						|
                                ts->non_cco_bc_info.sta[j].tei, tx_flag,
 | 
						|
                                i, j);
 | 
						|
                        }
 | 
						|
                    }
 | 
						|
 | 
						|
                    start_offset += ts->bc_slot_dur;
 | 
						|
                    /* ensure standard rf slot does not overlap with
 | 
						|
                     * other node slots.
 | 
						|
                     */
 | 
						|
                    if (start_offset >= rf_start_offset) {
 | 
						|
                        if (ts->non_cco_bc_info.sta[j].tei != self_tei &&
 | 
						|
                            BEACON_TX_ONLY_RF == tx_flag &&
 | 
						|
                            (start_offset - ts->bc_slot_dur) <
 | 
						|
                            rf_start_offset) {
 | 
						|
                            /* rf_bc_slot_dur is not an integer
 | 
						|
                             * multiple of bc_slot_dur
 | 
						|
                             */
 | 
						|
                            iot_printf("%s, warning std bcn miscfg, "
 | 
						|
                                "self tei:%lu, self type:%lu, "
 | 
						|
                                "conflict tei:%lu, tx type:%lu, "
 | 
						|
                                "start_offset:%lu, rf_start_offset:%lu, "
 | 
						|
                                "bc_slot_dur:%lu, std pos:%lu, cur pos:%lu\n",
 | 
						|
                                __FUNCTION__,
 | 
						|
                                ts->non_cco_bc_info.sta[i].tei,
 | 
						|
                                ts->non_cco_bc_info.sta[i].tx_flag,
 | 
						|
                                ts->non_cco_bc_info.sta[j].tei,
 | 
						|
                                ts->non_cco_bc_info.sta[j].tx_flag,
 | 
						|
                                start_offset, rf_start_offset, ts->bc_slot_dur,
 | 
						|
                                i, j);
 | 
						|
                        }
 | 
						|
 | 
						|
                        if (new_cmd_required) {
 | 
						|
                            cnt++;
 | 
						|
                            cmd++;
 | 
						|
                            new_cmd_required = 0;
 | 
						|
                        }
 | 
						|
 | 
						|
                        cmd->rf_end_t = start_offset;
 | 
						|
                    } else {
 | 
						|
                        /* just check tei different, the same tei situation
 | 
						|
                         * has been detected previously.
 | 
						|
                         */
 | 
						|
                        if (ts->non_cco_bc_info.sta[j].tei != self_tei) {
 | 
						|
                            if (tx_flag != BEACON_TX_HPLC_CSMA_SIMPLE_RF &&
 | 
						|
                                tx_flag != BEACON_TX_ONLY_HPLC) {
 | 
						|
                                /* if come here, indicate that rf node slots
 | 
						|
                                 * overlap each other and may be misconfigured
 | 
						|
                                 */
 | 
						|
                                iot_printf("%s, warning std bcn miscfg, "
 | 
						|
                                    "self tei:%lu, self type:%lu, "
 | 
						|
                                    "conflict tei:%lu, tx type:%lu, "
 | 
						|
                                    "start_offset:%lu, rf_start_offset:%lu,"
 | 
						|
                                    " std pos:%lu, cur pos:%lu\n",
 | 
						|
                                    __FUNCTION__,
 | 
						|
                                    ts->non_cco_bc_info.sta[i].tei,
 | 
						|
                                    ts->non_cco_bc_info.sta[i].tx_flag,
 | 
						|
                                    ts->non_cco_bc_info.sta[j].tei,
 | 
						|
                                    ts->non_cco_bc_info.sta[j].tx_flag,
 | 
						|
                                    start_offset, rf_start_offset, i, j);
 | 
						|
                                // TODO: maybe do something to backoff other slot
 | 
						|
                            }
 | 
						|
                        }
 | 
						|
                    }
 | 
						|
                }
 | 
						|
 | 
						|
                /* if the rf_bc_slot_dur exceeds the entire non bc period,
 | 
						|
                 * we consider this is unreasonable, need print and handle.
 | 
						|
                 */
 | 
						|
                if (start_offset < rf_start_offset) {
 | 
						|
                    iot_printf("%s warning std rf cfg is err, self tei:%lu"
 | 
						|
                        " config_rf:%lu, etr_non_pd:%lu\n",
 | 
						|
                        __FUNCTION__, self_tei, rf_start_offset, start_offset);
 | 
						|
 | 
						|
                    /* fix hplc+rf test bed STA slot time management case fail,
 | 
						|
                     * pco dev is not assigned rf tdma slot to send rf beacon.
 | 
						|
                     * ensure that rf beacon has enought time slot, allow
 | 
						|
                     * this TDMA time slot overlapped with following time slot.
 | 
						|
                     */
 | 
						|
                    if (mac_get_cert_test_flag()) {
 | 
						|
                        start_offset = rf_start_offset;
 | 
						|
                        cmd->rf_end_t = start_offset;
 | 
						|
                    } else {
 | 
						|
                        /* ensure that the TDMA time slot does not
 | 
						|
                         * exceed the CSMA time slot.
 | 
						|
                         */
 | 
						|
                        rf_start_offset = start_offset;
 | 
						|
                        cmd->rf_end_t = rf_start_offset;
 | 
						|
                    }
 | 
						|
                }
 | 
						|
 | 
						|
                new_cmd_required = 1;
 | 
						|
                break;
 | 
						|
            }
 | 
						|
            case BEACON_TX_HPLC_SIMPLE_RF:
 | 
						|
            {
 | 
						|
                /* send rf package after the current slot ends */
 | 
						|
                start_offset += ts->bc_slot_dur;
 | 
						|
                cmd->rf_end_t = start_offset;
 | 
						|
 | 
						|
                /* new cmd */
 | 
						|
                cnt++;
 | 
						|
                cmd++;
 | 
						|
 | 
						|
                cmd->rf_tx_q_en_bm = mac_rf_sched_get_wb_bc_q(rf_vdev);
 | 
						|
                start_offset += ts->bc_slot_dur;
 | 
						|
                cmd->rf_end_t = start_offset;
 | 
						|
                new_cmd_required = 1;
 | 
						|
 | 
						|
                /* judge i + 1 slot */
 | 
						|
                if (i + 1 < ts->non_cco_bc_info.bc_cnt) {
 | 
						|
                    tx_flag = ts->non_cco_bc_info.sta[i + 1].tx_flag;
 | 
						|
                    if (ts->non_cco_bc_info.sta[i + 1].tei == self_tei) {
 | 
						|
                        if (BEACON_TX_ONLY_RF != tx_flag) {
 | 
						|
                            iot_printf("%s warning next simple bcn err tei:%lu, "
 | 
						|
                                "type:%lu, simple pos:%lu, cur pos:%lu\n",
 | 
						|
                                __FUNCTION__, ts->non_cco_bc_info.sta[i+ 1].tei,
 | 
						|
                                tx_flag, i, i + 1);
 | 
						|
                        }
 | 
						|
                    } else {
 | 
						|
                        if (BEACON_TX_ONLY_RF == tx_flag) {
 | 
						|
                            iot_printf("%s warning next simple, self tei:%lu, "
 | 
						|
                                "type:%lu, conflict tei:%lu, type:%lu, "
 | 
						|
                                "simple pos:%lu, rf pos:%lu\n",
 | 
						|
                                __FUNCTION__,
 | 
						|
                                ts->non_cco_bc_info.sta[i].tei,
 | 
						|
                                ts->non_cco_bc_info.sta[i].tx_flag,
 | 
						|
                                ts->non_cco_bc_info.sta[i + 1].tei,
 | 
						|
                                ts->non_cco_bc_info.sta[i + 1].tx_flag,
 | 
						|
                                i, i + 1);
 | 
						|
                        }
 | 
						|
                    }
 | 
						|
                } else {
 | 
						|
                    iot_printf("%s warning simple bcn err, slot empty tei:%lu, "
 | 
						|
                        "type:%lu, simple pos:%lu, non bc cnt:%lu\n",
 | 
						|
                        __FUNCTION__, ts->non_cco_bc_info.sta[i].tei,
 | 
						|
                        ts->non_cco_bc_info.sta[i].tx_flag,
 | 
						|
                        i, ts->non_cco_bc_info.bc_cnt);
 | 
						|
                }
 | 
						|
 | 
						|
                /* check that the time slot is correct */
 | 
						|
                for (j = i + 2; j < ts->non_cco_bc_info.bc_cnt; j++) {
 | 
						|
                    if (ts->non_cco_bc_info.sta[j].tei == self_tei) {
 | 
						|
                        iot_printf("%s warning simple bcn err tei:%lu, "
 | 
						|
                            "type:%lu, simple pos:%lu, cur pos:%lu\n",
 | 
						|
                            __FUNCTION__, ts->non_cco_bc_info.sta[j].tei,
 | 
						|
                            tx_flag, i, j);
 | 
						|
                    }
 | 
						|
 | 
						|
                    if (new_cmd_required) {
 | 
						|
                        cnt++;
 | 
						|
                        cmd++;
 | 
						|
                        new_cmd_required = 0;
 | 
						|
                    }
 | 
						|
 | 
						|
                    start_offset += ts->bc_slot_dur;
 | 
						|
                    cmd->rf_end_t = start_offset;
 | 
						|
                }
 | 
						|
                new_cmd_required = 1;
 | 
						|
                break;
 | 
						|
            }
 | 
						|
            case BEACON_TX_HPLC_CSMA_SIMPLE_RF:
 | 
						|
            {
 | 
						|
 | 
						|
                /* don't do anything, just complete the entire cmd */
 | 
						|
                for (j = i; j < ts->non_cco_bc_info.bc_cnt; j++) {
 | 
						|
                    if (j > i && ts->non_cco_bc_info.sta[j].tei == self_tei) {
 | 
						|
                        iot_printf("%s warning, csma rf err tei:%lu, "
 | 
						|
                            "type:%lu, csma pos:%lu, cur pos:%lu\n",
 | 
						|
                            __FUNCTION__, ts->non_cco_bc_info.sta[j].tei,
 | 
						|
                            ts->non_cco_bc_info.sta[j].tx_flag, i, j);
 | 
						|
                    }
 | 
						|
                    start_offset += ts->bc_slot_dur;
 | 
						|
                    cmd->rf_end_t = start_offset;
 | 
						|
                }
 | 
						|
                new_cmd_required = 1;
 | 
						|
                break;
 | 
						|
            }
 | 
						|
            case BEACON_TX_HPLC_SIMPLE_RF_SYNC:
 | 
						|
            {
 | 
						|
                /* new cmd */
 | 
						|
                cnt++;
 | 
						|
                cmd++;
 | 
						|
 | 
						|
                cmd->rf_tx_q_en_bm = mac_rf_sched_get_wb_bc_q(rf_vdev);
 | 
						|
                start_offset += ts->bc_slot_dur;
 | 
						|
                cmd->rf_end_t = start_offset;
 | 
						|
                new_cmd_required = 1;
 | 
						|
 | 
						|
                /* check that the time slot is correct */
 | 
						|
                for (j = i + 1; j < ts->non_cco_bc_info.bc_cnt; j++) {
 | 
						|
                    if (new_cmd_required) {
 | 
						|
                        cnt++;
 | 
						|
                        cmd++;
 | 
						|
                        new_cmd_required = 0;
 | 
						|
                    }
 | 
						|
 | 
						|
                    start_offset += ts->bc_slot_dur;
 | 
						|
                    cmd->rf_end_t = start_offset;
 | 
						|
                }
 | 
						|
                new_cmd_required = 1;
 | 
						|
                break;
 | 
						|
            }
 | 
						|
            default:
 | 
						|
                sta_tx_type = BEACON_TX_ONLY_HPLC;
 | 
						|
                iot_printf("%s warning abnomal type:%lu\n",
 | 
						|
                    __FUNCTION__, tx_flag);
 | 
						|
                /* new cmd */
 | 
						|
                cnt++;
 | 
						|
                cmd++;
 | 
						|
 | 
						|
                start_offset += ts->bc_slot_dur *
 | 
						|
                    (ts->non_cco_bc_info.bc_cnt - i);
 | 
						|
                cmd->rf_end_t = start_offset;
 | 
						|
 | 
						|
                new_cmd_required = 1;
 | 
						|
                break;
 | 
						|
            }
 | 
						|
            /* break i loop */
 | 
						|
            break;
 | 
						|
        } else {
 | 
						|
            start_offset += ts->bc_slot_dur;
 | 
						|
            cmd->rf_end_t = start_offset;
 | 
						|
            new_cmd_required = 1;
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
bc_done:
 | 
						|
 | 
						|
    if (new_cmd_required) {
 | 
						|
        cnt++;
 | 
						|
        cmd++;
 | 
						|
        new_cmd_required = 0;
 | 
						|
    }
 | 
						|
 | 
						|
    /* prepare tdma slot
 | 
						|
     * TODO: current do not support tdma.
 | 
						|
     */
 | 
						|
    if (ts->tdma_slot_dur) {
 | 
						|
        start_offset += ts->tdma_slot_dur * ts->cco_bc_cnt;
 | 
						|
        start_offset += ts->tdma_slot_dur * ts->non_cco_bc_info.bc_cnt;
 | 
						|
        cmd->rf_end_t = start_offset;
 | 
						|
        new_cmd_required = 1;
 | 
						|
    }
 | 
						|
 | 
						|
    if (new_cmd_required) {
 | 
						|
        cnt++;
 | 
						|
        cmd++;
 | 
						|
        new_cmd_required = 0;
 | 
						|
    }
 | 
						|
 | 
						|
    /* prepare csma slot */
 | 
						|
    judge_ntb = start_offset;
 | 
						|
    for (i = 0; i < ts->csma_info.phase_cnt; i++) {
 | 
						|
        start_offset += ts->csma_info.slot_dur[i];
 | 
						|
    }
 | 
						|
    /* judge csma exist */
 | 
						|
    if (judge_ntb != start_offset) {
 | 
						|
        csma_is_exist = 1;
 | 
						|
        cmd->rf_tx_q_en_bm = mac_rf_sched_get_csma_q(rf_vdev);
 | 
						|
        cmd->rf_end_t = start_offset - MAC_RF_SCHED_CSMA_GAP_MS;
 | 
						|
        cnt++;
 | 
						|
        cmd++;
 | 
						|
        if (MAC_RF_SCHED_CSMA_GAP_MS) {
 | 
						|
            cmd->rf_end_t = start_offset;
 | 
						|
            cnt++;
 | 
						|
            cmd++;
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    /* prepare dedicated csma slot */
 | 
						|
    judge_ntb = start_offset;
 | 
						|
    for (i = 0; i < ts->d_csma_info.phase_cnt; i++) {
 | 
						|
        start_offset += ts->d_csma_info.slot_dur[i];
 | 
						|
    }
 | 
						|
 | 
						|
    /* judge dcsma exist */
 | 
						|
    if (judge_ntb != start_offset) {
 | 
						|
        csma_is_exist = 1;
 | 
						|
        cmd->rf_tx_q_en_bm = mac_rf_sched_get_dcsma_q(rf_vdev);
 | 
						|
        rf_vdev->bcsma_slot_exist = 1;
 | 
						|
        cmd->rf_end_t = start_offset - MAC_RF_SCHED_CSMA_GAP_MS;
 | 
						|
        cnt++;
 | 
						|
        cmd++;
 | 
						|
        if (MAC_RF_SCHED_CSMA_GAP_MS) {
 | 
						|
            cmd->rf_end_t = start_offset;
 | 
						|
            cnt++;
 | 
						|
            cmd++;
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    /* check cmd list */
 | 
						|
    if (start_offset != ts->bc_period) {
 | 
						|
        iot_printf("%s, cfg err, cfg ntb:%lu, bc pb:%lu\n",
 | 
						|
            __FUNCTION__, start_offset, ts->bc_period);
 | 
						|
       if (start_offset + MAC_RF_SCHED_CSMA_GAP_MS < ts->bc_period &&
 | 
						|
        csma_is_exist) {
 | 
						|
           start_offset = ts->bc_period;
 | 
						|
           if (MAC_RF_SCHED_CSMA_GAP_MS) {
 | 
						|
               cmd--;
 | 
						|
               cmd--;
 | 
						|
               cmd->rf_end_t = start_offset - MAC_RF_SCHED_CSMA_GAP_MS;
 | 
						|
               cmd++;
 | 
						|
               cmd->rf_end_t = start_offset;
 | 
						|
               cmd++;
 | 
						|
           } else {
 | 
						|
               cmd--;
 | 
						|
               cmd->rf_end_t = start_offset;
 | 
						|
               cmd++;
 | 
						|
           }
 | 
						|
       }
 | 
						|
    }
 | 
						|
    IOT_ASSERT(cnt <= HW_SCHED_CMD_MAX_CNT);
 | 
						|
 | 
						|
    cl->total_cnt = cnt;
 | 
						|
 | 
						|
    mac_rf_sched_offset_switch(cl, cnt);
 | 
						|
    if (need_early_stop) {
 | 
						|
        cl->cmd[cl->total_cnt - 1].rf_end_t -=
 | 
						|
            MAC_MS_TO_NTB(MAC_EARLY_STOP_CMDLIST_T_MS);
 | 
						|
    }
 | 
						|
 | 
						|
    mac_rf_sched_dump(cl, cnt);
 | 
						|
 | 
						|
    mac_rf_sched_load_cmd_list(rf_vdev, cl);
 | 
						|
    mac_rf_sched_enable_bp(rf_vdev, 1);
 | 
						|
 | 
						|
    return sta_tx_type;
 | 
						|
}
 | 
						|
 | 
						|
void mac_rf_sched_sta_bc_alert(mac_rf_vdev_t *rf_vdev, mac_bc_time_slot_t *ts,
 | 
						|
    uint64_t start_ntb, uint8_t ts_reuse, uint32_t tx_resus)
 | 
						|
{
 | 
						|
    mac_rf_pdev_t *rf_pdev;
 | 
						|
 | 
						|
    if (ts_reuse && tx_resus) {
 | 
						|
        /* flush tdma hwq */
 | 
						|
        rf_pdev = get_rf_pdev_ptr(PLC_PDEV_ID, rf_vdev->ref_pdev_id);
 | 
						|
        mac_rf_tx_flush_all_tdma_queue(&rf_pdev->hwq_hdl);
 | 
						|
        /* rf schedule support */
 | 
						|
        mac_rf_sched_sta_set(rf_vdev, ts, iot_uint64_lower32(start_ntb), 0);
 | 
						|
    } else {
 | 
						|
        /* rf schedule support */
 | 
						|
        mac_rf_sched_set_csma_only(rf_vdev, start_ntb, (uint8_t)tx_resus);
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
void mac_rf_sched_stop(mac_rf_vdev_t *rf_vdev)
 | 
						|
{
 | 
						|
    mac_rf_sched_ctx_t *ctx = rf_vdev->rf_sched_ctx;
 | 
						|
 | 
						|
    /* stop scheduler */
 | 
						|
    mac_rf_sched_enable_bp(rf_vdev, 0);
 | 
						|
    /* clean up command list */
 | 
						|
    mac_rf_sched_free_cmd_list(rf_vdev);
 | 
						|
    ctx->curr_hw_cmd_list = NULL;
 | 
						|
}
 | 
						|
 | 
						|
/* set scheduler to work in csma only mode */
 | 
						|
static void mac_rf_sched_set_csma_only_intern(mac_rf_vdev_t *rf_vdev,
 | 
						|
    mac_bc_cmsa_si_t *csma, uint64_t start_ntb, uint8_t enable_tx)
 | 
						|
{
 | 
						|
    uint16_t start_offset, cnt;
 | 
						|
    hw_sched_cmd_list_t *cl = NULL;
 | 
						|
    mac_rf_sched_ctx_t *ctx = rf_vdev->rf_sched_ctx;
 | 
						|
    hw_sched_cmd_t *cmd;
 | 
						|
    /* clear flag every time  */
 | 
						|
    rf_vdev->bcsma_slot_exist = 0;
 | 
						|
 | 
						|
    cl = mac_rf_sched_alloc_cmd_list(rf_vdev);
 | 
						|
    ctx->curr_hw_cmd_list = cl;
 | 
						|
    IOT_ASSERT(cl);
 | 
						|
    cl->start_ntb = iot_uint64_lower32(start_ntb);
 | 
						|
    cl->start_ntb_h = iot_uint64_higher32(start_ntb);
 | 
						|
    cmd = cl->cmd;
 | 
						|
    cnt = 0;
 | 
						|
    start_offset = 0;
 | 
						|
 | 
						|
    //TODO: dbg for hw sched
 | 
						|
    cl->alloc_ntb = mac_rf_sched_get_ntb(rf_vdev);
 | 
						|
    cl->caller = 3;
 | 
						|
 | 
						|
    if (enable_tx) {
 | 
						|
        cmd->rf_tx_q_en_bm = mac_rf_sched_get_csma_q(rf_vdev);
 | 
						|
    }
 | 
						|
#if PLC_SUPPORT_DBG_PKT_MODE
 | 
						|
    /* if and only if it's STA/PCO dev, and not blocking dbg pkt sch
 | 
						|
     * in rx only period
 | 
						|
     */
 | 
						|
    else {
 | 
						|
        cmd->rf_tx_q_en_bm = mac_rf_sched_get_dbg_q(rf_vdev);
 | 
						|
    }
 | 
						|
#endif
 | 
						|
    start_offset += (uint16_t)csma->slot_dur[0];
 | 
						|
    cmd->rf_end_t = start_offset;
 | 
						|
    cnt++;
 | 
						|
 | 
						|
    mac_rf_sched_dump(cl, cnt);
 | 
						|
 | 
						|
    /* for csma only mode, make sure cmd list is short enough */
 | 
						|
    IOT_ASSERT(cnt < HW_SHCED_CMD_DEPTH);
 | 
						|
    cl->total_cnt = cnt;
 | 
						|
 | 
						|
    mac_rf_sched_offset_switch(cl, cnt);
 | 
						|
    /* load command list of next beacon period */
 | 
						|
    mac_rf_sched_load_cmd_list(rf_vdev, cl);
 | 
						|
    /* start HW scheduler */
 | 
						|
    mac_rf_sched_enable_bp(rf_vdev, 1);
 | 
						|
}
 | 
						|
 | 
						|
void mac_rf_sched_set_csma_only(mac_rf_vdev_t *rf_vdev, uint64_t start_ntb,
 | 
						|
    uint8_t enable_tx)
 | 
						|
{
 | 
						|
    mac_bc_cmsa_si_t csma;
 | 
						|
 | 
						|
    /* config HW scheduler to RX only mode */
 | 
						|
    /* for one phase cco device and sta device */
 | 
						|
    csma.phase_cnt = 1;
 | 
						|
    csma.slot_dur[0] = MAC_CSMA_ONLY_PEIROD_MS;
 | 
						|
    mac_rf_sched_set_csma_only_intern(rf_vdev, &csma, start_ntb, enable_tx);
 | 
						|
}
 | 
						|
 | 
						|
void mac_rf_sched_init(mac_rf_vdev_t *rf_vdev)
 | 
						|
{
 | 
						|
    rf_vdev->rf_sched_ctx = os_mem_malloc(PLC_MAC_SCHED_MID,
 | 
						|
        sizeof(mac_rf_sched_ctx_t));
 | 
						|
    IOT_ASSERT(rf_vdev->rf_sched_ctx);
 | 
						|
}
 | 
						|
 | 
						|
#endif /* HPLC_RF_DEV_SUPPORT */
 | 
						|
 |