544 lines
		
	
	
		
			16 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
		
		
			
		
	
	
			544 lines
		
	
	
		
			16 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| 
								 | 
							
								/****************************************************************************
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								Copyright(c) 2019 by Aerospace C.Power (Chongqing) Microelectronics. ALL RIGHTS RESERVED.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								This Information is proprietary to Aerospace C.Power (Chongqing) Microelectronics and MAY NOT
							 | 
						||
| 
								 | 
							
								be copied by any method or incorporated into another program without
							 | 
						||
| 
								 | 
							
								the express written consent of Aerospace C.Power. This Information or any portion
							 | 
						||
| 
								 | 
							
								thereof remains the property of Aerospace C.Power. The Information contained herein
							 | 
						||
| 
								 | 
							
								is believed to be accurate and Aerospace C.Power assumes no responsibility or
							 | 
						||
| 
								 | 
							
								liability for its use in any way and conveys no license or title under
							 | 
						||
| 
								 | 
							
								any patent or copyright and makes no representation or warranty that this
							 | 
						||
| 
								 | 
							
								Information is free from patent or copyright infringement.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								****************************************************************************/
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#include "sw_sched.h"
							 | 
						||
| 
								 | 
							
								#include "iot_errno.h"
							 | 
						||
| 
								 | 
							
								#include "mac_msg.h"
							 | 
						||
| 
								 | 
							
								#include "mac.h"
							 | 
						||
| 
								 | 
							
								#include "mac_hwq_mgr.h"
							 | 
						||
| 
								 | 
							
								#include "mac_stream.h"
							 | 
						||
| 
								 | 
							
								#include "mac_pdev.h"
							 | 
						||
| 
								 | 
							
								#include "mac_desc_engine.h"
							 | 
						||
| 
								 | 
							
								#include "hw_tonemap.h"
							 | 
						||
| 
								 | 
							
								#include "rate_control.h"
							 | 
						||
| 
								 | 
							
								#include "mac_tx_hw.h"
							 | 
						||
| 
								 | 
							
								#include "mac_msdu.h"
							 | 
						||
| 
								 | 
							
								#include "iot_bitops.h"
							 | 
						||
| 
								 | 
							
								#include "phy_chn.h"
							 | 
						||
| 
								 | 
							
								#include "iot_io.h"
							 | 
						||
| 
								 | 
							
								#include "mac_peer.h"
							 | 
						||
| 
								 | 
							
								#include "mac_tx_power.h"
							 | 
						||
| 
								 | 
							
								#include "mac_rf.h"
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								mac_swq_t * g_mac_swq[MAX_MAC_QUE_NUM]={0};
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#if HPLC_RF_DEV_SUPPORT
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#include "mac_rf_common_hw.h"
							 | 
						||
| 
								 | 
							
								#include "rf_hw_tonemap.h"
							 | 
						||
| 
								 | 
							
								#include "rf_rate_control.h"
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								mac_swq_t * g_mac_rf_swq[MAX_MAC_RF_QUE_NUM] = {0};
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								uint32_t mac_rf_swsch_init()
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								    uint32_t type;
							 | 
						||
| 
								 | 
							
								    iot_printf("%s\n", __FUNCTION__);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    for (type = 0; type < MAX_MAC_RF_QUE_NUM; type++) {
							 | 
						||
| 
								 | 
							
								        g_mac_rf_swq[type] = os_mem_malloc(PLC_MAC_SHC_MID,
							 | 
						||
| 
								 | 
							
								            sizeof(mac_swq_t));
							 | 
						||
| 
								 | 
							
								        IOT_ASSERT(g_mac_rf_swq[type]);
							 | 
						||
| 
								 | 
							
								        g_mac_rf_swq[type]->q_depth = 0;
							 | 
						||
| 
								 | 
							
								        iot_list_init(&g_mac_rf_swq[type]->stream_list);
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								    return 0;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								uint32_t mac_rf_swsch_trigger_tx(pdevid_t rf_pdev_id, vdevid_t rf_vdev_id)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								    uint32_t ret = ERR_OK;
							 | 
						||
| 
								 | 
							
								    mac_rf_vdev_t *rf_vdev = get_rf_vdev_ptr(PLC_PDEV_ID, rf_pdev_id,
							 | 
						||
| 
								 | 
							
								        rf_vdev_id);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    IOT_ASSERT(rf_vdev);
							 | 
						||
| 
								 | 
							
								    if (rf_vdev->stop_flag == 0) {
							 | 
						||
| 
								 | 
							
								        //iot_printf("%s\n", __FUNCTION__);
							 | 
						||
| 
								 | 
							
								        mac_msg_t *msg = mac_alloc_msg();
							 | 
						||
| 
								 | 
							
								        if (msg == NULL) {
							 | 
						||
| 
								 | 
							
								            IOT_ASSERT(0);
							 | 
						||
| 
								 | 
							
								            ret = ERR_NOMEM;
							 | 
						||
| 
								 | 
							
								            goto out;
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								        msg->type = MAC_MSG_TYPE_SCH;
							 | 
						||
| 
								 | 
							
								        msg->id = MAC_MSG_ID_SCH_TX;
							 | 
						||
| 
								 | 
							
								        msg->data1 = (((uint32_t)rf_pdev_id) << 8) | rf_vdev_id;
							 | 
						||
| 
								 | 
							
								        msg->data2 = NULL;
							 | 
						||
| 
								 | 
							
								        msg->data3 = NULL;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        mac_queue_msg(msg, MAC_MSG_QUEUE_HP);
							 | 
						||
| 
								 | 
							
								    } else {
							 | 
						||
| 
								 | 
							
								        ret = ERR_FAIL;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								out:
							 | 
						||
| 
								 | 
							
								    return ret;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								uint32_t mac_rf_swsch_tx_msdu(mac_rf_pdev_t *rf_pdev, mac_msdu_t *msdu,
							 | 
						||
| 
								 | 
							
								    uint32_t delimiter_type, tei_t dtei, lid_t lid, uint8_t is_bcast)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								    uint8_t blkz = 0;
							 | 
						||
| 
								 | 
							
								    uint32_t pbsz = 0;
							 | 
						||
| 
								 | 
							
								    uint8_t phr_mcs = 0;
							 | 
						||
| 
								 | 
							
								    uint8_t mcs = 0;
							 | 
						||
| 
								 | 
							
								    nid_t nid = 0;
							 | 
						||
| 
								 | 
							
								    mac_vdev_t *vdev = NULL;
							 | 
						||
| 
								 | 
							
								    uint32_t option = mac_rf_get_self_option();
							 | 
						||
| 
								 | 
							
								    /* get msdu len && all pb num */
							 | 
						||
| 
								 | 
							
								    uint32_t msdu_len = iot_pkt_data_len(msdu->buf);
							 | 
						||
| 
								 | 
							
								    /* get block size, pb size, phy header mcs , plc mcs */
							 | 
						||
| 
								 | 
							
								    mac_rf_data_get_rate(msdu_len, option, is_bcast, &blkz, &phr_mcs, &mcs,
							 | 
						||
| 
								 | 
							
								        msdu->retry_cnt, dtei);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    pbsz = phy_rf_get_pbsz(blkz);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    if (msdu->is_dbg_pkt) {
							 | 
						||
| 
								 | 
							
								        mac_pdev_t *pdev = get_pdev_ptr(rf_pdev->parent_pdev_id);
							 | 
						||
| 
								 | 
							
								        vdev = get_vdev_ptr(rf_pdev->parent_pdev_id, pdev->dbg_pkt_vdev_id);
							 | 
						||
| 
								 | 
							
								    } else {
							 | 
						||
| 
								 | 
							
								        vdev = get_vdev_ptr(rf_pdev->parent_pdev_id, PLC_DEFAULT_VDEV);
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    tei_t stei = vdev_get_tei(vdev);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    /* get nid */
							 | 
						||
| 
								 | 
							
								    vdev_get_nid(vdev, &nid);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    return mac_tx_rf_msdu(rf_pdev, msdu, option, delimiter_type, dtei,
							 | 
						||
| 
								 | 
							
								        lid, is_bcast, nid, stei, blkz, pbsz, phr_mcs, mcs, msdu_len);
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#endif /* HPLC_RF_DEV_SUPPORT */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								mac_swq_t * mac_swsch_get_g_swq(uint32_t swq_id, uint32_t is_rf)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								    mac_swq_t *swq = NULL;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#if HPLC_RF_DEV_SUPPORT
							 | 
						||
| 
								 | 
							
								    swq = ((is_rf) ? g_mac_rf_swq[(swq_id)] : g_mac_swq[(swq_id)]);
							 | 
						||
| 
								 | 
							
								#else /* HPLC_RF_DEV_SUPPORT */
							 | 
						||
| 
								 | 
							
								    swq = ((is_rf) ? NULL : g_mac_swq[(swq_id)]);
							 | 
						||
| 
								 | 
							
								#endif /* HPLC_RF_DEV_SUPPORT */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    return swq;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								uint32_t mac_swsch_init()
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								    uint32_t type;
							 | 
						||
| 
								 | 
							
								    iot_printf("%s\n", __FUNCTION__);
							 | 
						||
| 
								 | 
							
								#if 1
							 | 
						||
| 
								 | 
							
								    for(type = 0; type < MAX_MAC_QUE_NUM; type++)
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								        g_mac_swq[type] = os_mem_malloc(PLC_MAC_SHC_MID,sizeof(mac_swq_t));
							 | 
						||
| 
								 | 
							
								        IOT_ASSERT(g_mac_swq[type]);
							 | 
						||
| 
								 | 
							
								        g_mac_swq[type]->q_depth = 0;
							 | 
						||
| 
								 | 
							
								        iot_list_init(&g_mac_swq[type]->stream_list);
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								#endif
							 | 
						||
| 
								 | 
							
								    return 0;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								uint32_t mac_swsch_trigger_tx(pdevid_t pdev_id, vdevid_t vdev_id)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								    /* send a MAC_MSG_TYPE_SCH : MAC_MSG_ID_SCH_TX*/
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    uint32_t ret = 0;
							 | 
						||
| 
								 | 
							
								    mac_vdev_t * vdev = g_mac_pdev[pdev_id]->vdev[vdev_id];
							 | 
						||
| 
								 | 
							
								    if(vdev->stop_flag == 0){
							 | 
						||
| 
								 | 
							
								        //iot_printf("%s\n", __FUNCTION__);
							 | 
						||
| 
								 | 
							
								        mac_msg_t *msg = mac_alloc_msg();
							 | 
						||
| 
								 | 
							
								        if (msg == NULL) {
							 | 
						||
| 
								 | 
							
								            IOT_ASSERT(0);
							 | 
						||
| 
								 | 
							
								            ret = ERR_NOMEM;
							 | 
						||
| 
								 | 
							
								            goto out;
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								        msg->type = MAC_MSG_TYPE_SCH;
							 | 
						||
| 
								 | 
							
								        msg->id = MAC_MSG_ID_SCH_TX;
							 | 
						||
| 
								 | 
							
								        msg->data1 = (((uint32_t)pdev_id) << 8) | vdev_id;
							 | 
						||
| 
								 | 
							
								        msg->data2 = NULL;
							 | 
						||
| 
								 | 
							
								        msg->data3 = NULL;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        mac_queue_msg(msg, MAC_MSG_QUEUE_HP);
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								out:
							 | 
						||
| 
								 | 
							
								    return ret;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								uint32_t mac_swsch_append(mac_swq_t *swq, phase_t phase, mac_stream_t *node)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								    /* TODO: */
							 | 
						||
| 
								 | 
							
								    IOT_ASSERT(swq && node);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    if (iot_list_empty(&swq->stream_list))
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								        /* if empty */
							 | 
						||
| 
								 | 
							
								        IOT_ASSERT(0 == swq->q_depth);
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								    if (node->in_swq == 0) {
							 | 
						||
| 
								 | 
							
								        /* add prev head, i.e. put to the last */
							 | 
						||
| 
								 | 
							
								        iot_list_add_prev(&node->msdu.tx.swq_node, &swq->stream_list);
							 | 
						||
| 
								 | 
							
								        swq->q_depth++;
							 | 
						||
| 
								 | 
							
								        node->phase_in_swq = phase;
							 | 
						||
| 
								 | 
							
								        node->in_swq = 1;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    return 0;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								uint32_t mac_swsch_remove(mac_swq_t *swq, mac_stream_t *node)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								    /* TODO: */
							 | 
						||
| 
								 | 
							
								    IOT_ASSERT(swq && node);
							 | 
						||
| 
								 | 
							
								    if (!iot_list_empty(&swq->stream_list))
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								        /* if not empty */
							 | 
						||
| 
								 | 
							
								        IOT_ASSERT(swq->q_depth > 0 && node->in_swq == 1);
							 | 
						||
| 
								 | 
							
								        iot_list_del(&node->msdu.tx.swq_node);
							 | 
						||
| 
								 | 
							
								        swq->q_depth--;
							 | 
						||
| 
								 | 
							
								        node->in_swq = 0;
							 | 
						||
| 
								 | 
							
								        node->phase_in_swq = PLC_PHASE_ALL;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								    else {
							 | 
						||
| 
								 | 
							
								        /* already empty */
							 | 
						||
| 
								 | 
							
								        IOT_ASSERT(0);
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								    return 0;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								uint32_t mac_swsch_del_stream(void *stream)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								    mac_stream_t *str = (mac_stream_t *)stream;
							 | 
						||
| 
								 | 
							
								    mac_swq_t *swq_ptr = NULL;
							 | 
						||
| 
								 | 
							
								    uint32_t swq_id;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    if(str->in_swq == 1) {
							 | 
						||
| 
								 | 
							
								        str->in_swq = 0;
							 | 
						||
| 
								 | 
							
								        uint32_t bcn_region_type = mac_get_bcn_region_type(str->lid);
							 | 
						||
| 
								 | 
							
								        if (str->is_rf) {
							 | 
						||
| 
								 | 
							
								            swq_id = (uint32_t)mac_rf_q_get_swq_type(bcn_region_type,
							 | 
						||
| 
								 | 
							
								                str->lid, (str->is_tx == IS_DBG_TX_STREAM));
							 | 
						||
| 
								 | 
							
								        } else {
							 | 
						||
| 
								 | 
							
								            swq_id = (uint32_t)mac_q_get_swq_type(bcn_region_type,
							 | 
						||
| 
								 | 
							
								                str->phase_in_swq, str->lid);
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								        swq_ptr = mac_swsch_get_g_swq(swq_id, str->is_rf);
							 | 
						||
| 
								 | 
							
								        IOT_ASSERT(swq_ptr);
							 | 
						||
| 
								 | 
							
								        if (swq_ptr->q_depth > 0) {
							 | 
						||
| 
								 | 
							
								            //TODO: focus on the reason
							 | 
						||
| 
								 | 
							
								            swq_ptr->q_depth--;
							 | 
						||
| 
								 | 
							
								            iot_list_del(&str->msdu.tx.swq_node);
							 | 
						||
| 
								 | 
							
								            str->in_swq = 0;
							 | 
						||
| 
								 | 
							
								            str->phase_in_swq = PLC_PHASE_ALL;
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								    return 0;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								uint32_t mac_swsch_tx_msdu(pdevid_t pdev_id, vdevid_t vdev_id,
							 | 
						||
| 
								 | 
							
								    mac_msdu_t *msdu,uint32_t delimiter_type,
							 | 
						||
| 
								 | 
							
								    uint32_t proto,uint32_t port)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								    mac_pdev_t *pdev;
							 | 
						||
| 
								 | 
							
								    mac_vdev_t *vdev;
							 | 
						||
| 
								 | 
							
								    uint32_t ret;
							 | 
						||
| 
								 | 
							
								    uint32_t pb_num_per_mpdu;
							 | 
						||
| 
								 | 
							
								    uint32_t mpdu_num_to_send;
							 | 
						||
| 
								 | 
							
								    uint32_t tmi, ext_tmi;
							 | 
						||
| 
								 | 
							
								    uint8_t rid;
							 | 
						||
| 
								 | 
							
								    uint32_t rate_mode;
							 | 
						||
| 
								 | 
							
								    uint32_t pb_sz, old_pb_sz;
							 | 
						||
| 
								 | 
							
								    uint32_t nid;
							 | 
						||
| 
								 | 
							
								    tei_t stei;
							 | 
						||
| 
								 | 
							
								    mac_stream_t *stream = msdu->ref_mac_stream;
							 | 
						||
| 
								 | 
							
								    mac_peer_t *peer = stream->peer;
							 | 
						||
| 
								 | 
							
								    tei_t dtei = (tei_t)peer->tei;
							 | 
						||
| 
								 | 
							
								    uint32_t lid = stream->lid;
							 | 
						||
| 
								 | 
							
								    uint32_t single_proto_band;
							 | 
						||
| 
								 | 
							
								    uint8_t is_fixed_rate;
							 | 
						||
| 
								 | 
							
								    uint32_t is_fixed_pbsz;
							 | 
						||
| 
								 | 
							
								    uint32_t hw_band_id;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    pdev = get_pdev_ptr(pdev_id);
							 | 
						||
| 
								 | 
							
								    if (msdu->is_dbg_pkt) {
							 | 
						||
| 
								 | 
							
								        vdev = get_vdev_ptr(pdev_id, pdev->dbg_pkt_vdev_id);
							 | 
						||
| 
								 | 
							
								    } else {
							 | 
						||
| 
								 | 
							
								        vdev = get_vdev_ptr(pdev_id, vdev_id);
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    stei = vdev_get_tei(vdev);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    IOT_ASSERT(stream->msdu.tx.cur_tx_msdu);
							 | 
						||
| 
								 | 
							
								    uint8_t is_bcast =\
							 | 
						||
| 
								 | 
							
								        (uint8_t)stream->msdu.tx.cur_tx_msdu->is_bcast;
							 | 
						||
| 
								 | 
							
								    phase_t phase =\
							 | 
						||
| 
								 | 
							
								        (uint8_t)stream->msdu.tx.cur_tx_msdu->phase;
							 | 
						||
| 
								 | 
							
								    uint32_t pkt_len = iot_pkt_data_len(msdu->buf);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    /* get nid */
							 | 
						||
| 
								 | 
							
								    ret = vdev_get_nid(vdev, &nid);
							 | 
						||
| 
								 | 
							
								    //TODO: need fix swsch trigger logic, need check vdev.
							 | 
						||
| 
								 | 
							
								    //IOT_ASSERT(ERR_OK == ret);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    hw_band_id = mac_tx_hw_band_id_get(vdev,
							 | 
						||
| 
								 | 
							
								        phy_band_id_get(), msdu->retry_cnt);
							 | 
						||
| 
								 | 
							
								    single_proto_band = phy_hw_band_to_proto_band(hw_band_id);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    /* get the rate for this mpdu */
							 | 
						||
| 
								 | 
							
								    if (!is_bcast) {
							 | 
						||
| 
								 | 
							
								        /* if uni-cast */
							 | 
						||
| 
								 | 
							
								        if (!vdev_get_fixed_rate(vdev)) {
							 | 
						||
| 
								 | 
							
								            is_fixed_rate = false;
							 | 
						||
| 
								 | 
							
								        } else {
							 | 
						||
| 
								 | 
							
								            is_fixed_rate = true;
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								        if (msdu->fix_rate) {
							 | 
						||
| 
								 | 
							
								            is_fixed_rate = true;
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								#if (PLC_SUPPORT_STA_TX_3_PHASE)
							 | 
						||
| 
								 | 
							
								        if (dtei == PLC_TEI_CCO) {
							 | 
						||
| 
								 | 
							
								            is_fixed_rate = true;
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								#endif
							 | 
						||
| 
								 | 
							
								        /* only first send, allow choose the pbsz */
							 | 
						||
| 
								 | 
							
								        is_fixed_pbsz = (msdu->retry)?1:0;
							 | 
						||
| 
								 | 
							
								        ret = mac_data_get_rate(vdev, peer, proto, is_fixed_rate, pkt_len,\
							 | 
						||
| 
								 | 
							
								            single_proto_band, is_fixed_pbsz, &rid, &pb_num_per_mpdu, \
							 | 
						||
| 
								 | 
							
								            &mpdu_num_to_send, &rate_mode, (uint8_t)msdu->retry_cnt);
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								    else
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								        ret = mac_data_get_bcast_rate(vdev, proto, true, pkt_len,
							 | 
						||
| 
								 | 
							
								            single_proto_band, msdu->retry_cnt, &rid, &rate_mode,
							 | 
						||
| 
								 | 
							
								            &mpdu_num_to_send, &pb_num_per_mpdu, msdu->is_dbg_pkt,
							 | 
						||
| 
								 | 
							
								            msdu->retry, msdu->rd_retry_cnt);
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								    IOT_ASSERT(ret == 0);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    /* get pbsz, tmi and ext emi if not GP */
							 | 
						||
| 
								 | 
							
								    phy_get_tmi_by_rid(proto, rid, &tmi, &ext_tmi);
							 | 
						||
| 
								 | 
							
								    phy_get_rt_pbsz(proto, rid, &pb_sz);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								 #if SUPPORT_SOUTHERN_POWER_GRID
							 | 
						||
| 
								 | 
							
								    if (PLC_PROTO_TYPE_SPG == proto) {
							 | 
						||
| 
								 | 
							
								        /* for spg, one mpdu should accommodate the msdu */
							 | 
						||
| 
								 | 
							
								        IOT_ASSERT((mac_get_sof_pb_valid_payload_sz(proto, pb_sz) \
							 | 
						||
| 
								 | 
							
								            * pb_num_per_mpdu * mpdu_num_to_send) >= pkt_len);
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								#endif
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#if DBG_MAC_TX_RID
							 | 
						||
| 
								 | 
							
								    iot_printf("tx msdu 0x%x's r%d->r%d, bmp=0x%x\n",
							 | 
						||
| 
								 | 
							
								            msdu, msdu->rate_idx, rid, msdu->send_bitmap);
							 | 
						||
| 
								 | 
							
								#endif
							 | 
						||
| 
								 | 
							
								    if (msdu->send_bitmap == 0xffffffff || msdu->rate_idx == MAX_RATE_IDX) {
							 | 
						||
| 
								 | 
							
								        /* first send */
							 | 
						||
| 
								 | 
							
								        msdu->rate_idx = rid;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								    else
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								        if (msdu->rate_idx != rid) {
							 | 
						||
| 
								 | 
							
								            /* if selected tmi is not the same to
							 | 
						||
| 
								 | 
							
								             * the previous one, restart the send
							 | 
						||
| 
								 | 
							
								             */
							 | 
						||
| 
								 | 
							
								            phy_get_rt_pbsz(proto, (uint8_t)msdu->rate_idx, &old_pb_sz);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								            if (pb_sz != old_pb_sz) {
							 | 
						||
| 
								 | 
							
								                msdu->retry = 0;
							 | 
						||
| 
								 | 
							
								                msdu->send_bitmap = 0xffffffff;
							 | 
						||
| 
								 | 
							
								                msdu->last_pos = 0;
							 | 
						||
| 
								 | 
							
								                iot_printf("change msdu 0x%x's pbsz %d->%d\n",
							 | 
						||
| 
								 | 
							
								                        msdu, old_pb_sz, pb_sz);
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								            msdu->rate_idx = rid;
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    if (!is_bcast && msdu->retry == 0) {
							 | 
						||
| 
								 | 
							
								        /* only one mpdu for the first send of ucast */
							 | 
						||
| 
								 | 
							
								        mpdu_num_to_send = 1;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    return mac_tx_msdu(pdev, msdu, \
							 | 
						||
| 
								 | 
							
								        pb_sz, pb_num_per_mpdu, \
							 | 
						||
| 
								 | 
							
								        mpdu_num_to_send, \
							 | 
						||
| 
								 | 
							
								        delimiter_type, nid, \
							 | 
						||
| 
								 | 
							
								        stei, dtei, lid, is_bcast, \
							 | 
						||
| 
								 | 
							
								        phase, proto, port, \
							 | 
						||
| 
								 | 
							
								        tmi, ext_tmi, rate_mode, single_proto_band);
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								//load mac_frame_list to cur_msdu
							 | 
						||
| 
								 | 
							
								uint32_t mac_load_msdu(mac_msdu_t * cur_msdu,
							 | 
						||
| 
								 | 
							
								    mac_stream_t *stream)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								    IOT_ASSERT(cur_msdu && stream);
							 | 
						||
| 
								 | 
							
								    mac_msdu_frame_t *msdu_list = \
							 | 
						||
| 
								 | 
							
								        stream->msdu.tx.mac_frame_list;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    if (msdu_list && msdu_list->buf) {
							 | 
						||
| 
								 | 
							
								        /* if has frame in the queue */
							 | 
						||
| 
								 | 
							
								        mac_msdu_init(cur_msdu, 1, stream, \
							 | 
						||
| 
								 | 
							
								            msdu_list->buf, (uint8_t)msdu_list->retry_cnt);
							 | 
						||
| 
								 | 
							
								        cur_msdu->is_bcast = \
							 | 
						||
| 
								 | 
							
								            msdu_list->is_bcast;
							 | 
						||
| 
								 | 
							
								        cur_msdu->phase = \
							 | 
						||
| 
								 | 
							
								            msdu_list->phase;
							 | 
						||
| 
								 | 
							
								        cur_msdu->tx_3phase = msdu_list->tx_3phase;
							 | 
						||
| 
								 | 
							
								        cur_msdu->is_dbg_pkt = msdu_list->is_dbg_pkt;
							 | 
						||
| 
								 | 
							
								        cur_msdu->fix_rate = msdu_list->fix_rate;
							 | 
						||
| 
								 | 
							
								        cur_msdu->ppm_step = msdu_list->ppm_step;
							 | 
						||
| 
								 | 
							
								        cur_msdu->ppm_step_type = (uint8_t)msdu_list->ppm_step_type;
							 | 
						||
| 
								 | 
							
								        cur_msdu->need_encrypt = (uint8_t)msdu_list->need_encrypt;
							 | 
						||
| 
								 | 
							
								        cur_msdu->key_idx = msdu_list->key_idx;
							 | 
						||
| 
								 | 
							
								        /* remove the loaded mac_frame_t */
							 | 
						||
| 
								 | 
							
								        if (msdu_list->next == NULL) {
							 | 
						||
| 
								 | 
							
								            stream->msdu.tx.last_mac_frame = NULL;
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								        stream->msdu.tx.mac_frame_list = msdu_list->next;
							 | 
						||
| 
								 | 
							
								        IOT_ASSERT(stream->msdu.tx.mac_frame_num > 0);
							 | 
						||
| 
								 | 
							
								        stream->msdu.tx.mac_frame_num--;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        /* increase token number */
							 | 
						||
| 
								 | 
							
								        uint32_t bcn_region_type;
							 | 
						||
| 
								 | 
							
								        bcn_region_type = \
							 | 
						||
| 
								 | 
							
								            mac_get_bcn_region_type(stream->lid);
							 | 
						||
| 
								 | 
							
								        mac_token_free(bcn_region_type, stream->lid, stream->is_rf);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        mac_desc_free(&g_mac_desc_eng, \
							 | 
						||
| 
								 | 
							
								            PLC_MAC_MSDU_FRAME_POOL, \
							 | 
						||
| 
								 | 
							
								            msdu_list);
							 | 
						||
| 
								 | 
							
								        return ERR_OK;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								    /* empty queue */
							 | 
						||
| 
								 | 
							
								    return ERR_FAIL;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								static uint32_t mac_swsch_post_msdu_internal(uint32_t is_rf)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								    mac_stream_t *stream = NULL;
							 | 
						||
| 
								 | 
							
								    uint32_t ret = 0;
							 | 
						||
| 
								 | 
							
								    uint32_t swq_id;
							 | 
						||
| 
								 | 
							
								    uint32_t proto = PHY_PROTO_TYPE_GET();
							 | 
						||
| 
								 | 
							
								    uint32_t max_mac_queue_num = 0;
							 | 
						||
| 
								 | 
							
								    mac_swq_t *p_mac_swq = NULL;
							 | 
						||
| 
								 | 
							
								    pdevid_t pdev_id = PLC_PDEV_ID;
							 | 
						||
| 
								 | 
							
								    vdevid_t vdev_id = PLC_DEFAULT_VDEV;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    mac_rf_pdev_t *rf_pdev = get_rf_pdev_ptr(pdev_id, RF_PDEV_ID);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    max_mac_queue_num = is_rf ? MAX_MAC_RF_QUE_NUM : MAX_MAC_QUE_NUM;
							 | 
						||
| 
								 | 
							
								    for (swq_id = 0; swq_id < max_mac_queue_num; swq_id++)  //go through all swq
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								nextstream:
							 | 
						||
| 
								 | 
							
								        p_mac_swq = mac_swsch_get_g_swq(swq_id, is_rf);
							 | 
						||
| 
								 | 
							
								        if (p_mac_swq->q_depth > 0)  //swq have stream pending
							 | 
						||
| 
								 | 
							
								        {
							 | 
						||
| 
								 | 
							
								            iot_list_head_t * curr_swq_head = \
							 | 
						||
| 
								 | 
							
								                &p_mac_swq->stream_list;
							 | 
						||
| 
								 | 
							
								            /* should not empty */
							 | 
						||
| 
								 | 
							
								            IOT_ASSERT_DUMP(!iot_list_empty(curr_swq_head), \
							 | 
						||
| 
								 | 
							
								                &p_mac_swq->q_depth, 1);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								            /* get stream through list_head, get one node just after
							 | 
						||
| 
								 | 
							
								             * the head node
							 | 
						||
| 
								 | 
							
								             */
							 | 
						||
| 
								 | 
							
								            stream = iot_list_entry(curr_swq_head->next, \
							 | 
						||
| 
								 | 
							
								                mac_stream_t, msdu.tx.swq_node);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								            if (NULL == stream->msdu.tx.cur_tx_msdu) {
							 | 
						||
| 
								 | 
							
								                /* not sending msdu before, alloc the msdu */
							 | 
						||
| 
								 | 
							
								                ret = \
							 | 
						||
| 
								 | 
							
								                    mac_desc_get(&g_mac_desc_eng, PLC_MAC_MSDU_POOL, \
							 | 
						||
| 
								 | 
							
								                        (void**)&stream->msdu.tx.cur_tx_msdu);
							 | 
						||
| 
								 | 
							
								                IOT_ASSERT(ret == 0);
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								            mac_msdu_t *msdu = stream->msdu.tx.cur_tx_msdu;
							 | 
						||
| 
								 | 
							
								            if (msdu->buf)
							 | 
						||
| 
								 | 
							
								            {
							 | 
						||
| 
								 | 
							
								                if (!msdu->in_hwq) {
							 | 
						||
| 
								 | 
							
								                    /* if not in hwq, retry the msdu */
							 | 
						||
| 
								 | 
							
								                    if (!is_rf) {
							 | 
						||
| 
								 | 
							
								                        ret = mac_swsch_tx_msdu(pdev_id, vdev_id, \
							 | 
						||
| 
								 | 
							
								                            msdu, FC_DELIM_SOF, \
							 | 
						||
| 
								 | 
							
								                            proto, \
							 | 
						||
| 
								 | 
							
								                            HW_DESC_TX_PORT_PLC);
							 | 
						||
| 
								 | 
							
								                    } else {
							 | 
						||
| 
								 | 
							
								                        ret = mac_rf_swsch_tx_msdu(rf_pdev, msdu, FC_DELIM_SOF,
							 | 
						||
| 
								 | 
							
								                            stream->peer->tei, stream->lid,
							 | 
						||
| 
								 | 
							
								                            (uint8_t)msdu->is_bcast);
							 | 
						||
| 
								 | 
							
								                    }
							 | 
						||
| 
								 | 
							
								                }
							 | 
						||
| 
								 | 
							
								                else {
							 | 
						||
| 
								 | 
							
								                    /* if already in hwq, continue for next stream */
							 | 
						||
| 
								 | 
							
								                    continue;
							 | 
						||
| 
								 | 
							
								                }
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								            else
							 | 
						||
| 
								 | 
							
								            {
							 | 
						||
| 
								 | 
							
								                /* first time sending of the packet */
							 | 
						||
| 
								 | 
							
								                ret = mac_load_msdu(msdu, stream);
							 | 
						||
| 
								 | 
							
								                if (ret == ERR_FAIL) {
							 | 
						||
| 
								 | 
							
								                    /* if no msdu in this stream left, free
							 | 
						||
| 
								 | 
							
								                     * the msdu desc in the stream to save
							 | 
						||
| 
								 | 
							
								                     * some memory
							 | 
						||
| 
								 | 
							
								                     */
							 | 
						||
| 
								 | 
							
								                    mac_msdu_deinit(msdu);
							 | 
						||
| 
								 | 
							
								                    stream->msdu.tx.cur_tx_msdu = NULL;
							 | 
						||
| 
								 | 
							
								                    /* if empty, remove the stream from the queue and
							 | 
						||
| 
								 | 
							
								                     * then sch next swq. if the peer can del ,del it
							 | 
						||
| 
								 | 
							
								                     */
							 | 
						||
| 
								 | 
							
								                    mac_peer_t *peer = stream->peer;
							 | 
						||
| 
								 | 
							
								                    mac_swsch_remove(p_mac_swq, stream);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								                    //TODO: confirm do we need delete temp peer when rf msdu ?
							 | 
						||
| 
								 | 
							
								                    mac_peer_del_temp_peer(peer);
							 | 
						||
| 
								 | 
							
								                    if(p_mac_swq->q_depth)
							 | 
						||
| 
								 | 
							
								                        goto nextstream;
							 | 
						||
| 
								 | 
							
								                    continue;
							 | 
						||
| 
								 | 
							
								                }
							 | 
						||
| 
								 | 
							
								                if (!is_rf) {
							 | 
						||
| 
								 | 
							
								                    ret = mac_swsch_tx_msdu(pdev_id, vdev_id, \
							 | 
						||
| 
								 | 
							
								                        msdu, FC_DELIM_SOF, \
							 | 
						||
| 
								 | 
							
								                        proto, \
							 | 
						||
| 
								 | 
							
								                        HW_DESC_TX_PORT_PLC);
							 | 
						||
| 
								 | 
							
								                } else {
							 | 
						||
| 
								 | 
							
								                    ret = mac_rf_swsch_tx_msdu(rf_pdev, msdu, FC_DELIM_SOF,
							 | 
						||
| 
								 | 
							
								                        stream->peer->tei, stream->lid,
							 | 
						||
| 
								 | 
							
								                        (uint8_t)msdu->is_bcast);
							 | 
						||
| 
								 | 
							
								                }
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								    return ret;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								uint32_t mac_swsch_post_msdu(pdevid_t pdev_id, vdevid_t vdev_id)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								    uint32_t ret = 0;
							 | 
						||
| 
								 | 
							
								    (void)pdev_id;
							 | 
						||
| 
								 | 
							
								    (void)vdev_id;
							 | 
						||
| 
								 | 
							
								    ret = mac_swsch_post_msdu_internal(0);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#if HPLC_RF_DEV_SUPPORT
							 | 
						||
| 
								 | 
							
								    ret = mac_swsch_post_msdu_internal(1);
							 | 
						||
| 
								 | 
							
								#endif
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    return ret;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 |