|
@@ -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);
|
|
rx_desc_info = qdf_nbuf_data(frag);
|
|
cur_fragno = dp_rx_frag_get_mpdu_frag_number(rx_desc_info);
|
|
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 this is the first fragment */
|
|
if (!(*head_addr)) {
|
|
if (!(*head_addr)) {
|
|
*head_addr = *tail_addr = frag;
|
|
*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) {
|
|
if (!next) {
|
|
*all_frag_present = 1;
|
|
*all_frag_present = 1;
|
|
return QDF_STATUS_SUCCESS;
|
|
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)
|
|
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,
|
|
QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_DEBUG,
|
|
"%s: final pktlen %d .11len %d",
|
|
"%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
|
|
* 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 msdu = qdf_nbuf_next(head);
|
|
qdf_nbuf_t rx_nbuf = msdu;
|
|
qdf_nbuf_t rx_nbuf = msdu;
|
|
|
|
+ struct dp_rx_tid *rx_tid = &peer->rx_tid[tid];
|
|
uint32_t len = 0;
|
|
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) {
|
|
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);
|
|
dp_rx_frag_pull_hdr(msdu, hdrsize);
|
|
len += qdf_nbuf_len(msdu);
|
|
len += qdf_nbuf_len(msdu);
|
|
msdu = qdf_nbuf_next(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(head),
|
|
(uint32_t)qdf_nbuf_len(rx_nbuf),
|
|
(uint32_t)qdf_nbuf_len(rx_nbuf),
|
|
(uint32_t)(head->data_len));
|
|
(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
|
|
* Returns: None
|
|
*/
|
|
*/
|
|
static void
|
|
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)
|
|
qdf_nbuf_t nbuf, uint16_t hdrsize)
|
|
{
|
|
{
|
|
struct llc_snap_hdr_t *llchdr;
|
|
struct llc_snap_hdr_t *llchdr;
|
|
@@ -918,6 +964,21 @@ dp_rx_defrag_nwifi_to_8023(struct dp_soc *soc,
|
|
uint16_t fc = 0;
|
|
uint16_t fc = 0;
|
|
union dp_align_mac_addr mac_addr;
|
|
union dp_align_mac_addr mac_addr;
|
|
uint8_t *rx_desc_info = qdf_mem_malloc(RX_PKT_TLVS_LEN);
|
|
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) {
|
|
if (!rx_desc_info) {
|
|
QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR,
|
|
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);
|
|
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
|
|
#ifdef WLAN_FEATURE_DP_RX_RING_HISTORY
|
|
/**
|
|
/**
|
|
* dp_rx_reinject_ring_record_entry() - Record reinject 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__);
|
|
"%s: reinjection done !", __func__);
|
|
return QDF_STATUS_SUCCESS;
|
|
return QDF_STATUS_SUCCESS;
|
|
}
|
|
}
|
|
|
|
+#endif
|
|
|
|
|
|
/*
|
|
/*
|
|
* dp_rx_defrag(): Defragment the fragment chain
|
|
* 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 */
|
|
/* 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;
|
|
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 */
|
|
/* 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) {
|
|
if (rx_reorder_array_elem->head) {
|
|
|
|
+ dp_debug("rxseq %d\n", rxseq);
|
|
if (rxseq != rx_tid->curr_seq_num) {
|
|
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
|
|
/* Drop stored fragments if out of sequence
|
|
* fragment is received
|
|
* 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_STATS_INC(soc, rx.rx_frag_oor, 1);
|
|
|
|
|
|
|
|
+ dp_debug("cur rxseq %d\n", rxseq);
|
|
/*
|
|
/*
|
|
* The sequence number for this fragment becomes the
|
|
* The sequence number for this fragment becomes the
|
|
* new sequence number to be processed
|
|
* 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;
|
|
rx_tid->curr_seq_num = rxseq;
|
|
}
|
|
}
|
|
} else {
|
|
} else {
|
|
|
|
+ dp_debug("cur rxseq %d\n", rxseq);
|
|
/* Start of a new sequence */
|
|
/* Start of a new sequence */
|
|
dp_rx_defrag_cleanup(peer, tid);
|
|
dp_rx_defrag_cleanup(peer, tid);
|
|
rx_tid->curr_seq_num = rxseq;
|
|
rx_tid->curr_seq_num = rxseq;
|
|
|
|
+ /* store PN number also */
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
/*
|