diff --git a/dp/wifi3.0/dp_rx_defrag.c b/dp/wifi3.0/dp_rx_defrag.c index 1a3c83b95b5d..435e599bf577 100644 --- a/dp/wifi3.0/dp_rx_defrag.c +++ b/dp/wifi3.0/dp_rx_defrag.c @@ -330,6 +330,7 @@ static QDF_STATUS dp_rx_defrag_fraglist_insert(struct dp_peer *peer, unsigned ti rx_desc_info = qdf_nbuf_data(frag); cur_fragno = dp_rx_frag_get_mpdu_frag_number(rx_desc_info); + dp_debug("cur_fragno %d\n", cur_fragno); /* If this is the first fragment */ if (!(*head_addr)) { *head_addr = *tail_addr = frag; @@ -401,6 +402,8 @@ static QDF_STATUS dp_rx_defrag_fraglist_insert(struct dp_peer *peer, unsigned ti if (!next) { *all_frag_present = 1; return QDF_STATUS_SUCCESS; + } else { + /* revisit */ } } @@ -807,8 +810,17 @@ static QDF_STATUS dp_rx_defrag_tkip_demic(const uint8_t *key, */ static void dp_rx_frag_pull_hdr(qdf_nbuf_t nbuf, uint16_t hdrsize) { - qdf_nbuf_pull_head(nbuf, - RX_PKT_TLVS_LEN + hdrsize); + struct rx_pkt_tlvs *rx_pkt_tlv = + (struct rx_pkt_tlvs *)qdf_nbuf_data(nbuf); + struct rx_mpdu_info *rx_mpdu_info_details = + &rx_pkt_tlv->mpdu_start_tlv.rx_mpdu_start.rx_mpdu_info_details; + + dp_debug("pn_31_0 0x%x pn_63_32 0x%x pn_95_64 0x%x pn_127_96 0x%x\n", + rx_mpdu_info_details->pn_31_0, rx_mpdu_info_details->pn_63_32, + rx_mpdu_info_details->pn_95_64, + rx_mpdu_info_details->pn_127_96); + + qdf_nbuf_pull_head(nbuf, RX_PKT_TLVS_LEN + hdrsize); QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_DEBUG, "%s: final pktlen %d .11len %d", @@ -825,15 +837,47 @@ static void dp_rx_frag_pull_hdr(qdf_nbuf_t nbuf, uint16_t hdrsize) * * Returns: None */ -static void -dp_rx_construct_fraglist(struct dp_peer *peer, - qdf_nbuf_t head, uint16_t hdrsize) +static int +dp_rx_construct_fraglist(struct dp_peer *peer, int tid, qdf_nbuf_t head, + uint16_t hdrsize) { qdf_nbuf_t msdu = qdf_nbuf_next(head); qdf_nbuf_t rx_nbuf = msdu; + struct dp_rx_tid *rx_tid = &peer->rx_tid[tid]; uint32_t len = 0; + uint64_t cur_pn128[2], prev_pn128[2]; + int out_of_order = 0; + + prev_pn128[0] = rx_tid->pn128[0]; + prev_pn128[1] = rx_tid->pn128[1]; while (msdu) { + struct rx_pkt_tlvs *rx_pkt_tlv = + (struct rx_pkt_tlvs *)qdf_nbuf_data(msdu); + struct rx_mpdu_info *rx_mpdu_info_details = + &rx_pkt_tlv->mpdu_start_tlv.rx_mpdu_start.rx_mpdu_info_details; + + cur_pn128[0] = rx_mpdu_info_details->pn_31_0; + cur_pn128[0] |= + ((uint64_t)rx_mpdu_info_details->pn_63_32 << 32); + cur_pn128[1] = rx_mpdu_info_details->pn_95_64; + cur_pn128[1] |= + ((uint64_t)rx_mpdu_info_details->pn_127_96 << 32); + + dp_debug("cur_pn128[0] 0x%llx cur_pn128[1] 0x%llx prev_pn128[0] 0x%llx prev_pn128[1] 0x%llx", + cur_pn128[0], cur_pn128[1], + prev_pn128[0], prev_pn128[1]); + if (cur_pn128[1] == prev_pn128[1]) + out_of_order = (cur_pn128[0] <= prev_pn128[0]); + else + out_of_order = (cur_pn128[1] < prev_pn128[1]); + + if (out_of_order) + return QDF_STATUS_E_FAILURE; + + prev_pn128[0] = cur_pn128[0]; + prev_pn128[1] = cur_pn128[1]; + dp_rx_frag_pull_hdr(msdu, hdrsize); len += qdf_nbuf_len(msdu); msdu = qdf_nbuf_next(msdu); @@ -849,6 +893,8 @@ dp_rx_construct_fraglist(struct dp_peer *peer, (uint32_t)qdf_nbuf_len(head), (uint32_t)qdf_nbuf_len(rx_nbuf), (uint32_t)(head->data_len)); + + return QDF_STATUS_SUCCESS; } /** @@ -909,7 +955,7 @@ static void dp_rx_defrag_err(struct dp_vdev *vdev, qdf_nbuf_t nbuf) * Returns: None */ static void -dp_rx_defrag_nwifi_to_8023(struct dp_soc *soc, +dp_rx_defrag_nwifi_to_8023(struct dp_soc *soc, struct dp_peer *peer, int tid, qdf_nbuf_t nbuf, uint16_t hdrsize) { struct llc_snap_hdr_t *llchdr; @@ -918,6 +964,21 @@ dp_rx_defrag_nwifi_to_8023(struct dp_soc *soc, uint16_t fc = 0; union dp_align_mac_addr mac_addr; uint8_t *rx_desc_info = qdf_mem_malloc(RX_PKT_TLVS_LEN); + struct rx_pkt_tlvs *rx_pkt_tlv = + (struct rx_pkt_tlvs *)qdf_nbuf_data(nbuf); + struct rx_mpdu_info *rx_mpdu_info_details = + &rx_pkt_tlv->mpdu_start_tlv.rx_mpdu_start.rx_mpdu_info_details; + struct dp_rx_tid *rx_tid = &peer->rx_tid[tid]; + + dp_debug("head_nbuf pn_31_0 0x%x pn_63_32 0x%x pn_95_64 0x%x pn_127_96 0x%x\n", + rx_mpdu_info_details->pn_31_0, rx_mpdu_info_details->pn_63_32, + rx_mpdu_info_details->pn_95_64, + rx_mpdu_info_details->pn_127_96); + + rx_tid->pn128[0] = rx_mpdu_info_details->pn_31_0; + rx_tid->pn128[0] |= ((uint64_t)rx_mpdu_info_details->pn_63_32 << 32); + rx_tid->pn128[1] = rx_mpdu_info_details->pn_95_64; + rx_tid->pn128[1] |= ((uint64_t)rx_mpdu_info_details->pn_127_96 << 32); if (!rx_desc_info) { QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR, @@ -1000,6 +1061,62 @@ dp_rx_defrag_nwifi_to_8023(struct dp_soc *soc, qdf_mem_free(rx_desc_info); } +#ifdef RX_DEFRAG_DO_NOT_REINJECT +/* + * dp_rx_defrag_deliver(): Deliver defrag packet to stack + * @peer: Pointer to the peer + * @tid: Transmit Identifier + * @head: Nbuf to be delivered + * + * Returns: None + */ +static inline void dp_rx_defrag_deliver(struct dp_peer *peer, + unsigned int tid, + qdf_nbuf_t head) +{ + struct dp_vdev *vdev = peer->vdev; + struct dp_soc *soc = vdev->pdev->soc; + qdf_nbuf_t deliver_list_head = NULL; + qdf_nbuf_t deliver_list_tail = NULL; + uint8_t *rx_tlv_hdr; + + rx_tlv_hdr = qdf_nbuf_data(head); + + QDF_NBUF_CB_RX_VDEV_ID(head) = vdev->vdev_id; + qdf_nbuf_set_tid_val(head, tid); + qdf_nbuf_pull_head(head, RX_PKT_TLVS_LEN); + + DP_RX_LIST_APPEND(deliver_list_head, deliver_list_tail, + head); + dp_rx_deliver_to_stack(soc, vdev, peer, deliver_list_head, + deliver_list_tail); +} + +/* + * dp_rx_defrag_reo_reinject(): Reinject the fragment chain back into REO + * @peer: Pointer to the peer + * @tid: Transmit Identifier + * @head: Buffer to be reinjected back + * + * Reinject the fragment chain back into REO + * + * Returns: QDF_STATUS + */ +static QDF_STATUS dp_rx_defrag_reo_reinject(struct dp_peer *peer, + unsigned int tid, qdf_nbuf_t head) +{ + struct dp_rx_reorder_array_elem *rx_reorder_array_elem; + + rx_reorder_array_elem = peer->rx_tid[tid].array; + + dp_rx_defrag_deliver(peer, tid, head); + rx_reorder_array_elem->head = NULL; + rx_reorder_array_elem->tail = NULL; + dp_rx_return_head_frag_desc(peer, tid); + + return QDF_STATUS_SUCCESS; +} +#else #ifdef WLAN_FEATURE_DP_RX_RING_HISTORY /** * dp_rx_reinject_ring_record_entry() - Record reinject ring history @@ -1235,6 +1352,7 @@ static QDF_STATUS dp_rx_defrag_reo_reinject(struct dp_peer *peer, "%s: reinjection done !", __func__); return QDF_STATUS_SUCCESS; } +#endif /* * dp_rx_defrag(): Defragment the fragment chain @@ -1371,8 +1489,9 @@ static QDF_STATUS dp_rx_defrag(struct dp_peer *peer, unsigned tid, } /* Convert the header to 802.3 header */ - dp_rx_defrag_nwifi_to_8023(soc, frag_list_head, hdr_space); - dp_rx_construct_fraglist(peer, frag_list_head, hdr_space); + dp_rx_defrag_nwifi_to_8023(soc, peer, tid, frag_list_head, hdr_space); + if (dp_rx_construct_fraglist(peer, tid, frag_list_head, hdr_space)) + return QDF_STATUS_E_DEFRAG_ERROR; return QDF_STATUS_SUCCESS; } @@ -1576,9 +1695,13 @@ dp_rx_defrag_store_fragment(struct dp_soc *soc, } /* Check if the fragment is for the same sequence or a different one */ + dp_debug("rx_tid %d", tid); if (rx_reorder_array_elem->head) { + dp_debug("rxseq %d\n", rxseq); if (rxseq != rx_tid->curr_seq_num) { + dp_debug("mismatch cur_seq %d rxseq %d\n", + rx_tid->curr_seq_num, rxseq); /* Drop stored fragments if out of sequence * fragment is received */ @@ -1586,6 +1709,7 @@ dp_rx_defrag_store_fragment(struct dp_soc *soc, DP_STATS_INC(soc, rx.rx_frag_oor, 1); + dp_debug("cur rxseq %d\n", rxseq); /* * The sequence number for this fragment becomes the * new sequence number to be processed @@ -1593,9 +1717,11 @@ dp_rx_defrag_store_fragment(struct dp_soc *soc, rx_tid->curr_seq_num = rxseq; } } else { + dp_debug("cur rxseq %d\n", rxseq); /* Start of a new sequence */ dp_rx_defrag_cleanup(peer, tid); rx_tid->curr_seq_num = rxseq; + /* store PN number also */ } /* diff --git a/dp/wifi3.0/dp_types.h b/dp/wifi3.0/dp_types.h index 5a5fbf174c7c..fd4589449d89 100644 --- a/dp/wifi3.0/dp_types.h +++ b/dp/wifi3.0/dp_types.h @@ -608,6 +608,9 @@ struct dp_rx_tid { uint32_t curr_seq_num; uint32_t curr_frag_num; + /* head PN number */ + uint64_t pn128[2]; + uint32_t defrag_timeout_ms; uint16_t dialogtoken; uint16_t statuscode;