307 lines
10 KiB
C
307 lines
10 KiB
C
/****************************************************************************
|
|
|
|
Copyright(c) 2019 by Aerospace C.Power (Chongqing) Microelectronics. ALL RIGHTS RESERVED.
|
|
|
|
This Information is proprietary to Aerospace C.Power (Chongqing) Microelectronics and MAY NOT
|
|
be copied by any method or incorporated into another program without
|
|
the express written consent of Aerospace C.Power. This Information or any portion
|
|
thereof remains the property of Aerospace C.Power. The Information contained herein
|
|
is believed to be accurate and Aerospace C.Power assumes no responsibility or
|
|
liability for its use in any way and conveys no license or title under
|
|
any patent or copyright and makes no representation or warranty that this
|
|
Information is free from patent or copyright infringement.
|
|
|
|
****************************************************************************/
|
|
#include "mac_msdu.h"
|
|
#include "iot_errno.h"
|
|
#include "plc_mac_header.h"
|
|
#include "plc_protocol.h"
|
|
#include "plc_const.h"
|
|
#include "mac_desc_engine.h"
|
|
#include "hw_tonemap.h"
|
|
#include "mac_tx_power.h"
|
|
#include "mpdu_header.h"
|
|
#include "iot_bitops_api.h"
|
|
#include "iot_io.h"
|
|
#include "mac_tx_hw.h"
|
|
#include "iot_config.h"
|
|
#include "tx_desc_reg_api.h"
|
|
#include "mac_rf_tx_hw.h"
|
|
#include "rf_hw_tonemap.h"
|
|
#include "mac_rf_tx_hw.h"
|
|
#include "mac_stream.h"
|
|
#include "rate_control.h"
|
|
|
|
#if HPLC_RF_DEV_SUPPORT
|
|
|
|
#include "mac_rf_tx_hw.h"
|
|
#include "rf_tx_mpdu_desc.h"
|
|
#include "rf_tx_desc_reg_api.h"
|
|
#include "sw_sched.h"
|
|
#include "mac_crypto.h"
|
|
|
|
uint32_t mac_tx_rf_msdu(mac_rf_pdev_t *rf_pdev, mac_msdu_t *msdu,
|
|
uint32_t option, uint32_t delimiter_type, tei_t dtei, lid_t lid,
|
|
uint8_t is_bcast, uint32_t nid, tei_t stei, uint32_t blkz, uint32_t pbsz,
|
|
uint32_t phr_mcs, uint32_t mcs, uint32_t msdu_len)
|
|
{
|
|
uint32_t tx_power = PHY_FULL_PWR_DBUV;
|
|
iot_pkt_t *data_buf = msdu->buf;
|
|
rf_tx_mpdu_start *tmp = NULL;
|
|
mac_rf_queue_t swq_id = 0;
|
|
uint32_t i, j, rest_pb_num_in_msdu, pb_num_to_send, hwretry_cnt;
|
|
uint32_t tmp_bitmap, cur_send_bitmap, pos, ret;
|
|
rf_tx_pb_start *pb_ptr;
|
|
rf_tx_mpdu_end *tx_status;
|
|
rf_tx_mpdu_start *next;
|
|
uint8_t list_start, list_end, phcl;
|
|
uint32_t hwqid, need_ack = 0, pb_buf_reuse, network = 0;
|
|
uint32_t tx_fl = 0;
|
|
uint32_t proto = PHY_PROTO_TYPE_GET();
|
|
|
|
if (dtei != PLC_TEI_BCAST) {
|
|
need_ack = 1;
|
|
}
|
|
// TODO: default hwretry cnt = 0
|
|
hwretry_cnt = 0;
|
|
|
|
phcl = mac_get_pb_hdr_resv_crc_len(FC_DELIM_SOF, proto);
|
|
|
|
/* get rest pb num in msdu */
|
|
if (msdu->send_bitmap == 0xffffffff) {
|
|
rest_pb_num_in_msdu = iot_ceil(msdu_len, (pbsz - phcl));
|
|
msdu->send_bitmap = 0xffffffff >> (32 - rest_pb_num_in_msdu);
|
|
} else {
|
|
rest_pb_num_in_msdu = iot_bitops_cbs((uint8_t)msdu->send_bitmap)
|
|
+ iot_bitops_cbs((uint8_t)(msdu->send_bitmap >> 8))
|
|
+ iot_bitops_cbs((uint8_t)(msdu->send_bitmap >> 16))
|
|
+ iot_bitops_cbs((uint8_t)(msdu->send_bitmap >> 24));
|
|
}
|
|
|
|
pb_num_to_send = rest_pb_num_in_msdu;
|
|
|
|
/* get the bitmap */
|
|
tmp_bitmap = msdu->send_bitmap;
|
|
|
|
/* construct all the mpdu desc */
|
|
for (i = 0; i < pb_num_to_send; i++) {
|
|
/* tmp pointer to mpdu start */
|
|
if (i == 0) {
|
|
list_start = 1;
|
|
tmp = &msdu->hw_desc.rf_mpdu_list;
|
|
pb_buf_reuse = 0;
|
|
} else {
|
|
list_start = 0;
|
|
pb_buf_reuse = 1;
|
|
}
|
|
/* is next exist && cal pb_num */
|
|
if (i != pb_num_to_send - 1) {
|
|
mac_desc_get(&g_mac_desc_eng, PLC_TX_MPDU_START_POOL,
|
|
(void**)&next);
|
|
IOT_ASSERT(next);
|
|
list_end = 0;
|
|
} else {
|
|
mac_desc_get(&g_mac_desc_eng, PLC_TX_DUMMY_NODE_POOL,
|
|
(void**)&next);
|
|
IOT_ASSERT(next);
|
|
mac_rf_tx_mpdu_fill_dummy((rf_tx_dummy_node *)next);
|
|
list_end = 1;
|
|
}
|
|
|
|
/* find the first vaild pb */
|
|
j = 0;
|
|
/* 1 mpdu have 1pb */
|
|
for(; j < 32; j += 8) {
|
|
ret = iot_bitops_ffs((uint8_t)(tmp_bitmap >> j));
|
|
if (ret) {
|
|
pos = (ret + j - 1);
|
|
tmp_bitmap &= (~(0x01 << pos));
|
|
break;
|
|
}
|
|
}
|
|
/* can not more than 32pb */
|
|
if (j == 32) {
|
|
IOT_ASSERT(0);
|
|
}
|
|
|
|
/* update msdu send_bitmap */
|
|
cur_send_bitmap = tmp_bitmap ^ msdu->send_bitmap;
|
|
|
|
iot_printf("---send_bitmap=0x%x/0x%x,HW_R_C=%d\n", \
|
|
cur_send_bitmap, msdu->send_bitmap, hwretry_cnt);
|
|
|
|
/* fill fc */
|
|
mac_rf_tx_mpdu_fill_phrinfo(tmp, proto, delimiter_type, network, nid,
|
|
0, stei, dtei, mcs, lid, (uint16_t)blkz, (uint8_t)msdu->retry, 0,
|
|
is_bcast);
|
|
|
|
if (msdu->need_encrypt) {
|
|
mac_encrypt_msdu_handle(data_buf, (uint8_t *)&tmp->phr0, proto,
|
|
msdu->key_idx);
|
|
msdu->need_encrypt = 0;
|
|
}
|
|
|
|
/* fill pb_list for mpdu */
|
|
mac_rf_tx_mpdu_form_pb(&pb_ptr, data_buf, cur_send_bitmap, pbsz);
|
|
/* fill mpdu end */
|
|
mac_desc_get(&g_mac_desc_eng, PLC_TX_MPDU_END_POOL,
|
|
(void**)&tx_status);
|
|
IOT_ASSERT(tx_status);
|
|
|
|
swq_id = mac_rf_q_get_swqid_from_lid(&rf_pdev->hwq_hdl, lid,
|
|
(uint8_t)msdu->is_dbg_pkt);
|
|
|
|
/* fill mac info */
|
|
mac_rf_tx_mpdu_fill_macinfo(tmp, next, pb_ptr, tx_status, proto,
|
|
need_ack, hwretry_cnt, tx_power, msdu->retry, 1, pb_buf_reuse, 0,
|
|
(uint32_t)iot_pkt_data(data_buf)-(uint32_t)data_buf, list_start,
|
|
list_end, phr_mcs, 0, 0, mcs, blkz, 0, 0, swq_id, option, 1, tx_fl);
|
|
|
|
/* fill phyinfo */
|
|
mac_rf_tx_mpdu_fill_phyinfo(tmp, 0);
|
|
|
|
tmp = next;
|
|
}
|
|
|
|
/* rf retry */
|
|
if (msdu->retry_cnt) {
|
|
msdu->retry_cnt--;
|
|
}
|
|
|
|
/* calulate hwqid */
|
|
hwqid = mac_rf_q_create_hwqid_from_swqid(&rf_pdev->hwq_hdl, swq_id);
|
|
|
|
/* enqueue to hwq */
|
|
msdu->in_hwq = 1;
|
|
return mac_rf_tx_hw_mpdu(&rf_pdev->hwq_hdl,
|
|
hwqid, &msdu->hw_desc.rf_mpdu_list);
|
|
}
|
|
|
|
mac_msdu_t *mac_rf_tx_hw_msdu_comp(uint32_t hwq_id, rf_tx_mpdu_start *current_mpdu,
|
|
mac_rf_pdev_t *pdev)
|
|
{
|
|
uint8_t is_msdu_free, pkt_state = IOT_PKT_STATE_UNKNOWN;
|
|
rf_tx_pb_start *pbstart = NULL;
|
|
mac_msdu_t *msdu = pdev->hwq_hdl.cur_msdu_ptr[hwq_id];
|
|
uint32_t proto = PHY_PROTO_TYPE_GET();
|
|
|
|
IOT_ASSERT(current_mpdu);
|
|
/* get mac_msdu addr */
|
|
if (current_mpdu->list_start) {
|
|
IOT_ASSERT(msdu == NULL);
|
|
msdu = (mac_msdu_t*)current_mpdu;
|
|
pdev->hwq_hdl.cur_msdu_ptr[hwq_id] = current_mpdu;
|
|
}
|
|
/* for peer's rate info */
|
|
mac_stream_t *stream = msdu->ref_mac_stream;
|
|
mac_peer_t *peer = NULL;
|
|
if (stream && stream->peer) {
|
|
peer = stream->peer;
|
|
is_msdu_free = 0;
|
|
} else {
|
|
is_msdu_free = 1;
|
|
|
|
/* force msdu all mpdu tx done */
|
|
if (!current_mpdu->list_end) {
|
|
/* for rf, 1 msdu can contain only 1 mpdu */
|
|
//current_mpdu->next->tx_status->tx_done = 1;
|
|
IOT_ASSERT_DUMP(0, (uint32_t *)current_mpdu, sizeof(*current_mpdu) / 4);
|
|
}
|
|
}
|
|
|
|
/* if sw retry broadcast */
|
|
if (!mac_is_unicast(proto,
|
|
mac_rf_tx_mpdu_st_get_phy_header(current_mpdu), 1)) {
|
|
current_mpdu->tx_status->tx_ok = 1;
|
|
current_mpdu->tx_status->rx_sack_ok = 0;
|
|
if (msdu->retry_cnt) {
|
|
msdu->retry = 1;
|
|
}
|
|
}
|
|
|
|
/* sw retry when no rf sack */
|
|
IOT_ASSERT(current_mpdu->tx_status);
|
|
if (!current_mpdu->tx_status->tx_ok) {
|
|
pkt_state = IOT_PKT_STATE_TX_FAIL;
|
|
msdu->retry = 1;
|
|
current_mpdu->tx_status->rx_sack_ok = 0;
|
|
if (peer) {
|
|
/* record no sack continue */
|
|
//TODO: call rf_ra_add_no_sack_cnt()
|
|
}
|
|
} else {
|
|
if (!current_mpdu->tx_status->rx_sack_ok) {
|
|
pkt_state = IOT_PKT_STATE_TX_OK_RX_UNKNOWN;
|
|
msdu->retry = 1;
|
|
} else {
|
|
pkt_state = IOT_PKT_STATE_TX_OK_RX_OK;
|
|
}
|
|
}
|
|
|
|
/*update bitmap*/
|
|
if (msdu) {
|
|
if (current_mpdu->pb != NULL) {
|
|
pbstart = current_mpdu->pb;
|
|
#if SUPPORT_SMART_GRID
|
|
if (proto == PLC_PROTO_TYPE_SG) {
|
|
sg_sof_pb_hdr_t pb_head = { 0 };
|
|
if (current_mpdu->tx_status->rx_sack_ok) {
|
|
*(uint8_t*) &pb_head = (uint8_t) pbstart->sof_pb_header;
|
|
msdu->send_bitmap &= ~((uint32_t)(1 << pb_head.seq));
|
|
}
|
|
#if DEBUG_SSN
|
|
iot_printf("--msdu:ssn%d, sack_ok:0x%x, send:0x%x\n",
|
|
pb_head.seq, current_mpdu->tx_status->rx_sack_ok,
|
|
msdu->send_bitmap);
|
|
#endif
|
|
} else
|
|
#endif
|
|
#if SUPPORT_SOUTHERN_POWER_GRID
|
|
if (proto == PLC_PROTO_TYPE_SPG) {
|
|
spg_sof_pb_hdr_t pb_head = { 0 };
|
|
if (current_mpdu->tx_status->rx_sack_ok) {
|
|
*(uint8_t*) &pb_head = (uint8_t) pbstart->sof_pb_header;
|
|
msdu->send_bitmap &= ~((uint32_t)(1 << pb_head.seq));
|
|
}
|
|
#if DEBUG_SSN
|
|
iot_printf("--msdu:ssn%d, sack_ok:0x%x, send:0x%x\n",
|
|
pb_head.seq, current_mpdu->tx_status->rx_sack_ok,
|
|
msdu->send_bitmap);
|
|
#endif
|
|
} else
|
|
#endif
|
|
{
|
|
//do not delete this case
|
|
}
|
|
}
|
|
}
|
|
|
|
if (current_mpdu->list_end) {
|
|
IOT_ASSERT(msdu && msdu->buf && msdu->in_hwq);
|
|
if (msdu->send_bitmap == 0) {
|
|
/* all pb sent ok, time to free the buf */
|
|
if (msdu->buf_need_free == 1) {
|
|
iot_pkt_free_tx_done(msdu->buf, pkt_state);
|
|
}
|
|
msdu->buf = NULL;
|
|
} else {
|
|
if(msdu->retry_cnt == 0) {
|
|
if (msdu->buf_need_free == 1) {
|
|
iot_pkt_free_tx_done(msdu->buf, pkt_state);
|
|
}
|
|
msdu->buf = NULL;
|
|
}
|
|
}
|
|
|
|
pdev->hwq_hdl.cur_msdu_ptr[hwq_id] = NULL;
|
|
msdu->in_hwq = 0;
|
|
|
|
if (is_msdu_free) {
|
|
return msdu;
|
|
}
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
#endif /* HPLC_RF_DEV_SUPPORT */
|