소스 검색

qcacmn: Avoid spin_lock_bh in ipa wlan rx callback

Spin_lock_bh is introduced in ipa wlan rx path by security fix
I0c0bc6e60efa193126ba1e3eca36c5e02f7f76a3,
wlan_ipa_w2i_cb->cdp_peer_state_get->dp_get_peer_state->
dp_peer_find_hash_find->qdf_spin_unlock_bh(&soc->peer_hash_lock),
which make rx pkt aggregation failed, for each rx pkt, once
put into backlog queue, net_rx soft irq is scheduled to handle it.
For each rx msdu, ipa rx work thread, net_rx soft irq and iperf/app
thread are scheduled, which make rx throughput failed to meet KPI.

To avoid spin_lock_bh, don't call cdp_peer_state_get for each rx pkt,
only call 1 time, and save peer auth state in IPA context, for following
pkts, just get peer auth state from IPA context without spin_lock_bh.

Change-Id: I36196bab4626194bda254219c4c44dc4f029cff0
CRs-Fixed: 3098860
Jianmin Zhu 3 년 전
부모
커밋
03f7a9accb
2개의 변경된 파일102개의 추가작업 그리고 5개의 파일을 삭제
  1. 6 2
      ipa/core/inc/wlan_ipa_priv.h
  2. 96 3
      ipa/core/src/wlan_ipa_core.c

+ 6 - 2
ipa/core/inc/wlan_ipa_priv.h

@@ -1,6 +1,6 @@
 /*
  * Copyright (c) 2013-2021 The Linux Foundation. All rights reserved.
- * Copyright (c) 2021 Qualcomm Innovation Center, Inc. All rights reserved.
+ * Copyright (c) 2021-2022 Qualcomm Innovation Center, Inc. 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
@@ -335,7 +335,8 @@ struct wlan_ipa_priv;
  * @interface_lock: Interface lock
  * @ifa_address: Interface address
  * @stats: Interface stats
- * @bssid: BSSID. valid only for sta iface ctx;
+ * @bssid: BSSID. valid only for sta iface ctx
+ * @is_authenticated: is peer authenticated
  */
 struct wlan_ipa_iface_context {
 	struct wlan_ipa_priv *ipa_ctx;
@@ -354,6 +355,7 @@ struct wlan_ipa_iface_context {
 	uint32_t ifa_address;
 	struct wlan_ipa_iface_stats stats;
 	struct qdf_mac_addr bssid;
+	uint8_t is_authenticated;
 };
 
 /**
@@ -402,11 +404,13 @@ struct wlan_ipa_stats {
 /**
  * struct ipa_uc_stas_map - IPA UC assoc station map
  * @is_reserved: STA reserved flag
+ * @is_authenticated: is peer authenticated
  * @mac_addr: Station mac address
  */
 struct ipa_uc_stas_map {
 	bool is_reserved;
 	struct qdf_mac_addr mac_addr;
+	uint8_t is_authenticated;
 };
 
 /**

+ 96 - 3
ipa/core/src/wlan_ipa_core.c

@@ -1063,6 +1063,97 @@ wlan_ipa_eapol_intrabss_fwd_check(struct wlan_ipa_priv *ipa_ctx,
 	return true;
 }
 
+#ifdef MDM_PLATFORM
+static inline void
+wlan_ipa_set_sap_client_auth(struct wlan_ipa_priv *ipa_ctx, uint8_t *peer_mac,
+			     uint8_t is_authenticated)
+{
+	uint8_t idx;
+	struct ipa_uc_stas_map *sta_map;
+
+	for (idx = 0; idx < WLAN_IPA_MAX_STA_COUNT; idx++) {
+		sta_map = &ipa_ctx->assoc_stas_map[idx];
+		if (sta_map->is_reserved &&
+		    qdf_is_macaddr_equal(&sta_map->mac_addr,
+					 (struct qdf_mac_addr *)peer_mac)) {
+			sta_map->is_authenticated = is_authenticated;
+			break;
+		}
+	}
+}
+
+static inline uint8_t
+wlan_ipa_get_sap_client_auth(struct wlan_ipa_priv *ipa_ctx, uint8_t *peer_mac)
+{
+	uint8_t idx;
+	struct ipa_uc_stas_map *sta_map;
+
+	for (idx = 0; idx < WLAN_IPA_MAX_STA_COUNT; idx++) {
+		sta_map = &ipa_ctx->assoc_stas_map[idx];
+		if (sta_map->is_reserved &&
+		    qdf_is_macaddr_equal(&sta_map->mac_addr,
+					 (struct qdf_mac_addr *)peer_mac)) {
+			return sta_map->is_authenticated;
+		}
+	}
+
+	return false;
+}
+
+static inline bool
+wlan_ipa_is_peer_authenticated(ol_txrx_soc_handle dp_soc,
+			       struct wlan_ipa_iface_context *iface,
+			       uint8_t *peer_mac)
+{
+	uint8_t is_authenticated = false;
+
+	if (iface->device_mode == QDF_SAP_MODE) {
+		is_authenticated = wlan_ipa_get_sap_client_auth(iface->ipa_ctx,
+								peer_mac);
+		if (is_authenticated)
+			return is_authenticated;
+		is_authenticated = wlan_ipa_get_peer_state(dp_soc,
+							   iface->session_id,
+							   peer_mac);
+		if (is_authenticated)
+			wlan_ipa_set_sap_client_auth(iface->ipa_ctx,
+						     peer_mac,
+						     true);
+
+	} else if (iface->device_mode == QDF_STA_MODE) {
+		is_authenticated = iface->is_authenticated;
+		if (is_authenticated)
+			return is_authenticated;
+		is_authenticated = wlan_ipa_get_peer_state(dp_soc,
+							   iface->session_id,
+							   peer_mac);
+		if (is_authenticated)
+			iface->is_authenticated = true;
+	}
+
+	return is_authenticated;
+}
+#else /* !MDM_PLATFORM */
+static inline void
+wlan_ipa_set_sap_client_auth(struct wlan_ipa_priv *ipa_ctx, uint8_t *peer_mac,
+			     uint8_t is_authenticated)
+{}
+
+static inline bool
+wlan_ipa_is_peer_authenticated(ol_txrx_soc_handle dp_soc,
+			       struct wlan_ipa_iface_context *iface,
+			       uint8_t *peer_mac)
+{
+	uint8_t is_authenticated = 0;
+
+	is_authenticated = wlan_ipa_get_peer_state(dp_soc,
+						   iface->session_id,
+						   peer_mac);
+
+	return is_authenticated;
+}
+#endif /* MDM_PLATFORM */
+
 /**
  * __wlan_ipa_w2i_cb() - WLAN to IPA callback handler
  * @priv: pointer to private data registered with IPA (we register a
@@ -1161,9 +1252,9 @@ static void __wlan_ipa_w2i_cb(void *priv, qdf_ipa_dp_evt_type_t evt,
 		 * non-EAPOL/WAPI frames to be intrabss forwarded
 		 * or submitted to stack.
 		 */
-		if (!wlan_ipa_get_peer_state(ipa_ctx->dp_soc,
-					     iface_context->session_id,
-					     &peer_mac_addr.bytes[0]) &&
+		if (!wlan_ipa_is_peer_authenticated(ipa_ctx->dp_soc,
+						    iface_context,
+						    &peer_mac_addr.bytes[0]) &&
 		    !is_eapol_wapi) {
 			ipa_err_rl("Non EAPOL/WAPI packet received when peer " QDF_MAC_ADDR_FMT " is unauthorized",
 				   QDF_MAC_ADDR_REF(peer_mac_addr.bytes));
@@ -1640,6 +1731,7 @@ static void wlan_ipa_cleanup_iface(struct wlan_ipa_iface_context *iface_context,
 		QDF_BUG(0);
 	}
 
+	iface_context->is_authenticated = false;
 	iface_context->dev = NULL;
 	iface_context->device_mode = QDF_MAX_NO_OF_MODE;
 	iface_context->session_id = WLAN_IPA_MAX_SESSION;
@@ -2891,6 +2983,7 @@ static QDF_STATUS __wlan_ipa_wlan_evt(qdf_netdev_t net_dev, uint8_t device_mode,
 		}
 
 		qdf_mutex_acquire(&ipa_ctx->event_lock);
+		wlan_ipa_set_sap_client_auth(ipa_ctx, mac_addr, false);
 		if (!ipa_ctx->sap_num_connected_sta) {
 			qdf_mutex_release(&ipa_ctx->event_lock);
 			ipa_debug("%s: Evt: %d, Client already disconnected",