diff --git a/dp/wifi3.0/dp_rx_defrag.c b/dp/wifi3.0/dp_rx_defrag.c index 5556f84196df..eb11ec302f17 100644 --- a/dp/wifi3.0/dp_rx_defrag.c +++ b/dp/wifi3.0/dp_rx_defrag.c @@ -830,6 +830,38 @@ static void dp_rx_frag_pull_hdr(qdf_nbuf_t nbuf, uint16_t hdrsize) __func__, (uint32_t)qdf_nbuf_len(nbuf), hdrsize); } +/* + * dp_rx_defrag_pn_check(): Check the PN of current fragmented with prev PN + * @msdu: msdu to get the current PN + * @cur_pn128: PN extracted from current msdu + * @prev_pn128: Prev PN + * + * Returns: 0 on success, non zero on failure + */ +static int dp_rx_defrag_pn_check(qdf_nbuf_t msdu, + uint64_t *cur_pn128, uint64_t *prev_pn128) +{ + 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; + int out_of_order = 0; + + 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); + + 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]); + + return out_of_order; +} + /* * dp_rx_construct_fraglist(): Construct a nbuf fraglist * @peer: Pointer to the peer @@ -848,35 +880,30 @@ dp_rx_construct_fraglist(struct dp_peer *peer, int tid, qdf_nbuf_t 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]; + uint64_t cur_pn128[2] = {0, 0}, prev_pn128[2]; int out_of_order = 0; + int index; + int needs_pn_check = 0; prev_pn128[0] = rx_tid->pn128[0]; prev_pn128[1] = rx_tid->pn128[1]; + index = hal_rx_msdu_is_wlan_mcast(msdu) ? dp_sec_mcast : dp_sec_ucast; + if (qdf_likely(peer->security[index].sec_type != cdp_sec_type_none)) + needs_pn_check = 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; + if (qdf_likely(needs_pn_check)) + out_of_order = dp_rx_defrag_pn_check(msdu, + &cur_pn128[0], + &prev_pn128[0]); - 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) + if (qdf_unlikely(out_of_order)) { + dp_info_rl("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]); return QDF_STATUS_E_FAILURE; + } prev_pn128[0] = cur_pn128[0]; prev_pn128[1] = cur_pn128[1];