Bladeren bron

qcacld-3.0: Add APIs for Bus Bandwidth Manager

Add APIs for Bus Bandwidth Manager to select and
set bus bandwidth vote.

Change-Id: Ib33046120ae94205def15856522197c6b9b36623
CRs-Fixed: 2835183
Yeshwanth Sriram Guntuka 4 jaren geleden
bovenliggende
commit
3ab9055c94
3 gewijzigde bestanden met toevoegingen van 347 en 0 verwijderingen
  1. 1 0
      core/hdd/inc/wlan_hdd_main.h
  2. 324 0
      core/hdd/src/wlan_hdd_bus_bandwidth.c
  3. 22 0
      core/hdd/src/wlan_hdd_bus_bandwidth.h

+ 1 - 0
core/hdd/inc/wlan_hdd_main.h

@@ -513,6 +513,7 @@ typedef enum {
 	NET_DEV_HOLD_COUNTRY_CHANGE_UPDATE_SAP = 56,
 	NET_DEV_HOLD_CACHE_STATION_STATS_CB = 57,
 	NET_DEV_HOLD_DISPLAY_TXRX_STATS = 58,
+	NET_DEV_HOLD_BUS_BW_MGR = 59,
 
 	/* Keep it at the end */
 	NET_DEV_HOLD_ID_MAX

+ 324 - 0
core/hdd/src/wlan_hdd_bus_bandwidth.c

@@ -25,6 +25,7 @@
 #include <wlan_hdd_includes.h>
 #include "qca_vendor.h"
 #include "wlan_hdd_bus_bandwidth.h"
+#include "wlan_hdd_main.h"
 
 /**
  * bus_bw_table_default - default table which provides bus bandwidth level
@@ -77,6 +78,329 @@ static bus_bw_table_type bus_bw_table_low_latency = {
 				       BUS_BW_LEVEL_6, BUS_BW_LEVEL_6},
 };
 
+/**
+ * bbm_convert_to_pld_bus_lvl() - Convert from internal bus vote level to
+ *  PLD bus vote level
+ * @vote_lvl: internal bus bw vote level
+ *
+ * Returns: PLD bus vote level
+ */
+static enum pld_bus_width_type
+bbm_convert_to_pld_bus_lvl(enum bus_bw_level vote_lvl)
+{
+	switch (vote_lvl) {
+	case BUS_BW_LEVEL_1:
+		return PLD_BUS_WIDTH_IDLE;
+	case BUS_BW_LEVEL_2:
+		return PLD_BUS_WIDTH_LOW;
+	case BUS_BW_LEVEL_3:
+		return PLD_BUS_WIDTH_MEDIUM;
+	case BUS_BW_LEVEL_4:
+		return PLD_BUS_WIDTH_HIGH;
+	case BUS_BW_LEVEL_5:
+		return PLD_BUS_WIDTH_LOW_LATENCY;
+	case BUS_BW_LEVEL_6:
+		return PLD_BUS_WIDTH_VERY_HIGH;
+	case BUS_BW_LEVEL_NONE:
+	default:
+		return PLD_BUS_WIDTH_NONE;
+	}
+}
+
+/**
+ * bbm_get_bus_bw_level_vote() - Select bus bw vote level per adapter based
+ *  on connection mode and throughput level
+ * @adapter: HDD adapter. Caller ensures that adapter is valid.
+ * @tput_level: throughput level
+ *
+ * Returns: Bus bw level
+ */
+static enum bus_bw_level
+bbm_get_bus_bw_level_vote(struct hdd_adapter *adapter,
+			  enum tput_level tput_level)
+{
+	struct hdd_station_ctx *sta_ctx;
+	struct hdd_ap_ctx *ap_ctx;
+	enum qca_wlan_802_11_mode i;
+	enum qca_wlan_802_11_mode dot11_mode;
+	enum bus_bw_level vote_lvl = BUS_BW_LEVEL_NONE;
+	struct bbm_context *bbm_ctx = adapter->hdd_ctx->bbm_ctx;
+	bus_bw_table_type *lkp_table = bbm_ctx->curr_bus_bw_lookup_table;
+
+	switch (adapter->device_mode) {
+	case QDF_STA_MODE:
+	case QDF_P2P_CLIENT_MODE:
+		sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
+		if (!hdd_conn_is_connected(sta_ctx))
+			break;
+
+		dot11_mode = hdd_convert_cfgdot11mode_to_80211mode(sta_ctx->
+							   conn_info.dot11mode);
+		if (dot11_mode >= QCA_WLAN_802_11_MODE_INVALID) {
+			hdd_err("invalid STA/P2P-CLI dot11 mode");
+			break;
+		}
+
+		return (*lkp_table)[dot11_mode][tput_level];
+	case QDF_SAP_MODE:
+	case QDF_P2P_GO_MODE:
+		ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(adapter);
+		if (!ap_ctx->ap_active)
+			break;
+
+		for (i = QCA_WLAN_802_11_MODE_11B;
+		     i < QCA_WLAN_802_11_MODE_INVALID; i++) {
+			if (ap_ctx->client_count[i] &&
+			    (*lkp_table)[i][tput_level] > vote_lvl)
+				vote_lvl = (*lkp_table)[i][tput_level];
+		}
+
+		return vote_lvl;
+	case QDF_NDI_MODE:
+		if (WLAN_HDD_GET_STATION_CTX_PTR(adapter)->
+		    conn_info.conn_state != eConnectionState_NdiConnected)
+			break;
+
+		/*
+		 * NDI dot11mode is currently hardcoded to 11AC in driver and
+		 * since the bus bw levels in table do not differ between 11AC
+		 * and 11AX, using max supported mode instead. Dot11mode of the
+		 * peers are not saved in driver and legacy modes are not
+		 * supported in NAN.
+		 */
+		return (*lkp_table)[QCA_WLAN_802_11_MODE_11AX][tput_level];
+	default:
+		break;
+	}
+
+	return vote_lvl;
+}
+
+/**
+ * bbm_apply_tput_policy() - Apply tput BBM policy by considering
+ *  throughput level and connection modes across adapters
+ * @hdd_ctx: HDD context
+ * @tput_level: throughput level
+ *
+ * Returns: None
+ */
+static void
+bbm_apply_tput_policy(struct hdd_context *hdd_ctx, enum tput_level tput_level)
+{
+	struct hdd_adapter *adapter;
+	struct hdd_adapter *next_adapter;
+	enum bus_bw_level next_vote = BUS_BW_LEVEL_NONE;
+	enum bus_bw_level tmp_vote;
+	struct bbm_context *bbm_ctx = hdd_ctx->bbm_ctx;
+
+	if (tput_level == TPUT_LEVEL_NONE) {
+		/*
+		 * This is to handle the scenario where bus bw periodic work
+		 * is force cancelled
+		 */
+		if (!hdd_is_any_adapter_connected(hdd_ctx))
+			bbm_ctx->per_policy_vote[BBM_TPUT_POLICY] = next_vote;
+		return;
+	}
+
+	hdd_for_each_adapter_dev_held_safe(hdd_ctx, adapter, next_adapter,
+					   NET_DEV_HOLD_BUS_BW_MGR) {
+		tmp_vote = bbm_get_bus_bw_level_vote(adapter, tput_level);
+		if (tmp_vote > next_vote)
+			next_vote = tmp_vote;
+		hdd_adapter_dev_put_debug(adapter, NET_DEV_HOLD_BUS_BW_MGR);
+	}
+
+	bbm_ctx->per_policy_vote[BBM_TPUT_POLICY] = next_vote;
+}
+
+/**
+ * bbm_apply_driver_mode_policy() - Apply driver mode BBM policy
+ * @bbm_ctx: bus bw mgr context
+ * @driver_mode: global driver mode
+ *
+ * Returns: None
+ */
+static void
+bbm_apply_driver_mode_policy(struct bbm_context *bbm_ctx,
+			     enum QDF_GLOBAL_MODE driver_mode)
+{
+	switch (driver_mode) {
+	case QDF_GLOBAL_MONITOR_MODE:
+	case QDF_GLOBAL_FTM_MODE:
+		bbm_ctx->per_policy_vote[BBM_DRIVER_MODE_POLICY] =
+							    BUS_BW_LEVEL_6;
+		return;
+	default:
+		bbm_ctx->per_policy_vote[BBM_DRIVER_MODE_POLICY] =
+							 BUS_BW_LEVEL_NONE;
+		return;
+	}
+}
+
+/**
+ * bbm_apply_non_persistent_policy() - Apply non persistent policy and set
+ *  the bus bandwidth
+ * @hdd_ctx: HDD context
+ * @flag: flag
+ *
+ * Returns: None
+ */
+static void
+bbm_apply_non_persistent_policy(struct hdd_context *hdd_ctx,
+				enum bbm_non_per_flag flag)
+{
+	switch (flag) {
+	case BBM_APPS_RESUME:
+		if (hdd_is_any_adapter_connected(hdd_ctx)) {
+			hdd_ctx->bbm_ctx->curr_vote_level = BUS_BW_LEVEL_RESUME;
+			pld_request_bus_bandwidth(hdd_ctx->parent_dev,
+			       bbm_convert_to_pld_bus_lvl(BUS_BW_LEVEL_RESUME));
+		} else {
+			hdd_ctx->bbm_ctx->curr_vote_level = BUS_BW_LEVEL_NONE;
+			pld_request_bus_bandwidth(hdd_ctx->parent_dev,
+				 bbm_convert_to_pld_bus_lvl(BUS_BW_LEVEL_NONE));
+		}
+		return;
+	case BBM_APPS_SUSPEND:
+		hdd_ctx->bbm_ctx->curr_vote_level = BUS_BW_LEVEL_NONE;
+		pld_request_bus_bandwidth(hdd_ctx->parent_dev,
+			    bbm_convert_to_pld_bus_lvl(BUS_BW_LEVEL_NONE));
+		return;
+	default:
+		hdd_debug("flag %d not handled in res/sus BBM policy", flag);
+		return;
+	}
+}
+
+/**
+ * bbm_apply_wlm_policy() - Apply WLM based BBM policy by selecting
+ *  lookup tables based on the latency level
+ * @bbm_ctx: Bus BW mgr context
+ * @wlm_level: WLM latency level
+ *
+ * Returns: None
+ */
+static void
+bbm_apply_wlm_policy(struct bbm_context *bbm_ctx, enum wlm_ll_level wlm_level)
+{
+	switch (wlm_level) {
+	case WLM_LL_NORMAL:
+		bbm_ctx->curr_bus_bw_lookup_table = &bus_bw_table_default;
+		break;
+	case WLM_LL_LOW:
+		bbm_ctx->curr_bus_bw_lookup_table = &bus_bw_table_low_latency;
+		break;
+	default:
+		hdd_debug("wlm level %d not handled in BBM WLM policy",
+			  wlm_level);
+		break;
+	}
+}
+
+/**
+ * bbm_apply_user_policy() - Apply user specified bus voting
+ *  level
+ * @bbm_ctx: Bus BW mgr context
+ * @set: set or reset flag
+ * @user_level: user bus vote level
+ *
+ * Returns: qdf status
+ */
+static QDF_STATUS
+bbm_apply_user_policy(struct bbm_context *bbm_ctx, bool set,
+		      enum bus_bw_level user_level)
+{
+	if (user_level >= BUS_BW_LEVEL_MAX) {
+		hdd_err("Invalid user vote level %d", user_level);
+		return QDF_STATUS_E_FAILURE;
+	}
+
+	if (set)
+		bbm_ctx->per_policy_vote[BBM_USER_POLICY] = user_level;
+	else
+		bbm_ctx->per_policy_vote[BBM_USER_POLICY] = BUS_BW_LEVEL_NONE;
+
+	return QDF_STATUS_SUCCESS;
+}
+
+/**
+ * bbm_request_bus_bandwidth() - Set bus bandwidth level
+ * @hdd_ctx: HDD context
+ *
+ * Returns: None
+ */
+static void
+bbm_request_bus_bandwidth(struct hdd_context *hdd_ctx)
+{
+	enum bbm_policy i;
+	enum bus_bw_level next_vote = BUS_BW_LEVEL_NONE;
+	enum pld_bus_width_type pld_vote;
+	struct bbm_context *bbm_ctx = hdd_ctx->bbm_ctx;
+
+	for (i = BBM_DRIVER_MODE_POLICY; i < BBM_MAX_POLICY; i++) {
+		if (bbm_ctx->per_policy_vote[i] > next_vote)
+			next_vote = bbm_ctx->per_policy_vote[i];
+	}
+
+	if (next_vote != bbm_ctx->curr_vote_level) {
+		pld_vote = bbm_convert_to_pld_bus_lvl(next_vote);
+		hdd_debug("Bus bandwidth vote level change from %d to %d pld_vote: %d",
+			  bbm_ctx->curr_vote_level, next_vote, pld_vote);
+		bbm_ctx->curr_vote_level = next_vote;
+		pld_request_bus_bandwidth(hdd_ctx->parent_dev, pld_vote);
+	}
+}
+
+void hdd_bbm_apply_independent_policy(struct hdd_context *hdd_ctx,
+				      struct bbm_params *params)
+{
+	struct bbm_context *bbm_ctx;
+	QDF_STATUS status;
+
+	if (!hdd_ctx || !params)
+		return;
+
+	bbm_ctx = hdd_ctx->bbm_ctx;
+
+	qdf_mutex_acquire(&bbm_ctx->bbm_lock);
+
+	switch (params->policy) {
+	case BBM_TPUT_POLICY:
+		bbm_apply_tput_policy(hdd_ctx, params->policy_info.tput_level);
+		break;
+	case BBM_NON_PERSISTENT_POLICY:
+		bbm_apply_non_persistent_policy(hdd_ctx,
+						params->policy_info.flag);
+		goto done;
+	case BBM_DRIVER_MODE_POLICY:
+		bbm_apply_driver_mode_policy(bbm_ctx,
+					     params->policy_info.driver_mode);
+		break;
+	case BBM_SELECT_TABLE_POLICY:
+		bbm_apply_wlm_policy(bbm_ctx, params->policy_info.wlm_level);
+		goto done;
+	case BBM_USER_POLICY:
+		/*
+		 * This policy is not used currently.
+		 */
+		status = bbm_apply_user_policy(bbm_ctx,
+					    params->policy_info.usr.set,
+					    params->policy_info.usr.user_level);
+		if (QDF_IS_STATUS_ERROR(status))
+			goto done;
+		break;
+	default:
+		hdd_debug("BBM policy %d not handled", params->policy);
+		goto done;
+	}
+
+	bbm_request_bus_bandwidth(hdd_ctx);
+
+done:
+	qdf_mutex_release(&bbm_ctx->bbm_lock);
+}
+
 int hdd_bbm_context_init(struct hdd_context *hdd_ctx)
 {
 	struct bbm_context *bbm_ctx;

+ 22 - 0
core/hdd/src/wlan_hdd_bus_bandwidth.h

@@ -48,6 +48,8 @@ enum bus_bw_level {
 	BUS_BW_LEVEL_MAX,
 };
 
+#define BUS_BW_LEVEL_RESUME BUS_BW_LEVEL_3
+
 /**
  * enum tput_level - throughput levels
  *
@@ -181,6 +183,20 @@ int hdd_bbm_context_init(struct hdd_context *hdd_ctx);
  * Returns: None
  */
 void hdd_bbm_context_deinit(struct hdd_context *hdd_ctx);
+
+/**
+ * hdd_bbm_apply_independent_policy() - Function to apply independent policies
+ *  to set the bus bw level
+ * @hdd_ctx: HDD context
+ * @params: BBM policy related params
+ *
+ * The function applies BBM related policies and appropriately sets the bus
+ * bandwidth level.
+ *
+ * Returns: None
+ */
+void hdd_bbm_apply_independent_policy(struct hdd_context *hdd_ctx,
+				      struct bbm_params *params);
 #else
 static inline int hdd_bbm_context_init(struct hdd_context *hdd_ctx)
 {
@@ -190,5 +206,11 @@ static inline int hdd_bbm_context_init(struct hdd_context *hdd_ctx)
 static inline void hdd_bbm_context_deinit(struct hdd_context *hdd_ctx)
 {
 }
+
+static inline
+void hdd_bbm_apply_independent_policy(struct hdd_context *hdd_ctx,
+				      struct bbm_params *params)
+{
+}
 #endif
 #endif