|
@@ -1031,22 +1031,25 @@ static inline bool dp_rx_adjust_nbuf_len(qdf_nbuf_t nbuf, uint16_t *mpdu_len)
|
|
|
* dp_rx_sg_create() - create a frag_list for MSDUs which are spread across
|
|
|
* multiple nbufs.
|
|
|
* @nbuf: pointer to the first msdu of an amsdu.
|
|
|
- * @rx_tlv_hdr: pointer to the start of RX TLV headers.
|
|
|
- *
|
|
|
*
|
|
|
* This function implements the creation of RX frag_list for cases
|
|
|
* where an MSDU is spread across multiple nbufs.
|
|
|
*
|
|
|
* Return: returns the head nbuf which contains complete frag_list.
|
|
|
*/
|
|
|
-qdf_nbuf_t dp_rx_sg_create(qdf_nbuf_t nbuf, uint8_t *rx_tlv_hdr)
|
|
|
+qdf_nbuf_t dp_rx_sg_create(qdf_nbuf_t nbuf)
|
|
|
{
|
|
|
qdf_nbuf_t parent, frag_list, next = NULL;
|
|
|
uint16_t frag_list_len = 0;
|
|
|
uint16_t mpdu_len;
|
|
|
bool last_nbuf;
|
|
|
|
|
|
- mpdu_len = hal_rx_msdu_start_msdu_len_get(rx_tlv_hdr);
|
|
|
+ /*
|
|
|
+ * Use msdu len got from REO entry descriptor instead since
|
|
|
+ * there is case the RX PKT TLV is corrupted while msdu_len
|
|
|
+ * from REO descriptor is right for non-raw RX scatter msdu.
|
|
|
+ */
|
|
|
+ mpdu_len = QDF_NBUF_CB_RX_PKT_LEN(nbuf);
|
|
|
/*
|
|
|
* this is a case where the complete msdu fits in one single nbuf.
|
|
|
* in this case HW sets both start and end bit and we only need to
|
|
@@ -1881,13 +1884,12 @@ more_data:
|
|
|
if (mpdu_desc_info.mpdu_flags & HAL_MPDU_F_RETRY_BIT)
|
|
|
qdf_nbuf_set_rx_retry_flag(rx_desc->nbuf, 1);
|
|
|
|
|
|
- if (qdf_unlikely(mpdu_desc_info.mpdu_flags &
|
|
|
- HAL_MPDU_F_RAW_AMPDU)) {
|
|
|
+ if (qdf_unlikely(msdu_desc_info.msdu_flags &
|
|
|
+ HAL_MSDU_F_MSDU_CONTINUATION)) {
|
|
|
/* previous msdu has end bit set, so current one is
|
|
|
* the new MPDU
|
|
|
*/
|
|
|
if (is_prev_msdu_last) {
|
|
|
- is_prev_msdu_last = false;
|
|
|
/* Get number of entries available in HW ring */
|
|
|
num_entries_avail =
|
|
|
hal_srng_dst_num_valid(hal_soc,
|
|
@@ -1900,16 +1902,26 @@ more_data:
|
|
|
*/
|
|
|
if (((msdu_desc_info.msdu_len /
|
|
|
(RX_BUFFER_SIZE - RX_PKT_TLVS_LEN) + 1)) >
|
|
|
- num_entries_avail)
|
|
|
+ num_entries_avail) {
|
|
|
+ DP_STATS_INC(
|
|
|
+ soc,
|
|
|
+ rx.msdu_scatter_wait_break,
|
|
|
+ 1);
|
|
|
break;
|
|
|
- } else {
|
|
|
- if (msdu_desc_info.msdu_flags &
|
|
|
- HAL_MSDU_F_LAST_MSDU_IN_MPDU)
|
|
|
- is_prev_msdu_last = true;
|
|
|
+ }
|
|
|
+ is_prev_msdu_last = false;
|
|
|
}
|
|
|
- qdf_nbuf_set_raw_frame(rx_desc->nbuf, 1);
|
|
|
+
|
|
|
}
|
|
|
|
|
|
+ if (qdf_unlikely(mpdu_desc_info.mpdu_flags &
|
|
|
+ HAL_MPDU_F_RAW_AMPDU))
|
|
|
+ qdf_nbuf_set_raw_frame(rx_desc->nbuf, 1);
|
|
|
+
|
|
|
+ if (!is_prev_msdu_last &&
|
|
|
+ msdu_desc_info.msdu_flags & HAL_MSDU_F_LAST_MSDU_IN_MPDU)
|
|
|
+ is_prev_msdu_last = true;
|
|
|
+
|
|
|
/* Pop out the descriptor*/
|
|
|
hal_srng_dst_get_next(hal_soc, hal_ring_hdl);
|
|
|
|
|
@@ -2064,7 +2076,7 @@ done:
|
|
|
* Check if DMA completed -- msdu_done is the last bit
|
|
|
* to be written
|
|
|
*/
|
|
|
- if (qdf_unlikely(!qdf_nbuf_is_raw_frame(nbuf) &&
|
|
|
+ if (qdf_unlikely(!qdf_nbuf_is_rx_chfrag_cont(nbuf) &&
|
|
|
!hal_rx_attn_msdu_done_get(rx_tlv_hdr))) {
|
|
|
dp_err("MSDU DONE failure");
|
|
|
DP_STATS_INC(soc, rx.err.msdu_done_fail, 1);
|
|
@@ -2120,14 +2132,23 @@ done:
|
|
|
qdf_nbuf_set_sa_valid(nbuf, is_sa_vld);
|
|
|
|
|
|
qdf_nbuf_pull_head(nbuf, RX_PKT_TLVS_LEN);
|
|
|
- } else if (qdf_nbuf_is_raw_frame(nbuf)) {
|
|
|
+ } else if (qdf_nbuf_is_rx_chfrag_cont(nbuf)) {
|
|
|
msdu_len = QDF_NBUF_CB_RX_PKT_LEN(nbuf);
|
|
|
- nbuf = dp_rx_sg_create(nbuf, rx_tlv_hdr);
|
|
|
-
|
|
|
- DP_STATS_INC(vdev->pdev, rx_raw_pkts, 1);
|
|
|
- DP_STATS_INC_PKT(peer, rx.raw, 1, msdu_len);
|
|
|
-
|
|
|
+ nbuf = dp_rx_sg_create(nbuf);
|
|
|
next = nbuf->next;
|
|
|
+
|
|
|
+ if (qdf_nbuf_is_raw_frame(nbuf)) {
|
|
|
+ DP_STATS_INC(vdev->pdev, rx_raw_pkts, 1);
|
|
|
+ DP_STATS_INC_PKT(peer, rx.raw, 1, msdu_len);
|
|
|
+ } else {
|
|
|
+ qdf_nbuf_free(nbuf);
|
|
|
+ DP_STATS_INC(soc, rx.err.scatter_msdu, 1);
|
|
|
+ dp_info_rl("scatter msdu len %d, dropped",
|
|
|
+ msdu_len);
|
|
|
+ nbuf = next;
|
|
|
+ dp_peer_unref_del_find_by_id(peer);
|
|
|
+ continue;
|
|
|
+ }
|
|
|
} else {
|
|
|
l2_hdr_offset =
|
|
|
hal_rx_msdu_end_l3_hdr_padding_get(soc->hal_soc,
|