diff --git a/core/hdd/inc/wlan_hdd_main.h b/core/hdd/inc/wlan_hdd_main.h index 25e40af73f..27b9d0e378 100644 --- a/core/hdd/inc/wlan_hdd_main.h +++ b/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 diff --git a/core/hdd/src/wlan_hdd_cfg.c b/core/hdd/src/wlan_hdd_cfg.c index 18603034c2..5844ec92fc 100644 --- a/core/hdd/src/wlan_hdd_cfg.c +++ b/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; } diff --git a/core/hdd/src/wlan_hdd_main.c b/core/hdd/src/wlan_hdd_main.c index f9d9483357..a5b9c11308 100644 --- a/core/hdd/src/wlan_hdd_main.c +++ b/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; diff --git a/core/sme/inc/sme_api.h b/core/sme/inc/sme_api.h index 1f4d91b030..3a1bf2baf4 100644 --- a/core/sme/inc/sme_api.h +++ b/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. diff --git a/core/sme/src/common/sme_api.c b/core/sme/src/common/sme_api.c index 59a41a6a26..ddaf1aabd4 100644 --- a/core/sme/src/common/sme_api.c +++ b/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,