소스 검색

qcacmn: Fix WAPI unencrypted frame error

WAPI cert AP sends rekey frames as unencrypted. Thus
RXDMA will report unencrypted frame error and error
frames are then sent to release ring as configured.
With current implementation, host just drops WAPI
error frames.

To pass WAPI cert case, fix is to deliever unencrypted
WAPI frames to stack.

Change-Id: I6dfd1b5e6958d729ec3da0a0d1f1e6c227b0597f
CRs-Fixed: 2350485
jiad 6 년 전
부모
커밋
268579c204
1개의 변경된 파일33개의 추가작업 그리고 11개의 파일을 삭제
  1. 33 11
      dp/wifi3.0/dp_rx_err.c

+ 33 - 11
dp/wifi3.0/dp_rx_err.c

@@ -758,7 +758,8 @@ dp_rx_null_q_desc_handle(struct dp_soc *soc, qdf_nbuf_t nbuf,
 }
 }
 
 
 /**
 /**
- * dp_rx_err_deliver() - Function to deliver error frames to OS
+ * dp_rx_process_err_unencrypted() - Function to deliver rxdma unencrypted_err
+ *				     frames to OS
  * @soc: core DP main context
  * @soc: core DP main context
  * @nbuf: buffer pointer
  * @nbuf: buffer pointer
  * @rx_tlv_hdr: start of rx tlv header
  * @rx_tlv_hdr: start of rx tlv header
@@ -767,8 +768,8 @@ dp_rx_null_q_desc_handle(struct dp_soc *soc, qdf_nbuf_t nbuf,
  * Return: None
  * Return: None
  */
  */
 static void
 static void
-dp_rx_err_deliver(struct dp_soc *soc, qdf_nbuf_t nbuf, uint8_t *rx_tlv_hdr,
-		  struct dp_peer *peer)
+dp_rx_process_err_unencrypted(struct dp_soc *soc, qdf_nbuf_t nbuf,
+			      uint8_t *rx_tlv_hdr, struct dp_peer *peer)
 {
 {
 	uint32_t pkt_len, l2_hdr_offset;
 	uint32_t pkt_len, l2_hdr_offset;
 	uint16_t msdu_len;
 	uint16_t msdu_len;
@@ -821,6 +822,32 @@ dp_rx_err_deliver(struct dp_soc *soc, qdf_nbuf_t nbuf, uint8_t *rx_tlv_hdr,
 		return;
 		return;
 	}
 	}
 
 
+	/*
+	 * Advance the packet start pointer by total size of
+	 * pre-header TLV's
+	 */
+	qdf_nbuf_pull_head(nbuf, l2_hdr_offset + RX_PKT_TLVS_LEN);
+
+	/*
+	 * WAPI cert AP sends rekey frames as unencrypted.
+	 * Thus RXDMA will report unencrypted frame error.
+	 * To pass WAPI cert case, SW needs to pass unencrypted
+	 * rekey frame to stack.
+	 */
+	if (qdf_nbuf_is_ipv4_wapi_pkt(nbuf)) {
+		qdf_nbuf_cb_update_peer_local_id(nbuf, peer->local_id);
+
+		if (qdf_likely(vdev->osif_rx)) {
+			DP_STATS_INC(peer, rx.to_stack.num, 1);
+			vdev->osif_rx(vdev->osif_vdev, nbuf);
+		} else {
+			qdf_nbuf_free(nbuf);
+			DP_STATS_INC(soc, rx.err.invalid_vdev, 1);
+		}
+
+		return;
+	}
+
 	/* Drop & free packet if mesh mode not enabled */
 	/* Drop & free packet if mesh mode not enabled */
 	if (!vdev->mesh_vdev) {
 	if (!vdev->mesh_vdev) {
 		qdf_nbuf_free(nbuf);
 		qdf_nbuf_free(nbuf);
@@ -828,12 +855,6 @@ dp_rx_err_deliver(struct dp_soc *soc, qdf_nbuf_t nbuf, uint8_t *rx_tlv_hdr,
 		return;
 		return;
 	}
 	}
 
 
-	/*
-	 * Advance the packet start pointer by total size of
-	 * pre-header TLV's
-	 */
-	qdf_nbuf_pull_head(nbuf, (l2_hdr_offset + RX_PKT_TLVS_LEN));
-
 	if (dp_rx_filter_mesh_packets(vdev, nbuf, rx_tlv_hdr)
 	if (dp_rx_filter_mesh_packets(vdev, nbuf, rx_tlv_hdr)
 							== QDF_STATUS_SUCCESS) {
 							== QDF_STATUS_SUCCESS) {
 		QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_INFO_MED,
 		QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_INFO_MED,
@@ -1330,8 +1351,9 @@ done:
 
 
 				switch (wbm_err_info.rxdma_err_code) {
 				switch (wbm_err_info.rxdma_err_code) {
 				case HAL_RXDMA_ERR_UNENCRYPTED:
 				case HAL_RXDMA_ERR_UNENCRYPTED:
-					dp_rx_err_deliver(soc, nbuf,
-							  rx_tlv_hdr, peer);
+					dp_rx_process_err_unencrypted(
+							soc, nbuf,
+							rx_tlv_hdr, peer);
 					nbuf = next;
 					nbuf = next;
 					if (peer)
 					if (peer)
 						dp_peer_unref_del_find_by_id(
 						dp_peer_unref_del_find_by_id(