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
This commit is contained in:
psimha 2018-01-08 16:35:26 -08:00 • committed by snandini
commit 7e69eaa303
2 changed files with 126 additions and 21 deletions

View file

@ -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);

View file

@ -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);