From ccfca4a11ecb0c731ec577b968e0cb4ed2e22ff4 Mon Sep 17 00:00:00 2001 From: gaurank kathpalia Date: Tue, 13 Aug 2019 11:51:27 +0530 Subject: [PATCH] qcacld-3.0: Update HE capabilities in wiphy structure Update the mac, phy, mcs, nss caps of bands 2.4ghz, and 5ghz for HE capabilities in the wiphy structure to inform userspace about the driver capability. Change-Id: I9fb1233e5396bf3ea411c057af9cbcd5b358271c CRs-Fixed: 2486266 --- .../mlme/dispatcher/inc/wlan_mlme_api.h | 10 +++ .../mlme/dispatcher/inc/wlan_mlme_ucfg_api.h | 14 ++++ .../mlme/dispatcher/src/wlan_mlme_api.c | 14 ++++ core/hdd/inc/wlan_hdd_main.h | 7 ++ core/hdd/src/wlan_hdd_cfg80211.c | 73 ++++++++++++++++--- core/hdd/src/wlan_hdd_main.c | 38 ++++++++++ 6 files changed, 147 insertions(+), 9 deletions(-) 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);