diff --git a/Kbuild b/Kbuild index 1c2ce9aa3865..c09de4e1ecd8 100644 --- a/Kbuild +++ b/Kbuild @@ -321,6 +321,9 @@ endif ifeq ($(CONFIG_WLAN_GET_TEMP), y) HDD_OBJS += $(HDD_SRC_DIR)/wlan_hdd_sysfs_get_temp.o endif +ifeq ($(CONFIG_WLAN_THERMAL_CFG), y) +HDD_OBJS += $(HDD_SRC_DIR)/wlan_hdd_sysfs_thermal_cfg.o +endif endif ifeq ($(CONFIG_QCACLD_FEATURE_FW_STATE), y) @@ -2557,6 +2560,7 @@ cppflags-$(CONFIG_WLAN_TXRX_STATS) += -DCONFIG_WLAN_TXRX_STATS cppflags-$(CONFIG_WLAN_SET_DP_TRACE) += -DCONFIG_WLAN_SET_DP_TRACE cppflags-$(CONFIG_WLAN_GET_RANGE_EXT) += -DCONFIG_WLAN_GET_RANGE_EXT cppflags-$(CONFIG_WLAN_GET_TEMP) += -DCONFIG_WLAN_GET_TEMP +cppflags-$(CONFIG_WLAN_THERMAL_CFG) += -DCONFIG_WLAN_THERMAL_CFG cppflags-$(CONFIG_FEATURE_UNIT_TEST_SUSPEND) += -DWLAN_SUSPEND_RESUME_TEST cppflags-$(CONFIG_FEATURE_WLM_STATS) += -DFEATURE_WLM_STATS diff --git a/configs/default_defconfig b/configs/default_defconfig index 0ed8978a6cfd..939338dafb24 100644 --- a/configs/default_defconfig +++ b/configs/default_defconfig @@ -195,6 +195,7 @@ ifeq ($(CONFIG_QCOM_TDLS), y) CONFIG_WLAN_GET_TDLS_PEERS := y endif CONFIG_WLAN_GET_TEMP := y + CONFIG_WLAN_THERMAL_CFG := y endif CONFIG_WLAN_POWER_DEBUG := y diff --git a/core/hdd/src/wlan_hdd_sysfs.c b/core/hdd/src/wlan_hdd_sysfs.c index eaaf2737a4fb..0dbdfef5fd54 100644 --- a/core/hdd/src/wlan_hdd_sysfs.c +++ b/core/hdd/src/wlan_hdd_sysfs.c @@ -59,6 +59,7 @@ #include #include #include +#include #define MAX_PSOC_ID_SIZE 10 @@ -723,12 +724,14 @@ void hdd_create_sysfs_files(struct hdd_context *hdd_ctx) hdd_sysfs_wow_ito_create(driver_kobject); hdd_sysfs_set_scan_cfg_create(driver_kobject); hdd_sysfs_set_dp_trace_create(driver_kobject); + hdd_sysfs_thermal_cfg_create(driver_kobject); } } void hdd_destroy_sysfs_files(void) { if (QDF_GLOBAL_MISSION_MODE == hdd_get_conparam()) { + hdd_sysfs_thermal_cfg_destroy(driver_kobject); hdd_sysfs_set_dp_trace_destroy(driver_kobject); hdd_sysfs_set_scan_cfg_destroy(driver_kobject); hdd_sysfs_wow_ito_destroy(driver_kobject); diff --git a/core/hdd/src/wlan_hdd_sysfs_thermal_cfg.c b/core/hdd/src/wlan_hdd_sysfs_thermal_cfg.c new file mode 100644 index 000000000000..f541ba9409db --- /dev/null +++ b/core/hdd/src/wlan_hdd_sysfs_thermal_cfg.c @@ -0,0 +1,208 @@ +/* + * Copyright (c) 2011-2020 The Linux Foundation. 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 above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +/** + * DOC: wlan_hdd_sysfs_thermal_cfg.c + * + * implementation for creating sysfs file thermal_cfg + */ + +#include +#include "osif_psoc_sync.h" +#include +#include +#include "qdf_trace.h" +#include "sme_api.h" +#include "qdf_status.h" + +#ifdef FW_THERMAL_THROTTLE_SUPPORT +#ifndef QCN7605_SUPPORT +static QDF_STATUS hdd_send_thermal_mgmt_cmd(mac_handle_t mac_handle, + uint16_t lower_thresh_deg, + uint16_t higher_thresh_deg) +{ + return sme_set_thermal_mgmt(mac_handle, lower_thresh_deg, + higher_thresh_deg); +} +#else +static QDF_STATUS hdd_send_thermal_mgmt_cmd(mac_handle_t mac_handle, + uint16_t lower_thresh_deg, + uint16_t higher_thresh_deg) +{ + return QDF_STATUS_SUCCESS; +} +#endif +#endif /* FW_THERMAL_THROTTLE_SUPPORT */ + +static ssize_t +__hdd_sysfs_thermal_cfg_store(struct hdd_context *hdd_ctx, + struct kobj_attribute *attr, + const char *buf, + size_t count) +{ + char buf_local[MAX_SYSFS_USER_COMMAND_SIZE_LENGTH + 1]; + char *sptr, *token; + uint32_t val1, val2, val3, val4, val7; + uint16_t val5, val6; + QDF_STATUS status; + int ret; + + if (!wlan_hdd_validate_modules_state(hdd_ctx)) + return -EINVAL; + + ret = hdd_sysfs_validate_and_copy_buf(buf_local, sizeof(buf_local), + buf, count); + + if (ret) { + hdd_err_rl("invalid input"); + return ret; + } + + sptr = buf_local; + hdd_debug("thermal_cfg: count %zu buf_local:(%s)", + count, buf_local); + + /* Get val1 */ + token = strsep(&sptr, " "); + if (!token) + return -EINVAL; + if (kstrtou32(token, 0, &val1)) + return -EINVAL; + + /* Get val2 */ + token = strsep(&sptr, " "); + if (!token) + return -EINVAL; + if (kstrtou32(token, 0, &val2)) + return -EINVAL; + + /* Get val3 */ + token = strsep(&sptr, " "); + if (!token) + return -EINVAL; + if (kstrtou32(token, 0, &val3)) + return -EINVAL; + + /* Get val4 */ + token = strsep(&sptr, " "); + if (!token) + return -EINVAL; + if (kstrtou32(token, 0, &val4)) + return -EINVAL; + + /* Get val5 */ + token = strsep(&sptr, " "); + if (!token) + return -EINVAL; + if (kstrtou16(token, 0, &val5)) + return -EINVAL; + + /* Get val6 */ + token = strsep(&sptr, " "); + if (!token) + return -EINVAL; + if (kstrtou16(token, 0, &val6)) + return -EINVAL; + + /* Get val7 */ + token = strsep(&sptr, " "); + if (!token) + return -EINVAL; + if (kstrtou32(token, 0, &val7)) + return -EINVAL; + + /* Check for valid inputs */ + if (val1 < 0 || val1 > 1 || val2 < 0 || val3 < 0 || val3 > 100 || + val4 < 0 || val4 > 3 || val5 < 0 || val6 < 0 || val7 < 0 || + val6 <= val5) + return -EINVAL; + + status = sme_set_thermal_throttle_cfg(hdd_ctx->mac_handle, + val1, val2, val3, + val4, val7); + + if (QDF_IS_STATUS_ERROR(status)) + return qdf_status_to_os_return(status); + + if (!val7) { + status = hdd_send_thermal_mgmt_cmd(hdd_ctx->mac_handle, + val5, val6); + + if (QDF_IS_STATUS_ERROR(status)) + return qdf_status_to_os_return(status); + } + + return count; +} + +static ssize_t +hdd_sysfs_thermal_cfg_store(struct kobject *kobj, + struct kobj_attribute *attr, + const char *buf, + size_t count) +{ + struct osif_psoc_sync *psoc_sync; + struct hdd_context *hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD); + ssize_t errno_size; + int ret; + + ret = wlan_hdd_validate_context(hdd_ctx); + if (ret != 0) + return ret; + + errno_size = osif_psoc_sync_op_start(wiphy_dev(hdd_ctx->wiphy), + &psoc_sync); + if (errno_size) + return errno_size; + + errno_size = __hdd_sysfs_thermal_cfg_store(hdd_ctx, attr, + buf, count); + + osif_psoc_sync_op_stop(psoc_sync); + + return errno_size; +} + +static struct kobj_attribute thermal_cfg_attribute = + __ATTR(thermal_cfg, 0220, NULL, + hdd_sysfs_thermal_cfg_store); + +int hdd_sysfs_thermal_cfg_create(struct kobject *driver_kobject) +{ + int error; + + if (!driver_kobject) { + hdd_err("could not get driver kobject!"); + return -EINVAL; + } + + error = sysfs_create_file(driver_kobject, + &thermal_cfg_attribute.attr); + if (error) + hdd_err("could not create thermal_cfg sysfs file"); + + return error; +} + +void +hdd_sysfs_thermal_cfg_destroy(struct kobject *driver_kobject) +{ + if (!driver_kobject) { + hdd_err("could not get driver kobject!"); + return; + } + sysfs_remove_file(driver_kobject, &thermal_cfg_attribute.attr); +} diff --git a/core/hdd/src/wlan_hdd_sysfs_thermal_cfg.h b/core/hdd/src/wlan_hdd_sysfs_thermal_cfg.h new file mode 100644 index 000000000000..e38656b9de21 --- /dev/null +++ b/core/hdd/src/wlan_hdd_sysfs_thermal_cfg.h @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2011-2020 The Linux Foundation. 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 above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +/** + * DOC: wlan_hdd_sysfs_thermal_cfg.h + * + * implementation for creating sysfs file thermal_cfg + */ + +#ifndef _WLAN_HDD_SYSFS_THERMAL_CFG_H +#define _WLAN_HDD_SYSFS_THERMAL_CFG_H + +#if defined(WLAN_SYSFS) && defined(CONFIG_WLAN_THERMAL_CFG) +/** + * hdd_sysfs_thermal_cfg_create() - API to create thermal_cfg + * @driver_kobject: sysfs driver kobject + * + * file path: /sys/kernel/wifi/thermal_cfg + * + * usage: + * echo [arg_0] [arg_1] [arg_2] [arg_3] [arg_4] [arg_5] [arg_6] + * > thermal_cfg + * + * Return: 0 on success and errno on failure + */ +int hdd_sysfs_thermal_cfg_create(struct kobject *driver_kobject); + +/** + * hdd_sysfs_thermal_cfg_destroy() - + * API to destroy thermal_cfg + * + * Return: none + */ +void +hdd_sysfs_thermal_cfg_destroy(struct kobject *driver_kobject); +#else +static inline int +hdd_sysfs_thermal_cfg_create(struct kobject *driver_kobject) +{ + return 0; +} + +static inline void +hdd_sysfs_thermal_cfg_destroy(struct kobject *driver_kobject) +{ +} +#endif +#endif /* #ifndef _WLAN_HDD_SYSFS_THERMAL_CFG_H */