Răsfoiți Sursa

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 ani în urmă
părinte
comite
268579c204
1 a modificat fișierele cu 33 adăugiri și 11 ștergeri
  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(