From 6f6166e36cfe0c162c0565ced47a0745eb680e4d Mon Sep 17 00:00:00 2001 From: Tallapragada Kalyan Date: Fri, 17 Feb 2017 17:00:23 +0530 Subject: [PATCH] qcacmn: Add support for intra-bss forwarding pkts should be forwarded from one STA to another STA belonging to same VAP from within the driver Change-Id: I68eb0dd91f7ac54352b4882ffdb9d5d53d627db1 Conflicts: dp/wifi3.0/dp_rx.c dp/wifi3.0/dp_types.h Conflicts: dp/wifi3.0/dp_rx.c Change-Id: I68eb0dd91f7ac54352b4882ffdb9d5d53d627db1 --- dp/wifi3.0/dp_htt.c | 7 +- dp/wifi3.0/dp_main.c | 20 ++++++ dp/wifi3.0/dp_peer.c | 93 ++++++++++++++++++++++++-- dp/wifi3.0/dp_peer.h | 2 +- dp/wifi3.0/dp_rx.c | 68 ++++++++++++++++--- dp/wifi3.0/dp_types.h | 148 +++++++++++++++++++++++++++++++++++++++++- dp/wifi3.0/hal_rx.h | 75 +++++++++++++++++++++ 7 files changed, 394 insertions(+), 19 deletions(-) diff --git a/dp/wifi3.0/dp_htt.c b/dp/wifi3.0/dp_htt.c index 6f941b438a..b03d97833d 100644 --- a/dp/wifi3.0/dp_htt.c +++ b/dp/wifi3.0/dp_htt.c @@ -518,9 +518,12 @@ static void dp_htt_t2h_msg_handler(void *context, HTC_PACKET *pkt) u_int8_t mac_addr_deswizzle_buf[HTT_MAC_ADDR_LEN]; u_int8_t *peer_mac_addr; u_int16_t peer_id; + u_int16_t hw_peer_id; u_int8_t vdev_id; peer_id = HTT_RX_PEER_MAP_PEER_ID_GET(*msg_word); + hw_peer_id = + HTT_RX_PEER_MAP_HW_PEER_ID_GET(*(msg_word+2)); vdev_id = HTT_RX_PEER_MAP_VDEV_ID_GET(*msg_word); peer_mac_addr = htt_t2h_mac_addr_deswizzle( (u_int8_t *) (msg_word+1), @@ -530,8 +533,8 @@ static void dp_htt_t2h_msg_handler(void *context, HTC_PACKET *pkt) "HTT_T2H_MSG_TYPE_PEER_MAP msg for peer id %d vdev id %d n", peer_id, vdev_id); - dp_rx_peer_map_handler( - soc->dp_soc, peer_id, vdev_id, peer_mac_addr); + dp_rx_peer_map_handler(soc->dp_soc, peer_id, hw_peer_id, + vdev_id, peer_mac_addr); break; } case HTT_T2H_MSG_TYPE_PEER_UNMAP: diff --git a/dp/wifi3.0/dp_main.c b/dp/wifi3.0/dp_main.c index 687294dc6b..719781240b 100644 --- a/dp/wifi3.0/dp_main.c +++ b/dp/wifi3.0/dp_main.c @@ -1692,6 +1692,13 @@ static void *dp_peer_create_wifi3(struct cdp_vdev *vdev_handle, if (!peer) return NULL; /* failure */ + TAILQ_INIT(&peer->ast_entry_list); + qdf_mem_copy(&peer->self_ast_entry.mac_addr, peer_mac_addr, + DP_MAC_ADDR_LEN); + peer->self_ast_entry.peer = peer; + TAILQ_INSERT_HEAD(&peer->ast_entry_list, &peer->self_ast_entry, + ast_entry_elem); + qdf_mem_zero(peer, sizeof(struct dp_peer)); qdf_spinlock_create(&peer->peer_info_lock); @@ -1849,6 +1856,8 @@ void dp_peer_unref_delete(void *peer_handle) struct dp_peer *tmppeer; int found = 0; uint16_t peer_id; + uint16_t hw_peer_id; + struct dp_ast_entry *ast_entry; /* * Hold the lock all the way from checking if the peer ref count @@ -1932,6 +1941,17 @@ void dp_peer_unref_delete(void *peer_handle) #ifdef notyet qdf_mempool_free(soc->osdev, soc->mempool_ol_ath_peer, peer); #else + TAILQ_FOREACH(ast_entry, &peer->ast_entry_list, + ast_entry_elem) { + hw_peer_id = ast_entry->ast_idx; + if (peer->self_ast_entry.ast_idx != hw_peer_id) + qdf_mem_free(ast_entry); + else + peer->self_ast_entry.ast_idx = + HTT_INVALID_PEER; + + soc->ast_table[hw_peer_id] = NULL; + } qdf_mem_free(peer); #endif if (soc->cdp_soc.ol_ops->peer_unref_delete) { diff --git a/dp/wifi3.0/dp_peer.c b/dp/wifi3.0/dp_peer.c index 38f8230c99..2c56e70592 100644 --- a/dp/wifi3.0/dp_peer.c +++ b/dp/wifi3.0/dp_peer.c @@ -327,7 +327,8 @@ int dp_peer_find_attach(struct dp_soc *soc) } static inline void dp_peer_find_add_id(struct dp_soc *soc, - uint8_t *peer_mac_addr, uint16_t peer_id, uint8_t vdev_id) + uint8_t *peer_mac_addr, uint16_t peer_id, uint16_t hw_peer_id, + uint8_t vdev_id) { struct dp_peer *peer; @@ -353,6 +354,8 @@ static inline void dp_peer_find_add_id(struct dp_soc *soc, "%s: ref_cnt: %d", __func__, qdf_atomic_read(&peer->ref_cnt)); soc->peer_id_to_obj_map[peer_id] = peer; + peer->self_ast_entry.ast_idx = hw_peer_id; + soc->ast_table[hw_peer_id] = &peer->self_ast_entry; if (dp_peer_find_add_id_to_obj(peer, peer_id)) { /* TBDXXX: assert for now */ @@ -363,19 +366,95 @@ static inline void dp_peer_find_add_id(struct dp_soc *soc, } } +static inline void dp_peer_add_ast(struct dp_soc *soc, + struct dp_peer *peer, uint8_t *peer_mac_addr, uint16_t hw_peer_id, + uint8_t vdev_id) +{ + struct dp_ast_entry *ast_entry; + + QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR, + "%s: peer %p ID %d vid %d mac %02x:%02x:%02x:%02x:%02x:%02x\n", + __func__, peer, hw_peer_id, vdev_id, peer_mac_addr[0], + peer_mac_addr[1], peer_mac_addr[2], peer_mac_addr[3], + peer_mac_addr[4], peer_mac_addr[5]); + + TAILQ_FOREACH(ast_entry, &peer->ast_entry_list, ast_entry_elem) { + if (!(qdf_mem_cmp(peer_mac_addr, ast_entry->mac_addr, + DP_MAC_ADDR_LEN))) { + soc->ast_table[ast_entry->ast_idx] = NULL; + ast_entry->ast_idx = hw_peer_id; + soc->ast_table[hw_peer_id] = ast_entry; + return; + } + } + + ast_entry = (struct dp_ast_entry *) + qdf_mem_malloc(sizeof(struct dp_ast_entry)); + + if (!ast_entry) { + QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR, + FL("fail to allocate ast_entry for: %d"), hw_peer_id); + QDF_ASSERT(0); + } + + qdf_mem_copy(&ast_entry->mac_addr, peer_mac_addr, DP_MAC_ADDR_LEN); + ast_entry->peer = peer; + ast_entry->next_hop = 1; + TAILQ_INSERT_TAIL(&peer->ast_entry_list, ast_entry, ast_entry_elem); + soc->ast_table[hw_peer_id] = ast_entry; + return; +} + +/** + * dp_rx_peer_map_handler() - handle peer map event from firmware + * @soc_handle - genereic soc handle + * @peeri_id - peer_id from firmware + * @hw_peer_id - ast index for this peer + * vdev_id - vdev ID + * peer_mac_addr - macc assress of the peer + * + * associate the peer_id that firmware provided with peer entry + * and update the ast table in the host with the hw_peer_id. + * + * Return: none + */ + void -dp_rx_peer_map_handler(void *soc_handle, uint16_t peer_id, uint8_t vdev_id, - uint8_t *peer_mac_addr) +dp_rx_peer_map_handler(void *soc_handle, uint16_t peer_id, uint16_t hw_peer_id, + uint8_t vdev_id, uint8_t *peer_mac_addr) { struct dp_soc *soc = (struct dp_soc *)soc_handle; + struct dp_peer *peer = NULL; + QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_INFO_HIGH, - "peer_map_event (soc:%p): peer_id %d, peer_mac " + "peer_map_event (soc:%p): peer_id %di, hw_peer_id %d, peer_mac " "%02x:%02x:%02x:%02x:%02x:%02x, vdev_id %d\n", soc, peer_id, - peer_mac_addr[0], peer_mac_addr[1], peer_mac_addr[2], - peer_mac_addr[3], peer_mac_addr[4], peer_mac_addr[5], vdev_id); + hw_peer_id, peer_mac_addr[0], peer_mac_addr[1], + peer_mac_addr[2], peer_mac_addr[3], peer_mac_addr[4], + peer_mac_addr[5], vdev_id); - dp_peer_find_add_id(soc, peer_mac_addr, peer_id, vdev_id); + peer = soc->peer_id_to_obj_map[peer_id]; + + if ((hw_peer_id < 0) || (hw_peer_id > WLAN_UMAC_PSOC_MAX_PEERS)) { + QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR, + "invalid hw_peer_id: %d", hw_peer_id); + QDF_ASSERT(0); + } + + /* + * check if peer already exists for this peer_id, if so + * this peer map event is in response for a wds peer add + * wmi command sent during wds source port learning. + * in this case just add the ast entry to the existing + * peer ast_list. + */ + if (!peer) + dp_peer_find_add_id(soc, peer_mac_addr, peer_id, + hw_peer_id, vdev_id); + else + dp_peer_add_ast(soc, peer, peer_mac_addr, + hw_peer_id, vdev_id); } void diff --git a/dp/wifi3.0/dp_peer.h b/dp/wifi3.0/dp_peer.h index 6fc8084986..64fb8f915d 100644 --- a/dp/wifi3.0/dp_peer.h +++ b/dp/wifi3.0/dp_peer.h @@ -46,7 +46,7 @@ dp_peer_find_by_id(struct dp_soc *soc, } void dp_rx_peer_map_handler(void *soc_handle, uint16_t peer_id, - uint8_t vdev_id, uint8_t *peer_mac_addr); + uint16_t hw_peer_id, uint8_t vdev_id, uint8_t *peer_mac_addr); void dp_rx_peer_unmap_handler(void *soc_handle, uint16_t peer_id); void dp_rx_sec_ind_handler(void *soc_handle, uint16_t peer_id, enum htt_sec_type sec_type, int is_unicast, diff --git a/dp/wifi3.0/dp_rx.c b/dp/wifi3.0/dp_rx.c index a19ba70622..f0847b67fb 100644 --- a/dp/wifi3.0/dp_rx.c +++ b/dp/wifi3.0/dp_rx.c @@ -283,10 +283,62 @@ dp_rx_intrabss_fwd(struct dp_soc *soc, uint8_t *rx_tlv_hdr, qdf_nbuf_t nbuf) { - DP_STATS_INC_PKT(sa_peer, rx.intra_bss, 1, - qdf_nbuf_len(nbuf)); - QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR, - FL("Intra-BSS forwarding not implemented")); + uint16_t da_idx; + uint16_t len; + struct dp_peer *da_peer; + struct dp_ast_entry *ast_entry; + qdf_nbuf_t nbuf_copy; + + /* check if the destination peer is available in peer table + * and also check if the source peer and destination peer + * belong to the same vap and destination peer is not bss peer. + */ + if ((hal_rx_msdu_end_da_is_valid_get(rx_tlv_hdr) && + !hal_rx_msdu_end_da_is_mcbc_get(rx_tlv_hdr))) { + da_idx = hal_rx_msdu_end_da_idx_get(rx_tlv_hdr); + + ast_entry = soc->ast_table[da_idx]; + if (!ast_entry) + return false; + + da_peer = ast_entry->peer; + + if (!da_peer) + return false; + + if (da_peer->vdev == sa_peer->vdev && !da_peer->bss_peer) { + memset(nbuf->cb, 0x0, sizeof(nbuf->cb)); + len = qdf_nbuf_len(nbuf); + if (!dp_tx_send(sa_peer->vdev, nbuf)) { + DP_STATS_INC_PKT(sa_peer, rx.intra_bss, 1, len); + return true; + } else + return false; + } + } + /* if it is a broadcast pkt (eg: ARP) and it is not its own + * source, then clone the pkt and send the cloned pkt for + * intra BSS forwarding and original pkt up the network stack + * Note: how do we handle multicast pkts. do we forward + * all multicast pkts as is or let a higher layer module + * like igmpsnoop decide whether to forward or not with + * Mcast enhancement. + */ + else if (qdf_unlikely((hal_rx_msdu_end_da_is_mcbc_get(rx_tlv_hdr) && + !sa_peer->bss_peer))) { + nbuf_copy = qdf_nbuf_copy(nbuf); + if (!nbuf_copy) + return false; + memset(nbuf_copy->cb, 0x0, sizeof(nbuf_copy->cb)); + len = qdf_nbuf_len(nbuf_copy); + if (dp_tx_send(sa_peer->vdev, nbuf_copy)) + qdf_nbuf_free(nbuf_copy); + else + DP_STATS_INC_PKT(sa_peer, rx.intra_bss, 1, len); + } + /* return false as we have to still send the original pkt + * up the stack + */ return false; } @@ -426,7 +478,6 @@ QDF_STATUS dp_rx_filter_mesh_packets(struct dp_vdev *vdev, qdf_nbuf_t nbuf) #endif - /** * dp_rx_process() - Brain of the Rx processing functionality * Called from the bottom half (tasklet/NET_RX_SOFTIRQ) @@ -749,9 +800,10 @@ done: dp_rx_wds_srcport_learn(soc, rx_tlv_hdr, peer, nbuf); /* Intrabss-fwd */ - if (peer && - dp_rx_intrabss_fwd(soc, peer, rx_tlv_hdr, nbuf)) - continue; /* Get next descriptor */ + if (vdev->opmode != wlan_op_mode_sta) + if (dp_rx_intrabss_fwd(soc, peer, rx_tlv_hdr, + nbuf)) + continue; /* Get next descriptor */ rx_bufs_used++; DP_RX_LIST_APPEND(deliver_list_head, diff --git a/dp/wifi3.0/dp_types.h b/dp/wifi3.0/dp_types.h index fc56150de2..4a2fe20ab4 100644 --- a/dp/wifi3.0/dp_types.h +++ b/dp/wifi3.0/dp_types.h @@ -56,6 +56,27 @@ #define DP_QOS_TID 0x0f #define DP_IPV6_PRIORITY_SHIFT 20 +#if defined(CONFIG_MCL) +#define MAX_PDEV_CNT 1 +#else +#define MAX_PDEV_CNT 3 +#endif +#define MAX_LINK_DESC_BANKS 8 +#define MAX_TXDESC_POOLS 4 +#define MAX_RXDESC_POOLS 4 +#define MAX_REO_DEST_RINGS 4 +#define MAX_TCL_DATA_RINGS 4 +#define DP_MAX_TX_RINGS 8 +#define DP_MAX_RX_RINGS 8 +#define MAX_IDLE_SCATTER_BUFS 16 +#define DP_MAX_IRQ_PER_CONTEXT 12 +#define DP_MAX_INTERRUPT_CONTEXTS 8 +#define DEFAULT_HW_PEER_ID 0xffff + +#define MAX_TX_HW_QUEUES 3 + +#define DP_MAX_INTERRUPT_CONTEXTS 8 + struct dp_soc_cmn; struct dp_pdev; struct dp_vdev; @@ -91,6 +112,7 @@ union dp_rx_desc_list_elem_t; #define DP_SW2HW_MACID(id) ((id) + 1) #define DP_HW2SW_MACID(id) ((id) > 0 ? ((id) - 1) : 0) +#define DP_MAC_ADDR_LEN 6 /** * enum dp_tx_frm_type @@ -290,6 +312,124 @@ struct reo_desc_list_node { struct dp_rx_tid rx_tid; }; +/* TODO: Proper comments have been added in the subsequesnt gerrit */ +/* packet info */ +struct dp_pkt_info { + uint32_t num; /*no of packets*/ + uint32_t bytes; /* total no of bytes */ +}; + +/* per pdev tx stats*/ +struct dp_tx_pdev_stats { + + struct dp_pkt_info rcvd; /*total packets received for transmission */ + struct { + /* Pkt Info for which completions were received */ + struct dp_pkt_info comp_pkt; + uint32_t mcs_count[MAX_MCS + 1]; /* MCS Count */ + } comp; /* Tx completions received*/ + + struct dp_pkt_info freed; /* Tx packets freed*/ + + struct dp_pkt_info processed; /* Tx packets processed*/ + struct dp_pkt_info outstanding; /* Tx packets remaining for processing*/ + + struct { + struct dp_pkt_info dropped_pkt; /* Total packets dropped */ + uint32_t desc_total; /* total descriptors dropped */ + uint32_t dma_map_error; /* Dropped due to Dma Error */ + uint32_t ring_full; /* dropped due to ring full */ + uint32_t fw_discard; /* Discarded bu firmware */ + uint32_t fw_discard_retired; /* fw_discard_retired */ + /* firmware_discard_untransmitted */ + uint32_t firmware_discard_untransmitted; + uint32_t mpdu_age_out; /* mpdu_age_out */ + uint32_t firmware_discard_reason1; /*firmware_discard_reason1*/ + uint32_t firmware_discard_reason2; /*firmware_discard_reason2*/ + uint32_t firmware_discard_reason3; /*firmware_discard_reason3*/ + } dropped; /* Packets dropped on the Tx side */ + + struct { + struct dp_pkt_info sg_pkt; /* total scatter gather packets */ + uint32_t dropped_host; /* SG packets dropped by host */ + uint32_t dropped_target; /* SG packets dropped by target */ + } sg; /* Scatter Gather packet info */ + + struct { + uint32_t num_seg; /* No of segments in TSO packets */ + struct dp_pkt_info tso_pkt; /* total no of TSO packets */ + uint32_t dropped_host; /* TSO packets dropped by host */ + uint32_t dropped_target; /* TSO packets dropped by target */ + } tso; /* TSO packets info */ + + struct { + /* total no of multicast conversion packets */ + struct dp_pkt_info mcast_pkt; + /* packets dropped due to map error */ + uint32_t dropped_map_error; + /* packets dropped due to self Mac address */ + uint32_t dropped_self_mac; + /* Packets dropped due to send fail */ + uint32_t dropped_send_fail; + /* total unicast packets transmitted */ + uint32_t ucast; + } mcast_en; /* Multicast Enhancement packets info */ + + /* Total packets passed Reinject handler */ + struct dp_pkt_info reinject_pkts; + /* Total packets passed to inspect handler */ + struct dp_pkt_info inspect_pkts; + /* Total Raw packets */ + struct dp_pkt_info raw_pkt; +}; + +/* Per pdev RX stats */ +struct dp_rx_pdev_stats { + struct dp_pkt_info rcvd_reo; /* packets received on the reo ring */ + struct { + /* packets dropped because of no peer */ + struct dp_pkt_info no_peer; + /* packets dropped because nsdu_done bit not set */ + struct dp_pkt_info msdu_not_done; + } dropped; /* packets dropped on rx */ + struct dp_pkt_info replenished; /* total packets replnished */ + struct dp_pkt_info to_stack; /* total packets sent up the stack */ + struct dp_pkt_info intra_bss; /* Intra BSS packets received */ + struct dp_pkt_info wds; /* WDS packets received */ + struct dp_pkt_info desc; + struct dp_pkt_info buff; + struct dp_pkt_info raw; /* Raw Pakets received */ + struct { + uint32_t rxdma_unitialized; /* rxdma_unitialized errors */ + uint32_t desc_alloc_fail; /* desc alloc failed errors */ + } err; /* Rx errors */ + uint32_t buf_freelist; /* buffers added back in freelist */ + uint32_t mcs_count[MAX_MCS + 1]; /* packets in different MCS rates */ + uint32_t sgi_count[MAX_MCS + 1]; /* SGI count */ + /* Number of MSDUs with no MPDU level aggregation */ + uint32_t non_ampdu_cnt; + /* Number of MSDUs part of AMSPU */ + uint32_t ampdu_cnt; + /* Number of MSDUs with no MSDU level aggregation */ + uint32_t non_amsdu_cnt; + /* Number of MSDUs part of AMSDU*/ + uint32_t amsdu_cnt; + /* Packet count in spatiel Streams */ + uint32_t nss[SS_COUNT]; + /* Packet count in different Bandwidths */ + uint32_t bw[SUPPORTED_BW]; + /* reception type os packets */ + uint32_t reception_type[SUPPORTED_RECEPTION_TYPES]; +}; + +struct dp_ast_entry { + uint16_t ast_idx; + uint8_t mac_addr[DP_MAC_ADDR_LEN]; + uint8_t next_hop; + struct dp_peer *peer; + TAILQ_ENTRY(dp_ast_entry) ast_entry_elem; +}; + /* SOC level structure for data path */ struct dp_soc { /* Common base structure - Should be the first member */ @@ -502,6 +642,8 @@ struct dp_soc { /* Enable processing of Tx completion status words */ bool process_tx_status; + struct dp_ast_entry *ast_table[WLAN_UMAC_PSOC_MAX_PEERS]; + #ifdef DP_INTR_POLL_BASED /*interrupt timer*/ qdf_timer_t int_timer; @@ -601,7 +743,6 @@ struct dp_pdev { struct dp_peer; -#define DP_MAC_ADDR_LEN 6 union dp_align_mac_addr { uint8_t raw[DP_MAC_ADDR_LEN]; struct { @@ -731,6 +872,8 @@ struct dp_peer { /* VDEV to which this peer is associated */ struct dp_vdev *vdev; + struct dp_ast_entry self_ast_entry; + qdf_atomic_t ref_cnt; /* TODO: See if multiple peer IDs are required in wifi3.0 */ @@ -785,5 +928,8 @@ struct dp_peer { qdf_time_t last_deauth_rcvd; /* Peer Stats */ struct cdp_peer_stats stats; + + TAILQ_HEAD(, dp_ast_entry) ast_entry_list; + /* TBD */ }; #endif /* _DP_TYPES_H_ */ diff --git a/dp/wifi3.0/hal_rx.h b/dp/wifi3.0/hal_rx.h index c0ec348d44..71300a05c6 100644 --- a/dp/wifi3.0/hal_rx.h +++ b/dp/wifi3.0/hal_rx.h @@ -1252,6 +1252,81 @@ QDF_STATUS hal_rx_mpdu_get_addr2(uint8_t *buf, uint8_t *mac_addr) return QDF_STATUS_E_FAILURE; } +#define HAL_RX_MSDU_END_DA_IDX_GET(_rx_msdu_end) \ + (_HAL_MS((*_OFFSET_TO_WORD_PTR(_rx_msdu_end, \ + RX_MSDU_END_13_DA_IDX_OFFSET)), \ + RX_MSDU_END_13_DA_IDX_MASK, \ + RX_MSDU_END_13_DA_IDX_LSB)) + + /** + * hal_rx_msdu_end_da_idx_get: API to get da_idx + * from rx_msdu_end TLV + * + * @ buf: pointer to the start of RX PKT TLV headers + * Return: da index + */ +static inline uint16_t +hal_rx_msdu_end_da_idx_get(uint8_t *buf) +{ + struct rx_pkt_tlvs *pkt_tlvs = (struct rx_pkt_tlvs *)buf; + struct rx_msdu_end *msdu_end = &pkt_tlvs->msdu_end_tlv.rx_msdu_end; + uint16_t da_idx; + + da_idx = HAL_RX_MSDU_END_DA_IDX_GET(msdu_end); + + return da_idx; +} + +#define HAL_RX_MSDU_END_DA_IS_VALID_GET(_rx_msdu_end) \ + (_HAL_MS((*_OFFSET_TO_WORD_PTR(_rx_msdu_end, \ + RX_MSDU_END_5_DA_IS_VALID_OFFSET)), \ + RX_MSDU_END_5_DA_IS_VALID_MASK, \ + RX_MSDU_END_5_DA_IS_VALID_LSB)) + + /** + * hal_rx_msdu_end_da_is_valid_get: API to check if da is valid + * from rx_msdu_end TLV + * + * @ buf: pointer to the start of RX PKT TLV headers + * Return: da_is_valid + */ +static inline uint8_t +hal_rx_msdu_end_da_is_valid_get(uint8_t *buf) +{ + struct rx_pkt_tlvs *pkt_tlvs = (struct rx_pkt_tlvs *)buf; + struct rx_msdu_end *msdu_end = &pkt_tlvs->msdu_end_tlv.rx_msdu_end; + uint8_t da_is_valid; + + da_is_valid = HAL_RX_MSDU_END_DA_IS_VALID_GET(msdu_end); + + return da_is_valid; +} + +#define HAL_RX_MSDU_END_DA_IS_MCBC_GET(_rx_msdu_end) \ + (_HAL_MS((*_OFFSET_TO_WORD_PTR(_rx_msdu_end, \ + RX_MSDU_END_5_DA_IS_MCBC_OFFSET)), \ + RX_MSDU_END_5_DA_IS_MCBC_MASK, \ + RX_MSDU_END_5_DA_IS_MCBC_LSB)) + + /** + * hal_rx_msdu_end_da_is_mcbc_get: API to check if pkt is MCBC + * from rx_msdu_end TLV + * + * @ buf: pointer to the start of RX PKT TLV headers + * Return: da_is_mcbc + */ +static inline uint8_t +hal_rx_msdu_end_da_is_mcbc_get(uint8_t *buf) +{ + struct rx_pkt_tlvs *pkt_tlvs = (struct rx_pkt_tlvs *)buf; + struct rx_msdu_end *msdu_end = &pkt_tlvs->msdu_end_tlv.rx_msdu_end; + uint8_t da_is_mcbc; + + da_is_mcbc = HAL_RX_MSDU_END_DA_IS_MCBC_GET(msdu_end); + + return da_is_mcbc; +} + /******************************************************************************* * RX ERROR APIS ******************************************************************************/