Parcourir la source

qcacld-3.0: Remove sta_info usage from softap xmit

Remove sta_info usage from _hard_xmit SAP API. The APIs are
taking/releasing a lock to access sta_info and adds lots of cpu cycles.
Replace it by accessing dp_peer from DP layer and checking for its
state.
Some of the existing stats being updated in sta_info during TX packet
path will be updated on demand using CDP APIs and stats obtained from FW.

CRs-Fixed: 3059244
Change-Id: Id33d7271244687e616ce08b80e1c540ec9b42084
Mohit Khanna il y a 3 ans
Parent
commit
6f11bb125a
1 fichiers modifiés avec 172 ajouts et 161 suppressions
  1. 172 161
      core/hdd/src/wlan_hdd_softap_tx_rx.c

+ 172 - 161
core/hdd/src/wlan_hdd_softap_tx_rx.c

@@ -551,54 +551,105 @@ int hdd_softap_inspect_dhcp_packet(struct hdd_adapter *adapter,
 static void hdd_softap_notify_dhcp_ind(void *context, struct sk_buff *netbuf)
 {
 }
+#endif /* SAP_DHCP_FW_IND */
+
+#if defined(IPA_OFFLOAD)
+static
+struct sk_buff *hdd_sap_skb_orphan(struct hdd_adapter *adapter,
+				   struct sk_buff *skb)
+{
+	if (!qdf_nbuf_ipa_owned_get(skb)) {
+		skb = hdd_skb_orphan(adapter, skb);
+	} else {
+		/*
+		 * Clear the IPA ownership after check it to avoid ipa_free_skb
+		 * is called when Tx completed for intra-BSS Tx packets
+		 */
+		qdf_nbuf_ipa_owned_clear(skb);
+	}
+	return skb;
+}
+#else
+static inline
+struct sk_buff *hdd_sap_skb_orphan(struct hdd_adapter *adapter,
+				   struct sk_buff *skb)
+{
+	return hdd_skb_orphan(adapter, skb);
+}
+#endif /* IPA_OFFLOAD */
+
+#ifdef QCA_LL_LEGACY_TX_FLOW_CONTROL
+static
+void hdd_softap_get_tx_resource(struct hdd_adapter *adapter,
+				struct sk_buff *skb)
+{
+	if (QDF_NBUF_CB_GET_IS_BCAST(skb) || QDF_NBUF_CB_GET_IS_MCAST(skb))
+		hdd_get_tx_resource(adapter, &adapter->mac_addr,
+				    WLAN_SAP_HDD_TX_FLOW_CONTROL_OS_Q_BLOCK_TIME);
+	else
+		hdd_get_tx_resource(adapter, (struct qdf_mac_addr *)skb->data,
+				    WLAN_SAP_HDD_TX_FLOW_CONTROL_OS_Q_BLOCK_TIME);
+}
+#else
+#define hdd_softap_get_tx_resource(adapter, skb)
 #endif
 
-/**
- * __hdd_softap_hard_start_xmit() - Transmit a frame
- * @skb: pointer to OS packet (sk_buff)
- * @dev: pointer to network device
- *
- * Function registered with the Linux OS for transmitting
- * packets. This version of the function directly passes
- * the packet to Transport Layer.
- * In case of any packet drop or error, log the error with
- * INFO HIGH/LOW/MEDIUM to avoid excessive logging in kmsg.
- *
- * Return: None
- */
-static void __hdd_softap_hard_start_xmit(struct sk_buff *skb,
-					 struct net_device *dev)
+static QDF_STATUS hdd_softap_validate_peer_state(struct hdd_adapter *adapter,
+						 struct sk_buff *skb)
 {
-	sme_ac_enum_type ac = SME_AC_BE;
-	struct hdd_adapter *adapter = (struct hdd_adapter *) netdev_priv(dev);
-	struct hdd_ap_ctx *ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(adapter);
-	struct hdd_context *hdd_ctx = adapter->hdd_ctx;
 	struct qdf_mac_addr *dest_mac_addr, *mac_addr;
 	static struct qdf_mac_addr bcast_mac_addr = QDF_MAC_ADDR_BCAST_INIT;
-	void *soc = cds_get_context(QDF_MODULE_ID_SOC);
-	uint32_t num_seg;
-	struct hdd_station_info *sta_info = NULL;
-	struct hdd_tx_rx_stats *stats = &adapter->hdd_stats.tx_rx_stats;
-	int cpu = qdf_get_smp_processor_id();
 
-	++stats->per_cpu[cpu].tx_called;
-	stats->cont_txtimeout_cnt = 0;
+	dest_mac_addr = (struct qdf_mac_addr *)skb->data;
 
-	/* Prevent this function from being called during SSR since TL
-	 * context may not be reinitialized at this time which may
-	 * lead to a crash.
-	 */
-	if (cds_is_driver_transitioning()) {
-		QDF_TRACE_DEBUG_RL(
-			  QDF_MODULE_ID_HDD_SAP_DATA,
-			  "%s: Recovery/(Un)load in Progress. Ignore!!!",
-			  __func__);
-		goto drop_pkt;
+	if (QDF_NBUF_CB_GET_IS_MCAST(skb))
+		mac_addr = &bcast_mac_addr;
+	else
+		mac_addr = dest_mac_addr;
+
+	if (!QDF_NBUF_CB_GET_IS_BCAST(skb) && !QDF_NBUF_CB_GET_IS_MCAST(skb)) {
+		/* for a unicast frame */
+		enum ol_txrx_peer_state peer_state;
+		void *soc = cds_get_context(QDF_MODULE_ID_SOC);
+
+		QDF_BUG(soc);
+		peer_state = cdp_peer_state_get(soc, adapter->vdev_id,
+						mac_addr->bytes);
+
+		if (peer_state == OL_TXRX_PEER_STATE_INVALID) {
+			hdd_sapd_debug_rl("Failed to find right station");
+			return QDF_STATUS_E_FAILURE;
+		}
+
+		if (peer_state != OL_TXRX_PEER_STATE_CONN &&
+		    peer_state != OL_TXRX_PEER_STATE_AUTH) {
+			hdd_sapd_debug_rl("Station not connected yet");
+			return QDF_STATUS_E_FAILURE;
+		}
+
+		if (peer_state == OL_TXRX_PEER_STATE_CONN) {
+			if (ntohs(skb->protocol) != HDD_ETHERTYPE_802_1_X) {
+				hdd_sapd_debug_rl("NON-EAPOL packet in non-Authenticated state");
+				return QDF_STATUS_E_FAILURE;
+			}
+		}
 	}
+	return QDF_STATUS_SUCCESS;
+}
 
-	if (hdd_ctx->hdd_wlan_suspended) {
+static
+QDF_STATUS hdd_softap_validate_driver_state(struct hdd_adapter *adapter)
+{
+	struct hdd_ap_ctx *ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(adapter);
+
+	if (qdf_unlikely(cds_is_driver_transitioning())) {
+		hdd_err_rl("driver is transitioning, drop pkt");
+		return QDF_STATUS_E_ABORTED;
+	}
+
+	if (qdf_unlikely(adapter->hdd_ctx->hdd_wlan_suspended)) {
 		hdd_err_rl("Device is system suspended, drop pkt");
-		goto drop_pkt;
+		return QDF_STATUS_E_ABORTED;
 	}
 
 	/*
@@ -609,168 +660,132 @@ static void __hdd_softap_hard_start_xmit(struct sk_buff *skb,
 	 * SAP starts Tx only after the BSS START is
 	 * done.
 	 */
-	if (ap_ctx->dfs_cac_block_tx)
-		goto drop_pkt;
+	if (qdf_unlikely(ap_ctx->dfs_cac_block_tx)) {
+		hdd_sapd_debug_rl("In CAC WAIT state, drop pkt");
+		return QDF_STATUS_E_ABORTED;
+	}
 
-	if (ap_ctx->hostapd_state.bss_state != BSS_START) {
-		QDF_TRACE_DEBUG_RL(
-			QDF_MODULE_ID_HDD_SAP_DATA,
-			"%s: SAP is not in START state (%d). Ignore!!!",
-			__func__, ap_ctx->hostapd_state.bss_state);
-		goto drop_pkt;
+	if (qdf_unlikely(ap_ctx->hostapd_state.bss_state != BSS_START)) {
+		hdd_sapd_debug_rl("SAP is not in START state (%d). Ignore!!!",
+				  ap_ctx->hostapd_state.bss_state);
+		return QDF_STATUS_E_ABORTED;
 	}
 
-	/*
-	 * If a transmit function is not registered, drop packet
-	 */
-	if (!adapter->tx_fn) {
-		QDF_TRACE_DEBUG_RL(
-			 QDF_MODULE_ID_HDD_SAP_DATA,
-			 "%s: TX function not registered by the data path",
-			 __func__);
-		goto drop_pkt;
+	if (qdf_unlikely(!adapter->tx_fn)) {
+		hdd_sapd_debug_rl("TX function not registered by the data path");
+		return QDF_STATUS_E_ABORTED;
 	}
 
-	wlan_hdd_classify_pkt(skb);
+	return QDF_STATUS_SUCCESS;
+}
 
-	dest_mac_addr = (struct qdf_mac_addr *)skb->data;
+static void hdd_softap_config_tx_pkt_tracing(struct hdd_adapter *adapter,
+					     struct sk_buff *skb)
+{
+	if (hdd_is_current_high_throughput(adapter->hdd_ctx))
+		return;
 
-	/* In case of mcast, fetch the bcast sta_info. Else use the pkt addr */
-	if (QDF_NBUF_CB_GET_IS_MCAST(skb))
-		mac_addr = &bcast_mac_addr;
-	else
-		mac_addr = dest_mac_addr;
+	QDF_NBUF_CB_TX_PACKET_TRACK(skb) = QDF_NBUF_TX_PKT_DATA_TRACK;
+	QDF_NBUF_UPDATE_TX_PKT_COUNT(skb, QDF_NBUF_TX_PKT_HDD);
+	qdf_dp_trace_set_track(skb, QDF_TX);
+	DPTRACE(qdf_dp_trace(skb, QDF_DP_TRACE_HDD_TX_PACKET_PTR_RECORD,
+			     QDF_TRACE_DEFAULT_PDEV_ID, qdf_nbuf_data_addr(skb),
+			     sizeof(qdf_nbuf_data(skb)),
+			     QDF_TX));
+}
 
-	sta_info = hdd_get_sta_info_by_mac(&adapter->sta_info_list,
-					   mac_addr->bytes,
-					   STA_INFO_SOFTAP_HARD_START_XMIT);
+/**
+ * __hdd_softap_hard_start_xmit() - Transmit a frame
+ * @skb: pointer to OS packet (sk_buff)
+ * @dev: pointer to network device
+ *
+ * Function registered with the Linux OS for transmitting
+ * packets. This version of the function directly passes
+ * the packet to Datapath Layer.
+ * In case of any error, drop the packet.
+ *
+ * Return: None
+ */
+static void __hdd_softap_hard_start_xmit(struct sk_buff *skb,
+					 struct net_device *dev)
+{
+	sme_ac_enum_type ac = SME_AC_BE;
+	struct hdd_adapter *adapter = (struct hdd_adapter *)netdev_priv(dev);
+	struct hdd_context *hdd_ctx = adapter->hdd_ctx;
+	struct qdf_mac_addr *dest_mac_addr;
+	void *soc = cds_get_context(QDF_MODULE_ID_SOC);
+	uint32_t num_seg;
+	struct hdd_tx_rx_stats *stats = &adapter->hdd_stats.tx_rx_stats;
+	int cpu = qdf_get_smp_processor_id();
 
-	if (!QDF_NBUF_CB_GET_IS_BCAST(skb) && !QDF_NBUF_CB_GET_IS_MCAST(skb)) {
-		if (!sta_info) {
-			QDF_TRACE_DEBUG_RL(QDF_MODULE_ID_HDD_SAP_DATA,
-					   "%s: Failed to find right station",
-					   __func__);
-			goto drop_pkt;
-		}
+	dest_mac_addr = (struct qdf_mac_addr *)skb->data;
+	++stats->per_cpu[cpu].tx_called;
+	stats->cont_txtimeout_cnt = 0;
 
-		if (sta_info->is_deauth_in_progress) {
-			QDF_TRACE_DEBUG_RL(
-				  QDF_MODULE_ID_HDD_SAP_DATA,
-				  "%s: STA " QDF_MAC_ADDR_FMT
-				  "deauth in progress", __func__,
-				  QDF_MAC_ADDR_REF(sta_info->sta_mac.bytes));
-			goto drop_pkt;
-		}
+	if (QDF_IS_STATUS_ERROR(hdd_softap_validate_driver_state(adapter)))
+		goto drop_pkt;
 
-		if (sta_info->peer_state != OL_TXRX_PEER_STATE_CONN &&
-		    sta_info->peer_state != OL_TXRX_PEER_STATE_AUTH) {
-			QDF_TRACE_DEBUG_RL(
-				QDF_MODULE_ID_HDD_SAP_DATA,
-				"%s: Station not connected yet", __func__);
-			goto drop_pkt;
-		}
+	wlan_hdd_classify_pkt(skb);
 
-		if (sta_info->peer_state == OL_TXRX_PEER_STATE_CONN) {
-			if (ntohs(skb->protocol) != HDD_ETHERTYPE_802_1_X) {
-				QDF_TRACE_DEBUG_RL(
-					  QDF_MODULE_ID_HDD_SAP_DATA,
-					  "%s: NON-EAPOL packet in non-Authenticated state",
-					  __func__);
-				goto drop_pkt;
-			}
-		}
-	}
+	if (QDF_IS_STATUS_ERROR(hdd_softap_validate_peer_state(adapter, skb)))
+		goto drop_pkt;
 
-	if (QDF_NBUF_CB_GET_IS_BCAST(skb) || QDF_NBUF_CB_GET_IS_MCAST(skb))
-		hdd_get_tx_resource(
-				adapter, &adapter->mac_addr,
-				WLAN_SAP_HDD_TX_FLOW_CONTROL_OS_Q_BLOCK_TIME);
-	else
-		hdd_get_tx_resource(
-				adapter, dest_mac_addr,
-				WLAN_SAP_HDD_TX_FLOW_CONTROL_OS_Q_BLOCK_TIME);
+	hdd_softap_get_tx_resource(adapter, skb);
 
 	/* Get TL AC corresponding to Qdisc queue index/AC. */
 	ac = hdd_qdisc_ac_to_tl_ac[skb->queue_mapping];
 	++stats->per_cpu[cpu].tx_classified_ac[ac];
 
-#if defined(IPA_OFFLOAD)
-	if (!qdf_nbuf_ipa_owned_get(skb)) {
-#endif
-
-		skb = hdd_skb_orphan(adapter, skb);
-		if (!skb)
-			goto drop_pkt_accounting;
+	skb = hdd_sap_skb_orphan(adapter, skb);
+	if (!skb)
+		goto drop_pkt_accounting;
 
-#if defined(IPA_OFFLOAD)
-	} else {
-		/*
-		 * Clear the IPA ownership after check it to avoid ipa_free_skb
-		 * is called when Tx completed for intra-BSS Tx packets
-		 */
-		qdf_nbuf_ipa_owned_clear(skb);
-	}
-#endif
 
-	/*
-	 * Add SKB to internal tracking table before further processing
-	 * in WLAN driver.
-	 */
 	qdf_net_buf_debug_acquire_skb(skb, __FILE__, __LINE__);
 
 	adapter->stats.tx_bytes += skb->len;
 
-	if (sta_info) {
-		sta_info->tx_bytes += skb->len;
-
-		if (qdf_nbuf_is_tso(skb)) {
-			num_seg = qdf_nbuf_get_tso_num_seg(skb);
-			adapter->stats.tx_packets += num_seg;
-			sta_info->tx_packets += num_seg;
-		} else {
-			++adapter->stats.tx_packets;
-			sta_info->tx_packets++;
-			hdd_ctx->no_tx_offload_pkt_cnt++;
-		}
-		sta_info->last_tx_rx_ts = qdf_system_ticks();
+	if (qdf_nbuf_is_tso(skb)) {
+		num_seg = qdf_nbuf_get_tso_num_seg(skb);
+		adapter->stats.tx_packets += num_seg;
+	} else {
+		++adapter->stats.tx_packets;
+		hdd_ctx->no_tx_offload_pkt_cnt++;
 	}
 
 	QDF_NBUF_CB_TX_EXTRA_FRAG_FLAGS_NOTIFY_COMP(skb) = 0;
 
-	hdd_softap_inspect_dhcp_packet(adapter, skb, QDF_TX);
-	hdd_softap_inspect_tx_eap_pkt(adapter, skb, false);
+	if (qdf_unlikely(QDF_NBUF_CB_GET_PACKET_TYPE(skb) ==
+			 QDF_NBUF_CB_PACKET_TYPE_DHCP))
+		hdd_softap_inspect_dhcp_packet(adapter, skb, QDF_TX);
 
-	hdd_event_eapol_log(skb, QDF_TX);
-	QDF_NBUF_CB_TX_PACKET_TRACK(skb) = QDF_NBUF_TX_PKT_DATA_TRACK;
-	QDF_NBUF_UPDATE_TX_PKT_COUNT(skb, QDF_NBUF_TX_PKT_HDD);
-	qdf_dp_trace_set_track(skb, QDF_TX);
-	DPTRACE(qdf_dp_trace(skb, QDF_DP_TRACE_HDD_TX_PACKET_PTR_RECORD,
-			QDF_TRACE_DEFAULT_PDEV_ID, qdf_nbuf_data_addr(skb),
-			sizeof(qdf_nbuf_data(skb)),
-			QDF_TX));
+	if (qdf_unlikely(QDF_NBUF_CB_GET_PACKET_TYPE(skb) ==
+			 QDF_NBUF_CB_PACKET_TYPE_EAPOL)) {
+		hdd_softap_inspect_tx_eap_pkt(adapter, skb, false);
+		hdd_event_eapol_log(skb, QDF_TX);
+	}
+
+	hdd_softap_config_tx_pkt_tracing(adapter, skb);
 
 	/* check whether need to linearize skb, like non-linear udp data */
 	if (hdd_skb_nontso_linearize(skb) != QDF_STATUS_SUCCESS) {
-		QDF_TRACE_DEBUG_RL(QDF_MODULE_ID_HDD_DATA,
-				   "%s: skb %pK linearize failed. drop the pkt",
-				   __func__, skb);
+		hdd_sapd_debug_rl("skb %pK linearize failed. drop the pkt",
+				  skb);
 		++stats->per_cpu[cpu].tx_dropped_ac[ac];
 		goto drop_pkt_and_release_skb;
 	}
 
 	if (adapter->tx_fn(soc, adapter->vdev_id, (qdf_nbuf_t)skb)) {
-		QDF_TRACE_DEBUG_RL(QDF_MODULE_ID_HDD_SAP_DATA,
-				   "%s: Failed to send packet to txrx for sta: "
-				   QDF_MAC_ADDR_FMT, __func__,
-				   QDF_MAC_ADDR_REF(dest_mac_addr->bytes));
+		hdd_sapd_debug_rl("Failed to send packet to txrx for sta: "
+				  QDF_MAC_ADDR_FMT,
+				  QDF_MAC_ADDR_REF(dest_mac_addr->bytes));
 		++stats->per_cpu[cpu].tx_dropped_ac[ac];
 		goto drop_pkt_and_release_skb;
 	}
+
 	netif_trans_update(dev);
 
 	wlan_hdd_sar_unsolicited_timer_start(hdd_ctx);
-	hdd_put_sta_info_ref(&adapter->sta_info_list, &sta_info, true,
-			     STA_INFO_SOFTAP_HARD_START_XMIT);
 
 	return;
 
@@ -781,11 +796,7 @@ drop_pkt:
 			      QDF_DP_TRACE_DROP_PACKET_RECORD, 0,
 			      QDF_TX);
 	kfree_skb(skb);
-
 drop_pkt_accounting:
-	if (sta_info)
-		hdd_put_sta_info_ref(&adapter->sta_info_list, &sta_info, true,
-				     STA_INFO_SOFTAP_HARD_START_XMIT);
 	++adapter->stats.tx_dropped;
 	++stats->per_cpu[cpu].tx_dropped;
 }