From 7e69eaa30332fc7e1f096b01517676e7eee90f10 Mon Sep 17 00:00:00 2001 From: psimha Date: Mon, 8 Jan 2018 16:35:26 -0800 Subject: [PATCH] qcacmn: RX defragmentation fixes - Handle WDS case during encapsulation - Drop non-head duplicate fragments from list - Get REO DST ring id from msdu_info of incoming packet Change-Id: I7e4c9c211548aafe9b4ba88fb12890f38aced324 CRs-Fixed: 2174750 --- dp/wifi3.0/dp_rx_defrag.c | 51 +++++++++++++++------ dp/wifi3.0/hal_rx.h | 96 ++++++++++++++++++++++++++++++++++++--- 2 files changed, 126 insertions(+), 21 deletions(-) diff --git a/dp/wifi3.0/dp_rx_defrag.c b/dp/wifi3.0/dp_rx_defrag.c index 7c23107636f3..b64e3277b051 100644 --- a/dp/wifi3.0/dp_rx_defrag.c +++ b/dp/wifi3.0/dp_rx_defrag.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017 The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2018 The Linux Foundation. All rights reserved. * * Permission to use, copy, modify, and/or distribute this software for * any purpose with or without fee is hereby granted, provided that the @@ -154,9 +154,9 @@ static void dp_rx_defrag_waitlist_remove(struct dp_peer *peer, unsigned tid) * * Build a per-tid, per-sequence fragment list. * - * Returns: None + * Returns: Success, if inserted */ -static void dp_rx_defrag_fraglist_insert(struct dp_peer *peer, unsigned tid, +static QDF_STATUS dp_rx_defrag_fraglist_insert(struct dp_peer *peer, unsigned tid, qdf_nbuf_t *head_addr, qdf_nbuf_t *tail_addr, qdf_nbuf_t frag, uint8_t *all_frag_present) { @@ -168,10 +168,12 @@ static void dp_rx_defrag_fraglist_insert(struct dp_peer *peer, unsigned tid, struct dp_rx_tid *rx_tid = &peer->rx_tid[tid]; uint8_t *rx_desc_info; + qdf_assert(frag); qdf_assert(head_addr); qdf_assert(tail_addr); + *all_frag_present = 0; rx_desc_info = qdf_nbuf_data(frag); cur_fragno = dp_rx_frag_get_mpdu_frag_number(rx_desc_info); @@ -181,7 +183,7 @@ static void dp_rx_defrag_fraglist_insert(struct dp_peer *peer, unsigned tid, qdf_nbuf_set_next(*tail_addr, NULL); rx_tid->curr_frag_num = cur_fragno; - goto end; + goto insert_done; } /* In sequence fragment */ @@ -198,7 +200,7 @@ static void dp_rx_defrag_fraglist_insert(struct dp_peer *peer, unsigned tid, if (cur_fragno == head_fragno) { qdf_nbuf_free(frag); - *all_frag_present = 0; + goto insert_fail; } else if (head_fragno > cur_fragno) { qdf_nbuf_set_next(frag, cur); cur = frag; @@ -212,6 +214,12 @@ static void dp_rx_defrag_fraglist_insert(struct dp_peer *peer, unsigned tid, dp_rx_frag_get_mpdu_frag_number( rx_desc_info); } + + if (cur_fragno == head_fragno) { + qdf_nbuf_free(frag); + goto insert_fail; + } + qdf_nbuf_set_next(prev, frag); qdf_nbuf_set_next(frag, cur); } @@ -239,12 +247,15 @@ static void dp_rx_defrag_fraglist_insert(struct dp_peer *peer, unsigned tid, if (!next) { *all_frag_present = 1; - return; + return QDF_STATUS_SUCCESS; } } -end: - *all_frag_present = 0; +insert_done: + return QDF_STATUS_SUCCESS; + +insert_fail: + return QDF_STATUS_E_FAILURE; } @@ -708,7 +719,7 @@ static void dp_rx_defrag_nwifi_to_8023(qdf_nbuf_t nbuf) struct llc_snap_hdr_t *llchdr; struct ethernet_hdr_t *eth_hdr; uint8_t ether_type[2]; - uint16_t fc; + uint16_t fc = 0; union dp_align_mac_addr mac_addr; uint8_t *rx_desc_info = qdf_mem_malloc(RX_PKT_TLVS_LEN); @@ -773,6 +784,14 @@ static void dp_rx_defrag_nwifi_to_8023(qdf_nbuf_t nbuf) break; case IEEE80211_FC1_DIR_DSTODS: + hal_rx_mpdu_get_addr3(rx_desc_info, + &mac_addr.raw[0]); + qdf_mem_copy(eth_hdr->dest_addr, &mac_addr.raw[0], + IEEE80211_ADDR_LEN); + hal_rx_mpdu_get_addr4(rx_desc_info, + &mac_addr.raw[0]); + qdf_mem_copy(eth_hdr->src_addr, &mac_addr.raw[0], + IEEE80211_ADDR_LEN); break; default: @@ -809,7 +828,7 @@ static void dp_rx_defrag_nwifi_to_8023(qdf_nbuf_t nbuf) void *ent_ring_desc, *ent_mpdu_desc_info, *ent_qdesc_addr; void *dst_mpdu_desc_info, *dst_qdesc_addr; qdf_dma_addr_t paddr; - uint32_t nbuf_len, seq_no; + uint32_t nbuf_len, seq_no, dst_ind; uint32_t *mpdu_wrd; void *dst_ring_desc = @@ -835,6 +854,8 @@ static void dp_rx_defrag_nwifi_to_8023(qdf_nbuf_t nbuf) msdu_desc_info = (uint8_t *)msdu0 + RX_MSDU_DETAILS_2_RX_MSDU_DESC_INFO_RX_MSDU_DESC_INFO_DETAILS_OFFSET; + dst_ind = hal_rx_msdu_reo_dst_ind_get(link_desc_va); + qdf_mem_zero(msdu_desc_info, sizeof(struct rx_msdu_desc_info)); HAL_RX_MSDU_DESC_INFO_SET(msdu_desc_info, @@ -844,7 +865,7 @@ static void dp_rx_defrag_nwifi_to_8023(qdf_nbuf_t nbuf) HAL_RX_MSDU_DESC_INFO_SET(msdu_desc_info, MSDU_CONTINUATION, 0x0); HAL_RX_MSDU_DESC_INFO_SET(msdu_desc_info, - REO_DESTINATION_INDICATION, 1); + REO_DESTINATION_INDICATION, dst_ind); HAL_RX_MSDU_DESC_INFO_SET(msdu_desc_info, MSDU_LENGTH, nbuf_len); HAL_RX_MSDU_DESC_INFO_SET(msdu_desc_info, @@ -914,9 +935,8 @@ static void dp_rx_defrag_nwifi_to_8023(qdf_nbuf_t nbuf) qdf_mem_copy(ent_qdesc_addr, dst_qdesc_addr, 8); - /* dst ind */ HAL_RX_FLD_SET(ent_ring_desc, REO_ENTRANCE_RING_5, - REO_DESTINATION_INDICATION, 0x1); + REO_DESTINATION_INDICATION, dst_ind); hal_srng_access_end(soc->hal_soc, hal_srng); @@ -1259,7 +1279,7 @@ static QDF_STATUS dp_rx_defrag_store_fragment(struct dp_soc *soc, * If the earlier sequence was dropped, this will be the fresh start. * Else, continue with next fragment in a given sequence */ - dp_rx_defrag_fraglist_insert(peer, tid, &rx_reorder_array_elem->head, + status = dp_rx_defrag_fraglist_insert(peer, tid, &rx_reorder_array_elem->head, &rx_reorder_array_elem->tail, frag, &all_frag_present); @@ -1269,7 +1289,8 @@ static QDF_STATUS dp_rx_defrag_store_fragment(struct dp_soc *soc, * have to use the next MSDU link descriptor and chain them together * before reinjection */ - if ((fragno == 0) && (rx_reorder_array_elem->head == frag)) { + if ((fragno == 0) && (status == QDF_STATUS_SUCCESS) && + (rx_reorder_array_elem->head == frag)) { status = dp_rx_defrag_save_info_from_ring_desc(ring_desc, peer, tid); diff --git a/dp/wifi3.0/hal_rx.h b/dp/wifi3.0/hal_rx.h index 8d331bd6a1c1..3d286bdffe39 100644 --- a/dp/wifi3.0/hal_rx.h +++ b/dp/wifi3.0/hal_rx.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-2017 The Linux Foundation. All rights reserved. + * Copyright (c) 2016-2018 The Linux Foundation. All rights reserved. * * Permission to use, copy, modify, and/or distribute this software for * any purpose with or without fee is hereby granted, provided that the @@ -359,6 +359,12 @@ enum hal_rx_ret_buf_manager { RX_MSDU_DESC_INFO_0_MSDU_CONTINUATION_OFFSET)) & \ RX_MSDU_DESC_INFO_0_MSDU_CONTINUATION_MASK) +#define HAL_RX_MSDU_REO_DST_IND_GET(msdu_info_ptr) \ + (_HAL_MS((*_OFFSET_TO_WORD_PTR(msdu_info_ptr, \ + RX_MSDU_DESC_INFO_0_REO_DESTINATION_INDICATION_OFFSET)), \ + RX_MSDU_DESC_INFO_0_REO_DESTINATION_INDICATION_MASK, \ + RX_MSDU_DESC_INFO_0_REO_DESTINATION_INDICATION_LSB)) + #define HAL_RX_MSDU_SA_IS_VALID_FLAG_GET(msdu_info_ptr) \ ((*_OFFSET_TO_WORD_PTR(msdu_info_ptr, \ RX_MSDU_DESC_INFO_0_SA_IS_VALID_OFFSET)) & \ @@ -1557,6 +1563,12 @@ hal_rx_mpdu_get_fr_ds(uint8_t *buf) RX_MPDU_INFO_2_MAC_ADDR_AD3_VALID_MASK, \ RX_MPDU_INFO_2_MAC_ADDR_AD3_VALID_LSB)) +#define HAL_RX_MPDU_MAC_ADDR_AD4_VALID_GET(_rx_mpdu_info) \ + (_HAL_MS((*_OFFSET_TO_WORD_PTR(_rx_mpdu_info, \ + RX_MPDU_INFO_2_MAC_ADDR_AD4_VALID_OFFSET)), \ + RX_MPDU_INFO_2_MAC_ADDR_AD4_VALID_MASK, \ + RX_MPDU_INFO_2_MAC_ADDR_AD4_VALID_LSB)) + #define HAL_RX_MPDU_AD1_31_0_GET(_rx_mpdu_info) \ (_HAL_MS((*_OFFSET_TO_WORD_PTR(_rx_mpdu_info, \ RX_MPDU_INFO_15_MAC_ADDR_AD1_31_0_OFFSET)), \ @@ -1593,6 +1605,18 @@ hal_rx_mpdu_get_fr_ds(uint8_t *buf) RX_MPDU_INFO_19_MAC_ADDR_AD3_47_32_MASK, \ RX_MPDU_INFO_19_MAC_ADDR_AD3_47_32_LSB)) +#define HAL_RX_MPDU_AD4_31_0_GET(_rx_mpdu_info) \ + (_HAL_MS((*_OFFSET_TO_WORD_PTR(_rx_mpdu_info, \ + RX_MPDU_INFO_20_MAC_ADDR_AD4_31_0_OFFSET)), \ + RX_MPDU_INFO_20_MAC_ADDR_AD4_31_0_MASK, \ + RX_MPDU_INFO_20_MAC_ADDR_AD4_31_0_LSB)) + +#define HAL_RX_MPDU_AD4_47_32_GET(_rx_mpdu_info) \ + (_HAL_MS((*_OFFSET_TO_WORD_PTR(_rx_mpdu_info, \ + RX_MPDU_INFO_21_MAC_ADDR_AD4_47_32_OFFSET)), \ + RX_MPDU_INFO_21_MAC_ADDR_AD4_47_32_MASK, \ + RX_MPDU_INFO_21_MAC_ADDR_AD4_47_32_LSB)) + /* * hal_rx_mpdu_get_addr1(): API to check get address1 of the mpdu * @@ -1674,8 +1698,8 @@ static inline QDF_STATUS hal_rx_mpdu_get_addr3(uint8_t *buf, uint8_t *mac_addr) { struct __attribute__((__packed__)) hal_addr3 { - uint16_t ad3_15_0; - uint32_t ad3_47_16; + uint32_t ad3_31_0; + uint16_t ad3_47_32; }; struct rx_pkt_tlvs *pkt_tlvs = (struct rx_pkt_tlvs *)buf; @@ -1689,8 +1713,43 @@ QDF_STATUS hal_rx_mpdu_get_addr3(uint8_t *buf, uint8_t *mac_addr) mac_addr_ad3_valid = HAL_RX_MPDU_MAC_ADDR_AD3_VALID_GET(mpdu_info); if (mac_addr_ad3_valid) { - addr->ad3_15_0 = HAL_RX_MPDU_AD3_31_0_GET(mpdu_info); - addr->ad3_47_16 = HAL_RX_MPDU_AD3_47_32_GET(mpdu_info); + addr->ad3_31_0 = HAL_RX_MPDU_AD3_31_0_GET(mpdu_info); + addr->ad3_47_32 = HAL_RX_MPDU_AD3_47_32_GET(mpdu_info); + return QDF_STATUS_SUCCESS; + } + + return QDF_STATUS_E_FAILURE; +} + +/* + * hal_rx_mpdu_get_addr4(): API to get address4 of the mpdu + * in the packet + * + * @buf: pointer to the start of RX PKT TLV header + * @mac_addr: pointer to mac address + * Return: sucess/failure + */ +static inline +QDF_STATUS hal_rx_mpdu_get_addr4(uint8_t *buf, uint8_t *mac_addr) +{ + struct __attribute__((__packed__)) hal_addr4 { + uint32_t ad4_31_0; + uint16_t ad4_47_32; + }; + + struct rx_pkt_tlvs *pkt_tlvs = (struct rx_pkt_tlvs *)buf; + struct rx_mpdu_start *mpdu_start = + &pkt_tlvs->mpdu_start_tlv.rx_mpdu_start; + + struct rx_mpdu_info *mpdu_info = &mpdu_start->rx_mpdu_info_details; + struct hal_addr4 *addr = (struct hal_addr4 *)mac_addr; + uint32_t mac_addr_ad4_valid; + + mac_addr_ad4_valid = HAL_RX_MPDU_MAC_ADDR_AD4_VALID_GET(mpdu_info); + + if (mac_addr_ad4_valid) { + addr->ad4_31_0 = HAL_RX_MPDU_AD4_31_0_GET(mpdu_info); + addr->ad4_47_32 = HAL_RX_MPDU_AD4_47_32_GET(mpdu_info); return QDF_STATUS_SUCCESS; } @@ -1967,6 +2026,31 @@ static inline void hal_rx_msdu_list_get(void *msdu_link_desc, *num_msdus = i; } +/** + * hal_rx_msdu_reo_dst_ind_get: Gets the REO + * destination ring ID from the msdu desc info + * + * @msdu_link_desc : Opaque cookie pointer used by HAL to get to + * the current descriptor + * + * Return: dst_ind (REO destination ring ID) + */ +static inline uint32_t +hal_rx_msdu_reo_dst_ind_get(void *msdu_link_desc) +{ + struct rx_msdu_details *msdu_details; + struct rx_msdu_desc_info *msdu_desc_info; + struct rx_msdu_link *msdu_link = (struct rx_msdu_link *)msdu_link_desc; + uint32_t dst_ind; + + msdu_details = HAL_RX_LINK_DESC_MSDU0_PTR(msdu_link); + + /* The first msdu in the link should exsist */ + msdu_desc_info = HAL_RX_MSDU_DESC_INFO_GET(&msdu_details[0]); + dst_ind = HAL_RX_MSDU_REO_DST_IND_GET(msdu_desc_info); + return dst_ind; +} + /** * hal_rx_reo_buf_paddr_get: Gets the physical address and * cookie from the REO destination ring element @@ -3067,7 +3151,7 @@ uint8_t hal_rx_get_rx_more_frag_bit(uint8_t *buf) * */ static inline -uint8_t hal_rx_get_frame_ctrl_field(uint8_t *buf) +uint16_t hal_rx_get_frame_ctrl_field(uint8_t *buf) { struct rx_pkt_tlvs *pkt_tlvs = hal_rx_get_pkt_tlvs(buf); struct rx_mpdu_info *rx_mpdu_info = hal_rx_get_mpdu_info(pkt_tlvs);