Parcourir la source

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
psimha il y a 7 ans
Parent
commit
7e69eaa303
2 fichiers modifiés avec 126 ajouts et 21 suppressions
  1. 36 15
      dp/wifi3.0/dp_rx_defrag.c
  2. 90 6
      dp/wifi3.0/hal_rx.h

+ 36 - 15
dp/wifi3.0/dp_rx_defrag.c

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

+ 90 - 6
dp/wifi3.0/hal_rx.h

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