diff --git a/components/mlme/dispatcher/inc/wlan_mlme_api.h b/components/mlme/dispatcher/inc/wlan_mlme_api.h index f2bbc47f77..a5c21f323e 100644 --- a/components/mlme/dispatcher/inc/wlan_mlme_api.h +++ b/components/mlme/dispatcher/inc/wlan_mlme_api.h @@ -822,6 +822,16 @@ QDF_STATUS wlan_mlme_cfg_get_he_ul_mumimo(struct wlan_objmgr_psoc *psoc, QDF_STATUS wlan_mlme_cfg_set_he_ul_mumimo(struct wlan_objmgr_psoc *psoc, uint32_t value); +/** + * mlme_cfg_get_he_caps() - Get the HE capability info + * @psoc: pointer to psoc object + * @he_cap: Caps that needs to be filled. + * + * Return: QDF Status + */ +QDF_STATUS mlme_cfg_get_he_caps(struct wlan_objmgr_psoc *psoc, + tDot11fIEhe_cap *he_cap); + /** * wlan_mlme_cfg_get_enable_ul_mimo() - Get the HE Ul mimo * @psoc: pointer to psoc object diff --git a/components/mlme/dispatcher/inc/wlan_mlme_ucfg_api.h b/components/mlme/dispatcher/inc/wlan_mlme_ucfg_api.h index 6959d6cb13..1fdede4af1 100644 --- a/components/mlme/dispatcher/inc/wlan_mlme_ucfg_api.h +++ b/components/mlme/dispatcher/inc/wlan_mlme_ucfg_api.h @@ -3149,6 +3149,20 @@ ucfg_mlme_update_tgt_he_cap(struct wlan_objmgr_psoc *psoc, return mlme_update_tgt_he_caps_in_cfg(psoc, cfg); } +/** + * ucfg_mlme_cfg_get_he_caps() - Get the HE capability info + * @psoc: pointer to psoc object + * @he_cap: Caps that needs to be filled. + * + * Return: QDF Status + */ +static inline +QDF_STATUS ucfg_mlme_cfg_get_he_caps(struct wlan_objmgr_psoc *psoc, + tDot11fIEhe_cap *he_cap) +{ + return mlme_cfg_get_he_caps(psoc, he_cap); +} + /** * ucfg_mlme_cfg_get_he_ul_mumimo() - Get the HE Ul Mumio * @psoc: pointer to psoc object diff --git a/components/mlme/dispatcher/src/wlan_mlme_api.c b/components/mlme/dispatcher/src/wlan_mlme_api.c index 4b8beae482..b1dffdb071 100644 --- a/components/mlme/dispatcher/src/wlan_mlme_api.c +++ b/components/mlme/dispatcher/src/wlan_mlme_api.c @@ -471,6 +471,20 @@ QDF_STATUS wlan_mlme_cfg_get_he_ul_mumimo(struct wlan_objmgr_psoc *psoc, return QDF_STATUS_SUCCESS; } +QDF_STATUS mlme_cfg_get_he_caps(struct wlan_objmgr_psoc *psoc, + tDot11fIEhe_cap *he_cap) +{ + struct wlan_mlme_psoc_obj *mlme_obj; + + mlme_obj = mlme_get_psoc_obj(psoc); + if (!mlme_obj) + return QDF_STATUS_E_FAILURE; + + *he_cap = mlme_obj->cfg.he_caps.he_cap_orig; + + return QDF_STATUS_SUCCESS; +} + QDF_STATUS wlan_mlme_cfg_set_he_ul_mumimo(struct wlan_objmgr_psoc *psoc, uint32_t value) { diff --git a/core/hdd/inc/wlan_hdd_main.h b/core/hdd/inc/wlan_hdd_main.h index ea63a1657f..6116985cdc 100644 --- a/core/hdd/inc/wlan_hdd_main.h +++ b/core/hdd/inc/wlan_hdd_main.h @@ -1665,6 +1665,8 @@ struct hdd_fw_ver_info { * struct hdd_context - hdd shared driver and psoc/device context * @psoc: object manager psoc context * @pdev: object manager pdev context + * @iftype_data_2g: Interface data for 2g band + * @iftype_data_5g: Interface data for 5g band * @bus_bw_work: work for periodically computing DDR bus bandwidth requirements * @g_event_flags: a bitmap of hdd_driver_flags * @psoc_idle_timeout_work: delayed work for psoc idle shutdown @@ -1697,6 +1699,11 @@ struct hdd_context { struct ieee80211_channel *channels_2ghz; struct ieee80211_channel *channels_5ghz; +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 19, 0)) + struct ieee80211_sband_iftype_data *iftype_data_2g; + struct ieee80211_sband_iftype_data *iftype_data_5g; +#endif + /* Completion variable to indicate Mc Thread Suspended */ struct completion mc_sus_event_var; diff --git a/core/hdd/src/wlan_hdd_cfg80211.c b/core/hdd/src/wlan_hdd_cfg80211.c index b29d955f57..ae1170e3fd 100644 --- a/core/hdd/src/wlan_hdd_cfg80211.c +++ b/core/hdd/src/wlan_hdd_cfg80211.c @@ -13294,6 +13294,53 @@ wlan_hdd_populate_srd_chan_info(struct hdd_context *hdd_ctx, uint32_t index) #endif +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 19, 0)) +static QDF_STATUS +wlan_hdd_iftype_data_alloc(struct hdd_context *hdd_ctx) +{ + hdd_ctx->iftype_data_2g = + qdf_mem_malloc(sizeof(*hdd_ctx->iftype_data_2g)); + + if (!hdd_ctx->iftype_data_2g) { + hdd_err("mem alloc failed for 2g iftype data"); + return QDF_STATUS_E_NOMEM; + } + hdd_ctx->iftype_data_5g = + qdf_mem_malloc(sizeof(*hdd_ctx->iftype_data_5g)); + + if (!hdd_ctx->iftype_data_5g) { + hdd_err("mem alloc failed for 5g iftype data"); + qdf_mem_free(hdd_ctx->iftype_data_2g); + hdd_ctx->iftype_data_2g = NULL; + return QDF_STATUS_E_NOMEM; + } + + return QDF_STATUS_SUCCESS; +} +#else +static inline QDF_STATUS +wlan_hdd_iftype_data_alloc(struct hdd_context *hdd_ctx) +{ + return QDF_STATUS_SUCCESS; +} +#endif + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 19, 0)) +static void +wlan_hdd_iftype_data_mem_free(struct hdd_context *hdd_ctx) +{ + qdf_mem_free(hdd_ctx->iftype_data_5g); + qdf_mem_free(hdd_ctx->iftype_data_2g); + hdd_ctx->iftype_data_5g = NULL; + hdd_ctx->iftype_data_2g = NULL; +} +#else +static inline void +wlan_hdd_iftype_data_mem_free(struct hdd_context *hdd_ctx) +{ +} +#endif + /* * FUNCTION: wlan_hdd_cfg80211_init * This function is called by hdd_wlan_startup() @@ -13377,14 +13424,17 @@ int wlan_hdd_cfg80211_init(struct device *dev, } hdd_ctx->channels_5ghz = qdf_mem_malloc(band_5_ghz_chanenls_size); if (!hdd_ctx->channels_5ghz) - goto mem_fail; + goto mem_fail_5g; + + if (QDF_IS_STATUS_ERROR(wlan_hdd_iftype_data_alloc(hdd_ctx))) + goto mem_fail_iftype_data; /*Initialise the supported cipher suite details */ if (ucfg_fwol_get_gcmp_enable(hdd_ctx->psoc)) { cipher_suites = qdf_mem_malloc(sizeof(hdd_cipher_suites) + sizeof(hdd_gcmp_cipher_suits)); if (!cipher_suites) - return -ENOMEM; + goto mem_fail_cipher_suites; wiphy->n_cipher_suites = QDF_ARRAY_SIZE(hdd_cipher_suites) + QDF_ARRAY_SIZE(hdd_gcmp_cipher_suits); qdf_mem_copy(cipher_suites, &hdd_cipher_suites, @@ -13395,7 +13445,7 @@ int wlan_hdd_cfg80211_init(struct device *dev, } else { cipher_suites = qdf_mem_malloc(sizeof(hdd_cipher_suites)); if (!cipher_suites) - return -ENOMEM; + goto mem_fail_cipher_suites; wiphy->n_cipher_suites = QDF_ARRAY_SIZE(hdd_cipher_suites); qdf_mem_copy(cipher_suites, &hdd_cipher_suites, sizeof(hdd_cipher_suites)); @@ -13436,12 +13486,16 @@ int wlan_hdd_cfg80211_init(struct device *dev, hdd_exit(); return 0; -mem_fail: +mem_fail_cipher_suites: + wlan_hdd_iftype_data_mem_free(hdd_ctx); +mem_fail_iftype_data: + qdf_mem_free(hdd_ctx->channels_5ghz); + hdd_ctx->channels_5ghz = NULL; +mem_fail_5g: hdd_err("Not enough memory to allocate channels"); - if (hdd_ctx->channels_2ghz) { - qdf_mem_free(hdd_ctx->channels_2ghz); - hdd_ctx->channels_2ghz = NULL; - } + qdf_mem_free(hdd_ctx->channels_2ghz); + hdd_ctx->channels_2ghz = NULL; + return -ENOMEM; } @@ -13466,8 +13520,9 @@ void wlan_hdd_cfg80211_deinit(struct wiphy *wiphy) (wiphy->bands[i]->channels)) wiphy->bands[i]->channels = NULL; } - qdf_mem_free(hdd_ctx->channels_2ghz); + wlan_hdd_iftype_data_mem_free(hdd_ctx); qdf_mem_free(hdd_ctx->channels_5ghz); + qdf_mem_free(hdd_ctx->channels_2ghz); hdd_ctx->channels_2ghz = NULL; hdd_ctx->channels_5ghz = NULL; diff --git a/core/hdd/src/wlan_hdd_main.c b/core/hdd/src/wlan_hdd_main.c index 5d6bfb63a2..be1a40869d 100644 --- a/core/hdd/src/wlan_hdd_main.c +++ b/core/hdd/src/wlan_hdd_main.c @@ -1993,6 +1993,43 @@ static void hdd_extract_fw_version_info(struct hdd_context *hdd_ctx) HDD_FW_VER_REL_ID(hdd_ctx->target_fw_vers_ext); } +#if defined(WLAN_FEATURE_11AX) && \ + (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 19, 0)) +static void hdd_update_wiphy_he_cap(struct hdd_context *hdd_ctx) +{ + tDot11fIEhe_cap he_cap_cfg; + struct ieee80211_supported_band *band_2g = + hdd_ctx->wiphy->bands[HDD_NL80211_BAND_2GHZ]; + struct ieee80211_supported_band *band_5g = + hdd_ctx->wiphy->bands[HDD_NL80211_BAND_5GHZ]; + QDF_STATUS status; + + status = ucfg_mlme_cfg_get_he_caps(hdd_ctx->psoc, &he_cap_cfg); + + if (QDF_IS_STATUS_ERROR(status)) + return; + + if (band_2g) { + hdd_ctx->iftype_data_2g->types_mask = + (BIT(NL80211_IFTYPE_STATION) | BIT(NL80211_IFTYPE_AP)); + hdd_ctx->iftype_data_2g->he_cap.has_he = he_cap_cfg.present; + band_2g->n_iftype_data = 1; + band_2g->iftype_data = hdd_ctx->iftype_data_2g; + } + if (band_5g) { + hdd_ctx->iftype_data_5g->types_mask = + (BIT(NL80211_IFTYPE_STATION) | BIT(NL80211_IFTYPE_AP)); + hdd_ctx->iftype_data_5g->he_cap.has_he = he_cap_cfg.present; + band_5g->n_iftype_data = 1; + band_5g->iftype_data = hdd_ctx->iftype_data_5g; + } +} +#else +static void hdd_update_wiphy_he_cap(struct hdd_context *hdd_ctx) +{ +} +#endif + int hdd_update_tgt_cfg(hdd_handle_t hdd_handle, struct wma_tgt_cfg *cfg) { int ret; @@ -2161,6 +2198,7 @@ int hdd_update_tgt_cfg(hdd_handle_t hdd_handle, struct wma_tgt_cfg *cfg) if (cfg->services.en_11ax) { hdd_info("11AX: 11ax is enabled - update HDD config"); hdd_update_tgt_he_cap(hdd_ctx, cfg); + hdd_update_wiphy_he_cap(hdd_ctx); } hdd_update_tgt_twt_cap(hdd_ctx, cfg);