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 */
 | |
| 
 |