diff --git a/core/hdd/inc/wlan_hdd_main.h b/core/hdd/inc/wlan_hdd_main.h index 17567e69fe..e86d58666f 100644 --- a/core/hdd/inc/wlan_hdd_main.h +++ b/core/hdd/inc/wlan_hdd_main.h @@ -2019,6 +2019,11 @@ struct hdd_context { uint8_t power_type; #endif bool is_wlan_disabled; + + uint8_t *oem_data; + uint8_t oem_data_len; + uint8_t *file_name; + qdf_mutex_t wifi_kobj_lock; }; /** diff --git a/core/hdd/inc/wlan_hdd_sysfs.h b/core/hdd/inc/wlan_hdd_sysfs.h index b5fa07f892..86ffc86fba 100644 --- a/core/hdd/inc/wlan_hdd_sysfs.h +++ b/core/hdd/inc/wlan_hdd_sysfs.h @@ -1,5 +1,6 @@ /* * Copyright (c) 2017-2018, 2020 The Linux Foundation. All rights reserved. +* Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved. * * Permission to use, copy, modify, and/or distribute this software for * any purpose with or without fee is hereby granted, provided that the @@ -67,6 +68,23 @@ void hdd_create_adapter_sysfs_files(struct hdd_adapter *adapter); * Return: none */ void hdd_destroy_adapter_sysfs_files(struct hdd_adapter *adapter); + +/** + * hdd_create_wifi_feature_interface_sysfs_file - Create wifi feature interface + * sysfs file + * + * Return: none + */ +void hdd_create_wifi_feature_interface_sysfs_file(void); + +/** + * hdd_sysfs_create_wifi_root_obj() - create wifi root kobj + * @hdd_ctx: pointer to hdd context + * + * Return: none + */ +void hdd_sysfs_create_wifi_root_obj(struct hdd_context *hdd_ctx); + #else static inline int hdd_sysfs_validate_and_copy_buf(char *dest_buf, size_t dest_buf_size, @@ -100,6 +118,14 @@ static void hdd_create_adapter_sysfs_files(struct hdd_adapter *adapter) static void hdd_destroy_adapter_sysfs_files(struct hdd_adapter *adapter) { } + +static inline void hdd_create_wifi_feature_interface_sysfs_file(void) +{ +} + +static inline void hdd_sysfs_create_wifi_root_obj(struct hdd_context *hdd_ctx) +{ +} #endif /* End of WLAN SYSFS*/ #endif /* End of _WLAN_HDD_SYSFS_H_ */ diff --git a/core/hdd/src/wlan_hdd_main.c b/core/hdd/src/wlan_hdd_main.c index 0998e4e918..2bf8bfb38f 100644 --- a/core/hdd/src/wlan_hdd_main.c +++ b/core/hdd/src/wlan_hdd_main.c @@ -9437,6 +9437,17 @@ static void wlan_hdd_cache_chann_mutex_destroy(struct hdd_context *hdd_ctx) } #endif +/** + * wlan_hdd_wifi_kobj_lock_destroy() - Destroy wifi kobj lock + * @hdd_ctx: pointer to hdd context + * + * Return: none + */ +static void wlan_hdd_wifi_kobj_lock_destroy(struct hdd_context *hdd_ctx) +{ + qdf_mutex_destroy(&hdd_ctx->wifi_kobj_lock); +} + void hdd_wlan_exit(struct hdd_context *hdd_ctx) { struct wiphy *wiphy = hdd_ctx->wiphy; @@ -9502,6 +9513,7 @@ void hdd_wlan_exit(struct hdd_context *hdd_ctx) qdf_spinlock_destroy(&hdd_ctx->hdd_adapter_lock); qdf_spinlock_destroy(&hdd_ctx->connection_status_lock); + wlan_hdd_wifi_kobj_lock_destroy(hdd_ctx); wlan_hdd_cache_chann_mutex_destroy(hdd_ctx); osif_request_manager_deinit(); @@ -14593,6 +14605,24 @@ static void hdd_deregister_policy_manager_callback( } #endif +/** + * wlan_hdd_free_file_name_and_oem_data() -Free file name and oem data memory + * @hdd_ctx: pointer to hdd context + * + * Return: none + */ +static void wlan_hdd_free_file_name_and_oem_data(struct hdd_context *hdd_ctx) +{ + if (hdd_ctx->file_name) { + qdf_mem_free(hdd_ctx->file_name); + hdd_ctx->file_name = NULL; + } + if (hdd_ctx->oem_data) { + qdf_mem_free(hdd_ctx->oem_data); + hdd_ctx->oem_data = NULL; + } +} + int hdd_wlan_stop_modules(struct hdd_context *hdd_ctx, bool ftm_mode) { void *hif_ctx; @@ -14757,6 +14787,7 @@ int hdd_wlan_stop_modules(struct hdd_context *hdd_ctx, bool ftm_mode) /* Free the cache channels of the command SET_DISABLE_CHANNEL_LIST */ wlan_hdd_free_cache_channels(hdd_ctx); + wlan_hdd_free_file_name_and_oem_data(hdd_ctx); hdd_driver_mem_cleanup(); /* Free the resources allocated while storing SAR config. These needs @@ -15222,6 +15253,17 @@ static QDF_STATUS hdd_open_adapters_for_mode(struct hdd_context *hdd_ctx, return status; } +/** + * wlan_hdd_wifi_kobj_lock_create() - Create wifi kobj lock + * @hdd_ctx: pointer to hdd context + * + * Return: none + */ +static QDF_STATUS wlan_hdd_wifi_kobj_lock_create(struct hdd_context *hdd_ctx) +{ + return qdf_mutex_create(&hdd_ctx->wifi_kobj_lock); +} + int hdd_wlan_startup(struct hdd_context *hdd_ctx) { QDF_STATUS status; @@ -15238,6 +15280,10 @@ int hdd_wlan_startup(struct hdd_context *hdd_ctx) if (QDF_IS_STATUS_ERROR(status)) return qdf_status_to_os_return(status); + status = wlan_hdd_wifi_kobj_lock_create(hdd_ctx); + if (QDF_IS_STATUS_ERROR(status)) + return qdf_status_to_os_return(status); + #ifdef FEATURE_WLAN_CH_AVOID mutex_init(&hdd_ctx->avoid_freq_lock); #endif diff --git a/core/hdd/src/wlan_hdd_oemdata.c b/core/hdd/src/wlan_hdd_oemdata.c index 94f44f1cee..b6e22d203c 100644 --- a/core/hdd/src/wlan_hdd_oemdata.c +++ b/core/hdd/src/wlan_hdd_oemdata.c @@ -41,6 +41,8 @@ #include "wlan_hdd_oemdata.h" #include "wlan_osif_request_manager.h" #include "wlan_hdd_main.h" +#include "wlan_hdd_sysfs.h" + #ifdef FEATURE_OEM_DATA_SUPPORT #ifdef CNSS_GENL #include @@ -1133,6 +1135,55 @@ oem_data_attr_policy[QCA_WLAN_VENDOR_ATTR_OEM_DATA_PARAMS_MAX + 1] = { [QCA_WLAN_VENDOR_ATTR_OEM_DATA_RESPONSE_EXPECTED] = {.type = NLA_FLAG}, }; +/** + * hdd_copy_file_name_and_oem_data() - Copy file name and oem data + * @hdd_ctx: pointer to hdd context + * @oem_event_data: oem event data param buffe + * + * Return: none + */ +static void hdd_copy_file_name_and_oem_data( + struct hdd_context *hdd_ctx, + const struct oem_data *oem_event_data) +{ + if (!oem_event_data->data_len || !oem_event_data->file_name_len) { + hdd_err("Invalid file name or data length"); + return; + } + + if (hdd_ctx->oem_data || hdd_ctx->file_name) { + hdd_err("OEM data or file name already present"); + return; + } + + hdd_ctx->oem_data = qdf_mem_malloc(oem_event_data->data_len); + if (hdd_ctx->oem_data) { + hdd_ctx->oem_data_len = oem_event_data->data_len; + qdf_mem_copy(hdd_ctx->oem_data, oem_event_data->data, + oem_event_data->data_len); + hdd_ctx->file_name = qdf_mem_malloc( + oem_event_data->file_name_len); + if (hdd_ctx->file_name) + qdf_mem_copy(hdd_ctx->file_name, + oem_event_data->file_name, + oem_event_data->file_name_len); + else + qdf_mem_free(hdd_ctx->oem_data); + } +} + +/** + * hdd_create_wifi_feature_interface() - Create wifi feature interface + * @hdd_ctx: pointer to hdd context + * + * Return: none + */ +static void hdd_create_wifi_feature_interface(struct hdd_context *hdd_ctx) +{ + hdd_sysfs_create_wifi_root_obj(hdd_ctx); + hdd_create_wifi_feature_interface_sysfs_file(); +} + void hdd_oem_event_async_cb(const struct oem_data *oem_event_data) { struct sk_buff *vendor_event; @@ -1142,10 +1193,14 @@ void hdd_oem_event_async_cb(const struct oem_data *oem_event_data) hdd_enter(); - ret = wlan_hdd_validate_context(hdd_ctx); - if (ret) + if (!hdd_ctx) return; + if (oem_event_data->file_name) { + hdd_copy_file_name_and_oem_data(hdd_ctx, oem_event_data); + return hdd_create_wifi_feature_interface(hdd_ctx); + } + len = nla_total_size(oem_event_data->data_len) + NLMSG_HDRLEN; vendor_event = cfg80211_vendor_event_alloc( hdd_ctx->wiphy, NULL, len, diff --git a/core/hdd/src/wlan_hdd_sysfs.c b/core/hdd/src/wlan_hdd_sysfs.c index a3025b3693..ffcc94601a 100644 --- a/core/hdd/src/wlan_hdd_sysfs.c +++ b/core/hdd/src/wlan_hdd_sysfs.c @@ -689,16 +689,25 @@ static void hdd_sysfs_destroy_driver_root_obj(void) } } -static void hdd_sysfs_create_wifi_root_obj(struct hdd_context *hdd_ctx) +void hdd_sysfs_create_wifi_root_obj(struct hdd_context *hdd_ctx) { + qdf_mutex_acquire(&hdd_ctx->wifi_kobj_lock); + if (wifi_kobject) { + hdd_debug("wifi kobj already created"); + goto wifi_kobj_created; + } wifi_kobject = pld_get_wifi_kobj(hdd_ctx->parent_dev); if (wifi_kobject) { hdd_debug("wifi_kobject created by platform"); - return; + goto wifi_kobj_created; } wifi_kobject = kobject_create_and_add("wifi", NULL); if (!wifi_kobject) hdd_err("could not allocate wifi kobject"); + +wifi_kobj_created: + qdf_mutex_release(&hdd_ctx->wifi_kobj_lock); + } static void hdd_sysfs_destroy_wifi_root_obj(void) @@ -723,6 +732,11 @@ static void hdd_sysfs_destroy_wifi_root_obj(void) wifi_kobject = NULL; } +void hdd_create_wifi_feature_interface_sysfs_file(void) +{ + hdd_sysfs_create_wifi_feature_interface(wifi_kobject); +} + #ifdef WLAN_FEATURE_BEACON_RECEPTION_STATS static int hdd_sysfs_create_bcn_reception_interface(struct hdd_adapter *adapter) @@ -881,7 +895,7 @@ void hdd_create_sysfs_files(struct hdd_context *hdd_ctx) hdd_sysfs_mem_stats_create(wlan_kobject); hdd_sysfs_create_wifi_root_obj(hdd_ctx); if (QDF_GLOBAL_MISSION_MODE == hdd_get_conparam()) { - hdd_sysfs_create_wifi_feature_interface(wifi_kobject); + hdd_create_wifi_feature_interface_sysfs_file(); hdd_sysfs_create_powerstats_interface(); hdd_sysfs_create_dump_in_progress_interface(wifi_kobject); hdd_sysfs_fw_mode_config_create(driver_kobject); diff --git a/core/wma/src/wma_utils.c b/core/wma/src/wma_utils.c index a6c2b87457..ff2a6560f1 100644 --- a/core/wma/src/wma_utils.c +++ b/core/wma/src/wma_utils.c @@ -5032,6 +5032,11 @@ int wma_oem_event_handler(void *wma_ctx, uint8_t *event_buff, uint32_t len) oem_event_data.data_len = event->data_len; oem_event_data.data = param_buf->data; + if (param_buf->num_file_name) { + oem_event_data.file_name = param_buf->file_name; + oem_event_data.file_name_len = param_buf->num_file_name; + } + if (pmac->sme.oem_data_event_handler_cb) pmac->sme.oem_data_event_handler_cb(&oem_event_data, pmac->sme.oem_data_vdev_id);