Browse Source

qcacld-3.0: Accept update nss command in disconnected state

Currently if the FW supports the dynamic nss update feature,
the driver rejects the command to change the nss, but
there can be case scenarios where this update is required.

Fix is to accept the command in disconnected state, and
update the vdev specific ini of nss, and also update the
ini, and dynamic configuration in vdev mlme obj, which
is used in dynamic nss update.

Change-Id: I9cfa7f112159148733f06bf479987928f112901f
CRs-Fixed: 2404262
gaurank kathpalia 6 years ago
parent
commit
6c4b50c28d

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

@@ -2503,6 +2503,18 @@ void hdd_free_mac_address_lists(struct hdd_context *hdd_ctx);
 void hdd_update_macaddr(struct hdd_context *hdd_ctx,
 			struct qdf_mac_addr hw_macaddr, bool generate_mac_auto);
 
+/**
+ * hdd_store_nss_chains_cfg_in_vdev() - Store the per vdev ini cfg in vdev_obj
+ * @adapter: Current HDD adapter passed from caller
+ *
+ * This function will store the per vdev nss params to the particular mlme
+ * vdev obj.
+ *
+ * Return: None
+ */
+void
+hdd_store_nss_chains_cfg_in_vdev(struct hdd_adapter *adapter);
+
 /**
  * wlan_hdd_disable_roaming() - disable roaming on all STAs except the input one
  * @cur_adapter: Current HDD adapter passed from caller

+ 45 - 14
core/hdd/src/wlan_hdd_cfg.c

@@ -1722,12 +1722,6 @@ hdd_set_nss_params(struct hdd_adapter *adapter,
 		return QDF_STATUS_E_INVAL;
 	}
 
-	if (!hdd_is_vdev_in_conn_state(adapter)) {
-		hdd_debug("Vdev (id %d) not in connected/started state, cannot accept command",
-				adapter->vdev_id);
-		return QDF_STATUS_E_FAILURE;
-	}
-
 	for (band = NSS_CHAINS_BAND_2GHZ; band < NSS_CHAINS_BAND_MAX; band++)
 		hdd_populate_vdev_nss(&user_cfg, tx_nss,
 				      rx_nss, band);
@@ -1772,6 +1766,7 @@ QDF_STATUS hdd_update_nss(struct hdd_adapter *adapter, uint8_t nss)
 	mac_handle_t mac_handle;
 	bool bval = 0;
 	uint8_t tx_nss, rx_nss;
+	uint8_t band, max_supp_nss;
 
 	if ((nss == 2) && (hdd_ctx->num_rf_chains != 2)) {
 		hdd_err("No support for 2 spatial streams");
@@ -1783,18 +1778,59 @@ QDF_STATUS hdd_update_nss(struct hdd_adapter *adapter, uint8_t nss)
 		return QDF_STATUS_E_INVAL;
 	}
 
+	qdf_status = ucfg_mlme_get_vht_enable2x2(hdd_ctx->psoc, &bval);
+	if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
+		hdd_err("unable to get vht_enable2x2");
+		return QDF_STATUS_E_FAILURE;
+	}
+
+	if (!bval) {
+		hdd_err("Nss in 1x1, no change required, 2x2 mode disabled");
+		return QDF_STATUS_E_FAILURE;
+	}
+
 	mac_handle = hdd_ctx->mac_handle;
 	if (!mac_handle) {
 		hdd_err("NULL MAC handle");
 		return QDF_STATUS_E_INVAL;
 	}
+	max_supp_nss = MAX_VDEV_NSS;
 
 	/* Till now we dont have support for different rx, tx nss values */
 	tx_nss = nss;
 	rx_nss = nss;
 
-	if (hdd_ctx->dynamic_nss_chains_support)
-		return hdd_set_nss_params(adapter, tx_nss, rx_nss);
+	/*
+	 * If FW is supporting the dynamic nss update, this command is meant to
+	 * be per vdev, so update only the ini params of that particular vdev
+	 * and not the global param enable2x2
+	 */
+	if (hdd_ctx->dynamic_nss_chains_support) {
+		if (hdd_is_vdev_in_conn_state(adapter))
+			return hdd_set_nss_params(adapter, tx_nss, rx_nss);
+		hdd_debug("Vdev %d in disconnect state, changing ini nss params",
+			  adapter->vdev_id);
+
+		for (band = NSS_CHAINS_BAND_2GHZ; band < NSS_CHAINS_BAND_MAX;
+		     band++) {
+			/* This API will change the global ini in mlme cfg */
+			sme_update_vdev_nss(mac_handle, rx_nss, tx_nss,
+					    adapter->device_mode, band);
+			/*
+			 * This API will change the vdev nss params in mac
+			 * context
+			 */
+			sme_update_vdev_type_nss(mac_handle, max_supp_nss,
+						 band);
+		}
+		/*
+		 * This API will change the ini and dynamic nss params in
+		 * mlme vdev priv obj.
+		 */
+		hdd_store_nss_chains_cfg_in_vdev(adapter);
+
+		return QDF_STATUS_SUCCESS;
+	}
 
 	/*
 	 * The code below is executed only when fw doesn't support dynamic
@@ -1803,12 +1839,6 @@ QDF_STATUS hdd_update_nss(struct hdd_adapter *adapter, uint8_t nss)
 	 */
 	enable2x2 = (nss == 1) ? 0 : 1;
 
-	qdf_status = ucfg_mlme_get_vht_enable2x2(hdd_ctx->psoc, &bval);
-	if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
-		hdd_err("unable to get vht_enable2x2");
-		return QDF_STATUS_E_FAILURE;
-	}
-
 	if (bval == enable2x2) {
 		hdd_debug("NSS same as requested");
 		return QDF_STATUS_SUCCESS;
@@ -1909,5 +1939,6 @@ skip_ht_cap_update:
 		status = false;
 
 	hdd_set_policy_mgr_user_cfg(hdd_ctx);
+
 	return (status == false) ? QDF_STATUS_E_FAILURE : QDF_STATUS_SUCCESS;
 }

+ 1 - 1
core/hdd/src/wlan_hdd_main.c

@@ -4122,7 +4122,7 @@ static int hdd_set_sme_session_param(struct hdd_adapter *adapter,
 	return 0;
 }
 
-static void
+void
 hdd_store_nss_chains_cfg_in_vdev(struct hdd_adapter *adapter)
 {
 	struct wlan_mlme_nss_chains vdev_ini_cfg;

+ 20 - 0
core/sme/inc/sme_api.h

@@ -360,6 +360,26 @@ void
 sme_store_nss_chains_cfg_in_vdev(struct wlan_objmgr_vdev *vdev,
 				 struct wlan_mlme_nss_chains *vdev_ini_cfg);
 
+/**
+ * sme_update_vdev_nss() - Change the nss in ini(rx_nss_(band)) for
+ * particular opmode, and band.
+ * @mac_handle: The handle returned by mac_open.
+ * @rx_nss: new value of rx nss that user wants to change.
+ * @tx_nss: new value of tx nss that user wants to change.
+ * @vdev_op_mode: vdev operation mode.
+ * @band:- band for which user wants to change nss.
+ *
+ * This API will change the nss in ini (for eg. rx_nss_2g) in the mlme cfg i.e
+ * the global config structure kept in mac context.
+ *
+ * Return: none
+ */
+void
+sme_update_vdev_nss(mac_handle_t mac_handle,
+		    uint8_t rx_nss, uint8_t tx_nss,
+		    enum QDF_OPMODE vdev_op_mode,
+		    enum nss_chains_band_info band);
+
 /**
  * sme_nss_chains_update() - validate and send the user params to fw
  * @mac_handle: The handle returned by mac_open.

+ 51 - 0
core/sme/src/common/sme_api.c

@@ -4329,6 +4329,57 @@ sme_validate_nss_chains_config(struct wlan_objmgr_vdev *vdev,
 	return QDF_STATUS_SUCCESS;
 }
 
+static void
+sme_change_vdev_nss_ini(mac_handle_t mac_handle,
+			uint8_t rx_nss, uint8_t tx_nss,
+			enum QDF_OPMODE vdev_op_mode,
+			enum nss_chains_band_info band)
+{
+	uint8_t nss_shift;
+	uint32_t nss_mask = 0x7;
+	struct mac_context *mac_ctx = MAC_CONTEXT(mac_handle);
+
+	nss_shift = sme_get_nss_chain_shift(vdev_op_mode);
+
+	mac_ctx->mlme_cfg->nss_chains_ini_cfg.rx_nss[band] &=
+						~(nss_mask << nss_shift);
+	mac_ctx->mlme_cfg->nss_chains_ini_cfg.rx_nss[band] |=
+						 (rx_nss << nss_shift);
+	mac_ctx->mlme_cfg->nss_chains_ini_cfg.tx_nss[band] &=
+						~(nss_mask << nss_shift);
+	mac_ctx->mlme_cfg->nss_chains_ini_cfg.tx_nss[band] |=
+						 (tx_nss << nss_shift);
+	sme_debug("rx nss %d tx nss %d changed for vdev mode %d for band %d",
+		  rx_nss, tx_nss, vdev_op_mode, band);
+}
+
+void
+sme_update_vdev_nss(mac_handle_t mac_handle,
+		    uint8_t rx_nss, uint8_t tx_nss,
+		    enum QDF_OPMODE vdev_op_mode,
+		    enum nss_chains_band_info band)
+{
+	/*
+	 * If device mode is P2P-DEVICE, then we want P2P to come in that
+	 * particular nss, then we should change the nss of P@P-CLI, and GO
+	 * and we are unaware that for what will be the device mode after
+	 * negotiation yet.
+	 */
+
+	if (vdev_op_mode == QDF_P2P_DEVICE_MODE ||
+	    vdev_op_mode == QDF_P2P_CLIENT_MODE ||
+	    vdev_op_mode == QDF_P2P_GO_MODE) {
+		sme_change_vdev_nss_ini(mac_handle, rx_nss, tx_nss,
+					QDF_P2P_CLIENT_MODE, band);
+		sme_change_vdev_nss_ini(mac_handle, rx_nss, tx_nss,
+					QDF_P2P_GO_MODE, band);
+		sme_change_vdev_nss_ini(mac_handle, rx_nss, tx_nss,
+					QDF_P2P_DEVICE_MODE, band);
+	} else
+		sme_change_vdev_nss_ini(mac_handle, rx_nss, tx_nss,
+					vdev_op_mode, band);
+}
+
 QDF_STATUS
 sme_nss_chains_update(mac_handle_t mac_handle,
 		      struct wlan_mlme_nss_chains *user_cfg,