Browse Source

qcacld-3.0: Select IPA TX pipe based on connection details

This change is one part of patch series to address IPA TX pipe
selection on sdxpinn platform, which is attached with 11BE/WiFi-7
capable chipset. One of the typical user scenarios are the SBS/HBS
configuration supported by the WiFi chipset.

From WLAN point of view, a pipe stands for a pair of TX and TX
completion ring resources. Starting from DBS capable chipset on
SDX platforms, two pipes are allocated for IPA usage, which are the
primary pipe and the alternate pipe. By design, the primary pipe
is used for 5 GHz/6 GHz connection while the alternate pipe is
for 2 GHz connection. Due to different throughput requirements
between two bands and memory saving considerations, two pipes are
initialized with different ring sizes as well as number of buffers
available, where the primary pipe has larger ring sizes as well as
number of TX buffers.

Starting from 11be/WiFi-7 chipset, SBS/HBS features are supported.
Take SAP-SAP concurrencies for instance, SAP1 can be configured to
run with channel 36 on 5 GHz while SAP2 can be configured to run with
channel 149 on 5 GHz or even in the 6 GHz band. With legacy DBS solution,
both SAP1 and SAP2 will use the primary pipe, which in turns TX
starvations are observed on the SAP which has higher phyrate.

To resolve such TX starvation issue, this change is to properly
select TX pipes for interfaces that are possible to be run
on 2 GHz/5 GHz/6 GHz bands but with below considerations being
considered as of the implementation time.
a. 3 home channels are not possible.
b. at same time, only two bands are possible.
c. two 11be SAP concurrencies are not possible.
d. 11be 320 MHz is only possible for single STA or single SAP.

This means that at one time with a maximum of 4 interfaces,
there must be two interfaces with same frequency.

Hence this change properly selects the TX pipe between the
primary pipe and the alternate pipe for all concurrencies that are
supported.

Change-Id: I60453ce0dae5a67f1af9304beeebaab9189c6896
CRs-Fixed: 3599453
Jia Ding 1 year ago
parent
commit
c1976f41a1

+ 22 - 1
core/hdd/inc/wlan_hdd_ipa.h

@@ -1,6 +1,6 @@
 /*
  * Copyright (c) 2013-2019 The Linux Foundation. All rights reserved.
- * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
+ * Copyright (c) 2022-2023 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
@@ -52,6 +52,20 @@ void hdd_ipa_send_nbuf_to_network(qdf_nbuf_t nbuf, qdf_netdev_t dev);
  */
 void hdd_ipa_set_mcc_mode(bool mcc_mode);
 
+/**
+ * hdd_ipa_get_tx_pipe() - Get tx pipe for the new connection
+ * @hdd_ctx: pointer to hdd_context
+ * @link: pointer to struct wlan_hdd_link_info
+ * @tx_pipe: boolean output param to store which pipe to use for @link.
+ *	     false is the primary tx pipe and true is the alternate tx pipe.
+ *
+ * Return: QDF_STATUS_SUCCESS for success, and otherwise for failure scenarios.
+ *
+ */
+QDF_STATUS hdd_ipa_get_tx_pipe(struct hdd_context *hdd_ctx,
+			       struct wlan_hdd_link_info *link,
+			       bool *tx_pipe);
+
 #else
 static inline
 void hdd_ipa_send_nbuf_to_network(qdf_nbuf_t skb, qdf_netdev_t dev)
@@ -62,5 +76,12 @@ static inline void hdd_ipa_set_mcc_mode(bool mcc_mode)
 {
 }
 
+static inline QDF_STATUS
+hdd_ipa_get_tx_pipe(struct hdd_context *hdd_ctx,
+		    struct wlan_hdd_link_info *link,
+		    bool *tx_pipe)
+{
+	return QDF_STATUS_SUCCESS;
+}
 #endif
 #endif /* HDD_IPA_H__ */

+ 30 - 0
core/hdd/src/wlan_hdd_cfg80211.c

@@ -27929,6 +27929,36 @@ hdd_convert_cfgdot11mode_to_80211mode(enum csr_cfgdot11mode mode)
 	}
 }
 
+enum qca_wlan_802_11_mode
+hdd_convert_phymode_to_80211mode(eCsrPhyMode mode)
+{
+	switch (mode) {
+	case eCSR_DOT11_MODE_11a:
+		return QCA_WLAN_802_11_MODE_11A;
+	case eCSR_DOT11_MODE_11b:
+		return QCA_WLAN_802_11_MODE_11B;
+	case eCSR_DOT11_MODE_11g:
+	case eCSR_DOT11_MODE_11g_ONLY:
+		return QCA_WLAN_802_11_MODE_11G;
+	case eCSR_DOT11_MODE_11n:
+	case eCSR_DOT11_MODE_11n_ONLY:
+		return QCA_WLAN_802_11_MODE_11N;
+	case eCSR_DOT11_MODE_11ac:
+	case eCSR_DOT11_MODE_11ac_ONLY:
+		return QCA_WLAN_802_11_MODE_11AC;
+	case eCSR_DOT11_MODE_11ax:
+	case eCSR_DOT11_MODE_11ax_ONLY:
+		return QCA_WLAN_802_11_MODE_11AX;
+	case eCSR_DOT11_MODE_11be:
+	case eCSR_DOT11_MODE_11be_ONLY:
+		return QCA_WLAN_802_11_MODE_11BE;
+	case eCSR_DOT11_MODE_abg:
+	case eCSR_DOT11_MODE_AUTO:
+	default:
+		return QCA_WLAN_802_11_MODE_INVALID;
+	}
+}
+
 bool hdd_is_legacy_connection(struct wlan_hdd_link_info *link_info)
 {
 	struct hdd_station_ctx *sta_ctx;

+ 10 - 0
core/hdd/src/wlan_hdd_cfg80211.h

@@ -927,6 +927,16 @@ hdd_latency_level_event_handler_cb(const void *event_data,
 enum qca_wlan_802_11_mode
 hdd_convert_cfgdot11mode_to_80211mode(enum csr_cfgdot11mode mode);
 
+/**
+ * hdd_convert_phymode_to_80211mode() - Function to convert eCsrPhyMode
+ *					to 80211 mode
+ * @mode: eCsrPhyMode
+ *
+ * Return: 80211 mode
+ */
+enum qca_wlan_802_11_mode
+hdd_convert_phymode_to_80211mode(eCsrPhyMode mode);
+
 /**
  * hdd_send_update_owe_info_event - Send update OWE info event
  * @adapter: Pointer to adapter

+ 150 - 1
core/hdd/src/wlan_hdd_ipa.c

@@ -26,7 +26,7 @@
 /* Include Files */
 #include <wlan_hdd_includes.h>
 #include <wlan_hdd_ipa.h>
-#include "wlan_policy_mgr_api.h"
+#include "wlan_policy_mgr_ucfg.h"
 #include "wlan_ipa_ucfg_api.h"
 #include <wlan_hdd_softap_tx_rx.h>
 #include <linux/inetdevice.h>
@@ -40,6 +40,21 @@
 #include "wlan_dp_ucfg_api.h"
 
 #ifdef IPA_OFFLOAD
+
+/**
+ * struct hdd_ipa_connection_info - connectio info for IPA component
+ * @vdev_id: vdev id
+ * @ch_freq: channel frequency
+ * @ch_width: channel width
+ * @wlan_80211_mode: enum qca_wlan_802_11_mode
+ */
+struct hdd_ipa_connection_info {
+	uint8_t vdev_id;
+	qdf_freq_t ch_freq;
+	enum phy_ch_width ch_width;
+	enum qca_wlan_802_11_mode wlan_80211_mode;
+};
+
 #if (defined(QCA_CONFIG_SMP) && defined(PF_WAKE_UP_IDLE)) ||\
 	IS_ENABLED(CONFIG_SCHED_WALT)
 /**
@@ -287,4 +302,138 @@ void hdd_ipa_set_mcc_mode(bool mcc_mode)
 
 	ucfg_ipa_set_mcc_mode(hdd_ctx->pdev, mcc_mode);
 }
+
+#ifdef IPA_WDI3_TX_TWO_PIPES
+static void
+hdd_ipa_fill_sta_connection_info(struct wlan_hdd_link_info *link,
+				 struct hdd_ipa_connection_info *conn)
+{
+	struct hdd_station_ctx *ctx = WLAN_HDD_GET_STATION_CTX_PTR(link);
+
+	conn->ch_freq = ctx->conn_info.chan_freq;
+	conn->ch_width = ctx->conn_info.ch_width;
+	conn->wlan_80211_mode = hdd_convert_cfgdot11mode_to_80211mode(
+			ctx->conn_info.dot11mode);
+}
+
+static void
+hdd_ipa_fill_sap_connection_info(struct wlan_hdd_link_info *link,
+				 struct hdd_ipa_connection_info *conn)
+{
+	struct hdd_ap_ctx *ctx = WLAN_HDD_GET_AP_CTX_PTR(link);
+
+	conn->ch_freq = ctx->operating_chan_freq;
+	conn->ch_width = ctx->sap_config.ch_params.ch_width;
+	conn->wlan_80211_mode = hdd_convert_phymode_to_80211mode(
+			ctx->sap_config.SapHw_mode);
+}
+
+static void hdd_ipa_fill_connection_info(struct wlan_hdd_link_info *link,
+					 struct hdd_ipa_connection_info *conn)
+{
+	struct hdd_adapter *adapter = link->adapter;
+
+	conn->vdev_id = link->vdev_id;
+
+	if (adapter->device_mode == QDF_STA_MODE)
+		hdd_ipa_fill_sta_connection_info(link, conn);
+	else if (adapter->device_mode == QDF_SAP_MODE)
+		hdd_ipa_fill_sap_connection_info(link, conn);
+}
+
+static QDF_STATUS
+hdd_ipa_get_tx_pipe_multi_conn(struct hdd_context *hdd_ctx,
+			       struct hdd_ipa_connection_info *conn,
+			       bool *tx_pipe)
+{
+	uint32_t new_freq = conn->ch_freq;
+	QDF_STATUS status;
+	uint8_t vdev_id;
+	bool pipe;
+
+	if (ucfg_policy_mgr_get_vdev_same_freq_new_conn(hdd_ctx->psoc,
+							new_freq,
+							&vdev_id)) {
+		/* Inherit the pipe selection of the connection that has
+		 * same freq.
+		 */
+		return ucfg_ipa_get_alt_pipe(hdd_ctx->pdev, vdev_id, tx_pipe);
+	} else {
+		if (ucfg_policy_mgr_get_vdev_diff_freq_new_conn(hdd_ctx->psoc,
+								new_freq,
+								&vdev_id)) {
+			status = ucfg_ipa_get_alt_pipe(hdd_ctx->pdev, vdev_id,
+						       &pipe);
+			if (QDF_IS_STATUS_ERROR(status))
+				return QDF_STATUS_E_INVAL;
+
+			/* Inverse the pipe selection of the connection that
+			 * has different channel frequency.
+			 */
+			*tx_pipe = !pipe;
+			return QDF_STATUS_SUCCESS;
+		} else {
+			return QDF_STATUS_E_INVAL;
+		}
+	}
+}
+
+QDF_STATUS hdd_ipa_get_tx_pipe(struct hdd_context *hdd_ctx,
+			       struct wlan_hdd_link_info *link,
+			       bool *tx_pipe)
+{
+	struct hdd_ipa_connection_info conn;
+	uint32_t count;
+
+	if (qdf_unlikely(!hdd_ctx || !link || !tx_pipe)) {
+		hdd_debug("Invalid parameters");
+		return QDF_STATUS_E_INVAL;
+	}
+
+	/* If SBS not capable, use legacy DBS selection */
+	if (!ucfg_policy_mgr_is_hw_sbs_capable(hdd_ctx->psoc)) {
+		hdd_debug("firmware is not sbs capable");
+		*tx_pipe = WLAN_REG_IS_24GHZ_CH_FREQ(conn.ch_freq);
+		return QDF_STATUS_SUCCESS;
+	}
+
+	hdd_ipa_fill_connection_info(link, &conn);
+
+	/* Always select the primary pipe for connection that is EHT160 or
+	 * EHT320 due to higher tput requiements.
+	 */
+	if (conn.wlan_80211_mode == QCA_WLAN_802_11_MODE_11BE &&
+	    (conn.ch_width == CH_WIDTH_160MHZ ||
+	     conn.ch_width == CH_WIDTH_320MHZ)) {
+		*tx_pipe = false;
+		return QDF_STATUS_SUCCESS;
+	}
+
+	count = ucfg_policy_mgr_get_connection_count(hdd_ctx->psoc);
+	if (!count) {
+		/* For first connection that is below EHT160, select the
+		 * alternate pipe so as to reserve the primary pipe for
+		 * potential connections that are above EHT160.
+		 */
+		*tx_pipe = true;
+		return QDF_STATUS_SUCCESS;
+	}
+
+	return hdd_ipa_get_tx_pipe_multi_conn(hdd_ctx, &conn, tx_pipe);
+}
+#else /* !IPA_WDI3_TX_TWO_PIPES */
+QDF_STATUS hdd_ipa_get_tx_pipe(struct hdd_context *hdd_ctx,
+			       struct wlan_hdd_link_info *link,
+			       bool *tx_pipe)
+{
+	if (qdf_unlikely(!tx_pipe))
+		return QDF_STATUS_E_INVAL;
+
+	/* For IPA_WDI3_TX_TWO_PIPES=n, only one tx pipe is available */
+	*tx_pipe = false;
+
+	return QDF_STATUS_SUCCESS;
+}
+#endif /* IPA_WDI3_TX_TWO_PIPES */
+
 #endif