From 469051e30f8207d2067b8354de3bb226cd62dc4e Mon Sep 17 00:00:00 2001 From: Chanwoo Choi Date: Wed, 6 Jan 2021 13:55:33 +0900 Subject: [PATCH 01/16] pass: hal: Replace HAL interface with hal-api-power Tizen 6.5 provides new HAL API layer to make tizen porting easy. Power HAL API (hal-api-power) provides HAL C API for controlling the h/w resources such as CPU/GPU/Memory Bus/Memory devices and provides HAL interface for HAL backend developer for using Tizen platform on new h/w device. PASS daemon just calls the Power HAL API without handling the HAL backend anymore. Describe the detailed changes as following: 1. Remove self-defined HAL functions and don't open HAL backend library directly. Instead, use hal-api-power to control the h/w resources. PASS deamon doesn't need to handle the HAL backend library anymore. 2. Remove pass-hal-devel package because of moving HAL interface defintion (src/hal/hal.h) into hal-api-power (hal-power-interface.h). 3. Change the open path of pass configuration files. - /etc/pass/ -> /hal/etc/pass/ Change-Id: I73a1c29c7af000335021faac62157b5342065682 Signed-off-by: Chanwoo Choi --- CMakeLists.txt | 11 +- include/pass/hal/hal.h | 245 --------------- packaging/pass.spec | 21 +- src/hal/CMakeLists.txt | 15 - src/hal/hal-log.h | 29 -- src/hal/hal.c | 92 ------ src/pass/pass-hal.c | 502 +++++------------------------- src/pass/pass-hal.h | 4 +- src/pass/pass-parser.c | 2 +- src/pass/pass-resmon.c | 2 +- src/pass/pass-thermal.c | 2 +- src/pass/pass.c | 2 +- systemd/{pass.service => pass.service.in} | 1 + unittest/CMakeLists.txt | 14 +- unittest/pass_haltests.cpp | 2 +- 15 files changed, 106 insertions(+), 838 deletions(-) delete mode 100644 include/pass/hal/hal.h delete mode 100755 src/hal/CMakeLists.txt delete mode 100644 src/hal/hal-log.h delete mode 100644 src/hal/hal.c rename systemd/{pass.service => pass.service.in} (84%) diff --git a/CMakeLists.txt b/CMakeLists.txt index a069f15..d8f2591 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -7,7 +7,6 @@ PROJECT(pass C) SET(EXEC_PREFIX "${CMAKE_INSTALL_PREFIX}/bin") SET(INCLUDEDIR "${CMAKE_INSTALL_PREFIX}/include/${PROJECT_NAME}") SET(VERSION 0.1.0) -SET(PASS_HAL_NAME pass-hal-devel) SET(SRCS src/pass/pass.c @@ -25,7 +24,6 @@ SET(SRCS src/pmqos/pmqos-parser.c src/thermal/thermal.c src/thermal/thermal-parser.c - src/hal/hal.c src/core/common.c src/core/config-parser.c src/core/device-notifier.c @@ -52,6 +50,8 @@ SET(PKG_MODULES gio-unix-2.0 libudev libsystemd + hal-api-common + hal-api-power ) INCLUDE(FindPkgConfig) @@ -65,6 +65,7 @@ SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} -fvisibility=hidden -fPIE") SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} -g -fno-omit-frame-pointer -finstrument-functions") SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${EXTRA_CFLAGS} -lrt") SET(CMAKE_EXE_LINKER_FLAGS "-pie") +SET(LIBDIR ${CMAKE_LIBDIR_PREFIX}) ADD_DEFINITIONS("-DLOG_TAG=\"PASS\"") ADD_DEFINITIONS("-DPREFIX=\"${CMAKE_INSTALL_PREFIX}\"") @@ -94,23 +95,21 @@ ADD_CUSTOM_COMMAND( COMMENT "Generating GDBus stub for thermal interface") ADD_EXECUTABLE(${PROJECT_NAME} ${SRCS}) -TARGET_LINK_LIBRARIES(${PROJECT_NAME} ${pkgs_LDFLAGS} "-ldl" "-lm") +TARGET_LINK_LIBRARIES(${PROJECT_NAME} ${pkgs_LDFLAGS} -ldl -lm) INSTALL(TARGETS ${PROJECT_NAME} DESTINATION bin) INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/scripts/${PROJECT_NAME}.conf DESTINATION /etc/dbus-1/system.d) INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/scripts/pass-pmqos.conf DESTINATION /etc/pass) INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/scripts/pass-thermal.conf DESTINATION /etc/pass) +CONFIGURE_FILE(${CMAKE_SOURCE_DIR}/systemd/${PROJECT_NAME}.service.in ${CMAKE_SOURCE_DIR}/systemd/${PROJECT_NAME}.service @ONLY) INSTALL(FILES ${CMAKE_SOURCE_DIR}/systemd/org.tizen.system.pass.service DESTINATION /usr/share/dbus-1/system-services) INSTALL(FILES ${CMAKE_SOURCE_DIR}/systemd/org.tizen.system.thermal.service DESTINATION /usr/share/dbus-1/system-services) CONFIGURE_FILE(${PROJECT_NAME}.pc.in ${PROJECT_NAME}.pc @ONLY) INSTALL(FILES ${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}.pc DESTINATION ${LIB_INSTALL_DIR}/pkgconfig) -CONFIGURE_FILE(${PASS_HAL_NAME}.pc.in ${PASS_HAL_NAME}.pc @ONLY) -INSTALL(FILES ${CMAKE_CURRENT_BINARY_DIR}/${PASS_HAL_NAME}.pc DESTINATION ${LIB_INSTALL_DIR}/pkgconfig) INSTALL(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/systemd/ DESTINATION lib/systemd/system FILES_MATCHING PATTERN "*.service" ) -ADD_SUBDIRECTORY(src/hal) ADD_SUBDIRECTORY(unittest) diff --git a/include/pass/hal/hal.h b/include/pass/hal/hal.h deleted file mode 100644 index 3e41493..0000000 --- a/include/pass/hal/hal.h +++ /dev/null @@ -1,245 +0,0 @@ -/* - * Copyright (c) 2017 Samsung Electronics Co., Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef _PASS_HAL_H_ -#define _PASS_HAL_H_ - -#include -#include -#include - -#define BUFF_MAX 255 - -#define MAKE_4B_CODE_4(A, B, C, D) \ - ((((A) & 0xff) << 24) | (((B) & 0xff) << 16) | \ - (((C) & 0xff) << 8) | (((D) & 0xff))) -#define MAKE_TAG_CONSTANT(A, B, C, D) MAKE_4B_CODE_4(A, B, C, D) - -#define HAL_INFO_TAG MAKE_TAG_CONSTANT('P', 'A', 'S', 'S') - -/* Symbolic name of the HAL info (PASS HAL Info) */ -#define HAL_INFO_SYM PassHalInfo - -#define PASS_RESOURCE_UNKNOWN 0 -#define PASS_RESOURCE_CPU_ID 1 -#define PASS_RESOURCE_BUS_ID 2 -#define PASS_RESOURCE_GPU_ID 3 -#define PASS_RESOURCE_MEMORY_ID 4 -#define PASS_RESOURCE_NONSTANDARD_ID 99 - -#define PASS_RESOURCE_CPU_NAME "cpu" -#define PASS_RESOURCE_BUS_NAME "bus" -#define PASS_RESOURCE_GPU_NAME "gpu" -#define PASS_RESOURCE_MEMORY_NAME "memory" -#define PASS_RESOURCE_NONSTANDARD_NAME "nonstandard" - -/** - * Define the common structure - */ - -struct pass_resource_common; - -/* - * pass_resource_info - Define the information structure for the resource. - * - * @magic : magic must be initialized to HAL_INFO_TAG - * @hal_version : HAL version - * @device_version: device version - * @id : device id, can have the following value. - * - PASS_RESOURCE_CPU_ID - * - PASS_RESOURCE_BUS_ID - * - PASS_RESOURCE_GPU_ID - * - PASS_RESOURCE_MEMORY_ID - * - PASS_RESOURCE_NONSTANDARD_ID - * @name : device name, can have the following value. - * - PASS_RESOURCE_CPU_NAME - * - PASS_RESOURCE_BUS_NAME - * - PASS_RESOURCE_GPU_NAME - * - PASS_RESOURCE_MEMORY_NAME - * - PASS_RESOURCE_NONSTANDARD_NAME - * @dso : module's dso - * @resourced[] : reserved for future use - * @open : function pointer to open device - * @close : function pointer to close device - */ -struct pass_resource_info { - uint32_t magic; - uint16_t hal_version; - uint16_t device_version; - const int id; - const char *name; - void *dso; - uint32_t reserved[8]; - - int (*open)(char *res_name, struct pass_resource_info *info, - struct pass_resource_common **common); - int (*close)(char *res_name, struct pass_resource_common *common); -}; - -struct pass_resource_common { - /* indicate to this device information structure */ - struct pass_resource_info *info; -}; - -/* - * Define the ops (operations) structure which are used on specific resource. - */ -struct pass_resource_dvfs_ops { - /* Get and set the current governor. */ - int (*get_curr_governor)(char *res_name, char *governor); - int (*set_curr_governor)(char *res_name, char *governor); - - int (*get_avail_governor)(char *res_name, char **avail_governor); - - /* Get the current frequency. */ - int (*get_curr_freq)(char *res_name); - - /* Get and set the minimum frequency. */ - int (*get_min_freq)(char *res_name); - int (*set_min_freq)(char *res_name, int freq); - - /* Get and set the maximum frequency. */ - int (*get_max_freq)(char *res_name); - int (*set_max_freq)(char *res_name, int freq); - - /* Get the minimum/maximum frequency which can be set to resource. */ - int (*get_available_min_freq)(char *res_name); - int (*get_available_max_freq)(char *res_name); - - /* Get and set the up_threshold to support boosting. */ - int (*get_up_threshold)(char *res_name); - int (*set_up_threshold)(char *res_name, int up_threshold); - - /* Get the load_table of each resource to estimate the system load. */ - int (*get_load_table)(char *name, void *pass_cpu_load_table); -}; - -struct pass_resource_hotplug_ops { - /* Get and set the online status of resource. */ - int (*get_online_state)(char *res_name, int cpu); - int (*set_online_state)(char *res_name, int cpu, int on); - /* Get and set the minimum number of online CPUs */ - int (*get_online_min_num) (char *res_name); - int (*set_online_min_num) (char *res_name, int min_num); - /* Get and set the maximum number of online CPUs */ - int (*get_online_max_num) (char *res_name); - int (*set_online_max_num) (char *res_name, int max_num); -}; - -struct pass_resource_tmu_ops { - /* Get the current temperature of resource. */ - int (*get_temp)(char *res_thermal_name); - - /* Get the policy of thermal management unit. */ - int (*get_policy)(char *res_thermal_name, char *policy); -}; - -/* - * Define the resource structure for CPU H/W. - * - * @common : common resource structure. - * @dvfs : function lists for the DVFS (Dynamic Volt. & Freq. Scaling). - * @tmu : function lists for the TMU (Thermal Management Unit). - * @hotplug : function lists for the CPU on/off. - */ -struct pass_resource_cpu { - struct pass_resource_common common; - - struct pass_resource_dvfs_ops dvfs; - struct pass_resource_tmu_ops tmu; - struct pass_resource_hotplug_ops hotplug; -}; - -/* - * Define the resource structure for Memory Bus H/W. - * - * @common : common resource structure. - * @dvfs : function lists for the DVFS (Dynamic Volt. & Freq. Scaling). - * @tmu : function lists for the TMU (Thermal Management Unit). - */ -struct pass_resource_bus { - struct pass_resource_common common; - - struct pass_resource_dvfs_ops dvfs; - struct pass_resource_tmu_ops tmu; -}; - -/* - * Define the resource structure for GPU H/W. - * - * @common : common resource structure. - * @dvfs : function lists for the DVFS (Dynamic Volt. & Freq. Scaling). - * @tmu : function lists for the TMU (Thermal Management Unit). - */ -struct pass_resource_gpu { - struct pass_resource_common common; - - struct pass_resource_dvfs_ops dvfs; - struct pass_resource_tmu_ops tmu; -}; - -/* - * Define the resource structure for Memory H/W. - * - * @common : common resource structure. - */ -struct pass_resource_memory { - struct pass_resource_common common; - - /* Get and set the /sys/kernel/debug/fault_around_bytes */ - int (*get_fault_around_bytes)(char *res_name); - int (*set_fault_around_bytes)(char *res_name, int fault_around_bytes); -}; - -/* - * Define the resource structure for nonstandard H/W. - * - * Following function is Deprecated. (Not recommended for use) - * @set_pmqos_data : function to bypass the scenario data to HAL. - * - * This structure indicates the nonstandard H/W which doesn't have - * the official supported framework (e.g., cpufreq, devfreq and so on) - * in Linux Kernel. But, the specific device might be controlled - * according to PMQoS scenario or other cases. - */ -struct pass_resource_nonstandard { - struct pass_resource_common common; - - /* - * NOTE: It is not propper method. But PASS must need to keep - * the backwards compatibility, set the PMQoS's data from - * platform to hal. So, It is not recommended to use it. - * - * This function will be removed after finding the proper method. - */ - int (*set_pmqos_data)(char *res_name, void *data); -}; - -int pass_get_hal_info(const char *id, const struct pass_resource_info **info); - -/** - * Structure define of HAL info module - * - * All HAL module should be use below define to make a specific - * structure for Tizen HAL. pass_get_resource_info function - * will load a pass_resource_data structure by using TizenHwInfo name - * at runtime. TizenHwInfo means Tizen Hardware Info. - */ -#define HAL_MODULE_STRUCTURE \ - __attribute__ ((visibility("default"))) \ - struct pass_resource_info HAL_INFO_SYM - -#endif /* _PASS_HAL_H_ */ diff --git a/packaging/pass.spec b/packaging/pass.spec index 89d837b..9e16a7a 100644 --- a/packaging/pass.spec +++ b/packaging/pass.spec @@ -1,7 +1,6 @@ %define _unpackaged_files_terminate_build 0 %define daemon_name pass -%define hal_name pass-hal-devel %define haltest_name pass-haltests %define unittest_name pass-unittest @@ -13,7 +12,6 @@ Group: System/Kernel License: Apache-2.0 Source0: %{name}-%{version}.tar.gz Source1: %{name}.manifest -Source2: %{hal_name}.manifest BuildRequires: cmake BuildRequires: pkgconfig(dlog) @@ -24,6 +22,8 @@ BuildRequires: pkgconfig(glib-2.0) BuildRequires: pkgconfig(gmock) BuildRequires: pkgconfig(libudev) BuildRequires: pkgconfig(libsystemd) +BuildRequires: pkgconfig(hal-api-common) +BuildRequires: pkgconfig(hal-api-power) %description PASS (Power-Aware System Service) @@ -35,14 +35,6 @@ Group: main %description %{daemon_name} PASS systemd daemon. -%package -n %{hal_name} -Summary: PASS HAL Header files -Group: Development/Library -Requires: pass = %{version}-%{release} - -%description -n %{hal_name} -Header files required to build pass-hal packages for specific boards. - %package -n %{haltest_name} Summary: PASS HAL test package with gtest Group: Development/Tools @@ -65,11 +57,11 @@ PASS unit test package with gtest %cmake . \ -DTZ_SYS_ETC=%TZ_SYS_ETC \ -DCMAKE_INSTALL_PREFIX=%{_prefix} \ + -DCMAKE_LIBDIR_PREFIX=%{_libdir} \ #eol %build cp %{SOURCE1} . -cp %{SOURCE2} . make %{?jobs:-j%jobs} %install @@ -106,13 +98,6 @@ systemctl daemon-reload %{_datadir}/dbus-1/system-services/org.tizen.system.pass.service %{_datadir}/dbus-1/system-services/org.tizen.system.thermal.service -%files -n %{hal_name} -%defattr(-,root,root,-) -%manifest %{hal_name}.manifest -%{_includedir}/%{daemon_name}/hal.h -%{_includedir}/%{daemon_name}/hal-log.h -%{_libdir}/pkgconfig/%{hal_name}.pc - %files -n %{haltest_name} %defattr(-,root,root,-) %{_bindir}/pass_haltests diff --git a/src/hal/CMakeLists.txt b/src/hal/CMakeLists.txt deleted file mode 100755 index c0f1fbc..0000000 --- a/src/hal/CMakeLists.txt +++ /dev/null @@ -1,15 +0,0 @@ -CMAKE_MINIMUM_REQUIRED(VERSION 2.6) -PROJECT(pass-hal-devel C) - -SET(HAL_HEADERS - ../../include/pass/hal/hal.h - hal-log.h -) - -INCLUDE(FindPkgConfig) -pkg_check_modules(pkgs REQUIRED - dlog) - -FOREACH(hheader ${HAL_HEADERS}) - INSTALL(FILES ${hheader} DESTINATION ${INCLUDEDIR}) -ENDFOREACH(hheader) diff --git a/src/hal/hal-log.h b/src/hal/hal-log.h deleted file mode 100644 index 4b43f61..0000000 --- a/src/hal/hal-log.h +++ /dev/null @@ -1,29 +0,0 @@ -/* - * PASS (Power Aware System Service) - * - * Copyright (c) 2017 Samsung Electronics Co., Ltd. - * - * Licensed under the Apache License, Version 2.0 (the License); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef __HAL_LOG_H__ -#define __HAL_LOG_H__ - -#include - -#define _D(fmt, arg...) do { SLOGD(fmt, ##arg); } while (0) -#define _I(fmt, arg...) do { SLOGI(fmt, ##arg); } while (0) -#define _W(fmt, arg...) do { SLOGW(fmt, ##arg); } while (0) -#define _E(fmt, arg...) do { SLOGE(fmt, ##arg); } while (0) - -#endif /* __HAL_LOG_H__ */ diff --git a/src/hal/hal.c b/src/hal/hal.c deleted file mode 100644 index 0b2cffa..0000000 --- a/src/hal/hal.c +++ /dev/null @@ -1,92 +0,0 @@ -/* - * PASS (Power Aware System Service) HAL - * - * Copyright (c) 2017 Samsung Electronics Co., Ltd. - * - * Licensed under the Apache License, Version 2.0 (the License); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** - * @file hal.c - * @brief Provide a helper function to load shared library, like cpu.so - * /gpu.so/bus.so etc, from HAL (Hardware Abstract Layer) - * package according to the type of h/w resource. - * @ingroup COM_POWER_MGNT - */ - -#include -#include -#include -#include -#include -#include -#include - -#include - -#include "hal-log.h" - -#ifndef EXPORT -#define EXPORT __attribute__ ((visibility("default"))) -#endif - -#ifndef LIBPATH -#error LIBPATH is not defined. -#endif - -#define MODULE_PATH LIBPATH"/pass" - -#define STRINGIZE2(s) #s -#define STRINGIZE(s) STRINGIZE2(s) - -EXPORT -int pass_get_hal_info(const char *name, const struct pass_resource_info **info) -{ - char path[PATH_MAX]; - void *handle; - struct pass_resource_info *it; - - if (!info || !name) - return -EINVAL; - - /* Load module */ - snprintf(path, sizeof(path), "%s/%s.so", MODULE_PATH, name); - handle = dlopen(path, RTLD_NOW); - if (!handle) { - _E("fail to open module : %s", dlerror()); - goto error; - } - - it = dlsym(handle, STRINGIZE(HAL_INFO_SYM)); - if (!it) { - _E("fail to find symbol : %s", dlerror()); - goto error; - } - - /* Check id */ - if (strncmp(name, it->name, strlen(name)) != 0) { - _E("fail to match name : name(%s), it->name(%s)", name, - it->name); - goto error; - } - - it->dso = handle; - *info = it; - return 0; - -error: - if (handle) - dlclose(handle); - - return -ENOENT; -} diff --git a/src/pass/pass-hal.c b/src/pass/pass-hal.c index 0ba680f..f2229f7 100644 --- a/src/pass/pass-hal.c +++ b/src/pass/pass-hal.c @@ -38,64 +38,6 @@ #include "pass.h" #include "pass-hal.h" -static struct pass_resource_dvfs_ops *get_dvfs(struct pass_resource *res, - int res_type) -{ - struct pass_resource_dvfs_ops *dvfs = NULL; - - switch (res_type) { - case PASS_RESOURCE_CPU_ID: - dvfs = &(res->hal.cpu->dvfs); - break; - case PASS_RESOURCE_BUS_ID: - dvfs = &(res->hal.bus->dvfs); - break; - case PASS_RESOURCE_GPU_ID: - dvfs = &(res->hal.gpu->dvfs); - break; - } - - return dvfs; -} - -static struct pass_resource_tmu_ops *get_tmu(struct pass_resource *res, - int res_type) -{ - struct pass_resource_tmu_ops *tmu = NULL; - - switch (res_type) { - case PASS_RESOURCE_CPU_ID: - tmu = &(res->hal.cpu->tmu); - break; - case PASS_RESOURCE_BUS_ID: - tmu = &(res->hal.bus->tmu); - break; - case PASS_RESOURCE_GPU_ID: - tmu = &(res->hal.gpu->tmu); - break; - } - - return tmu; -} - -static struct pass_resource_hotplug_ops *get_hotplug(struct pass_resource *res, - int res_type) -{ - struct pass_resource_hotplug_ops *hotplug = NULL; - - switch (res_type) { - case PASS_RESOURCE_CPU_ID: - hotplug = &(res->hal.cpu->hotplug); - break; - case PASS_RESOURCE_BUS_ID: - case PASS_RESOURCE_GPU_ID: - hotplug = NULL; - break; - } - - return hotplug; -} - /** * @brief Get the current governor for DVFS(Dynamic Voltage and Frequency * Scaling) resource @@ -104,23 +46,16 @@ static struct pass_resource_hotplug_ops *get_hotplug(struct pass_resource *res, * @return @c 0 on success, otherwise error value * @retval -22 Invalid argument (-EINVAL) * @retval -1 Operation not permitted (-EPERM) - * @retval -19 Operation not supported (-ENODEV) + * @retval -19 Operation not supported (-ENOTSUP) */ int pass_hal_get_curr_governor(struct pass_resource *res, char *governor) { - struct pass_resource_dvfs_ops *dvfs; - if (!res || !governor) return -EINVAL; - dvfs = get_dvfs(res, res->config_data.res_type); - if (!dvfs) - return -EPERM; - - if (!dvfs->get_curr_governor) - return -ENODEV; - - return dvfs->get_curr_governor(res->config_data.res_name, governor); + return hal_power_dvfs_get_curr_governor(res->config_data.res_type, + res->config_data.res_name, + governor); } /** @@ -131,23 +66,16 @@ int pass_hal_get_curr_governor(struct pass_resource *res, char *governor) * @return @c 0 on success, otherwise error value * @retval -22 Invalid argument (-EINVAL) * @retval -1 Operation not permitted (-EPERM) - * @retval -19 Operation not supported (-ENODEV) + * @retval -19 Operation not supported (-ENOTSUP) */ int pass_hal_set_curr_governor(struct pass_resource *res, char *governor) { - struct pass_resource_dvfs_ops *dvfs; - if (!res || !governor) return -EINVAL; - dvfs = get_dvfs(res, res->config_data.res_type); - if (!dvfs) - return -EPERM; - - if (!dvfs->set_curr_governor) - return -ENODEV; - - return dvfs->set_curr_governor(res->config_data.res_name, governor); + return hal_power_dvfs_set_curr_governor(res->config_data.res_type, + res->config_data.res_name, + governor); } /** @@ -157,23 +85,15 @@ int pass_hal_set_curr_governor(struct pass_resource *res, char *governor) * @return @c positive integer on success, otherwise error value * @retval -22 Invalid argument (-EINVAL) * @retval -1 Operation not permitted (-EPERM) - * @retval -19 Operation not supported (-ENODEV) + * @retval -19 Operation not supported (-ENOTSUP) */ int pass_hal_get_curr_freq(struct pass_resource *res) { - struct pass_resource_dvfs_ops *dvfs; - if (!res) return -EINVAL; - dvfs = get_dvfs(res, res->config_data.res_type); - if (!dvfs) - return -EPERM; - - if (!dvfs->get_curr_freq) - return -ENODEV; - - return dvfs->get_curr_freq(res->config_data.res_name); + return hal_power_dvfs_get_curr_freq(res->config_data.res_type, + res->config_data.res_name); } /** @@ -183,23 +103,15 @@ int pass_hal_get_curr_freq(struct pass_resource *res) * @return @c positive integer on success, otherwise error value * @retval -22 Invalid argument (-EINVAL) * @retval -1 Operation not permitted (-EPERM) - * @retval -19 Operation not supported (-ENODEV) + * @retval -19 Operation not supported (-ENOTSUP) */ int pass_hal_get_min_freq(struct pass_resource *res) { - struct pass_resource_dvfs_ops *dvfs; - if (!res) return -EINVAL; - dvfs = get_dvfs(res, res->config_data.res_type); - if (!dvfs) - return -EPERM; - - if (!dvfs->get_min_freq) - return -ENODEV; - - return dvfs->get_min_freq(res->config_data.res_name); + return hal_power_dvfs_get_min_freq(res->config_data.res_type, + res->config_data.res_name); } /** @@ -210,23 +122,16 @@ int pass_hal_get_min_freq(struct pass_resource *res) * @return @c positive integer on success, otherwise error value * @retval -22 Invalid argument (-EINVAL) * @retval -1 Operation not permitted (-EPERM) - * @retval -19 Operation not supported (-ENODEV) + * @retval -19 Operation not supported (-ENOTSUP) */ int pass_hal_set_min_freq(struct pass_resource *res, int freq) { - struct pass_resource_dvfs_ops *dvfs; - if (!res || freq < 0) return -EINVAL; - dvfs = get_dvfs(res, res->config_data.res_type); - if (!dvfs) - return -EPERM; - - if (!dvfs->set_min_freq) - return -ENODEV; - - return dvfs->set_min_freq(res->config_data.res_name, freq); + return hal_power_dvfs_set_min_freq(res->config_data.res_type, + res->config_data.res_name, + freq); } /** @@ -236,23 +141,15 @@ int pass_hal_set_min_freq(struct pass_resource *res, int freq) * @return @c positive integer on success, otherwise error value * @retval -22 Invalid argument (-EINVAL) * @retval -1 Operation not permitted (-EPERM) - * @retval -19 Operation not supported (-ENODEV) + * @retval -19 Operation not supported (-ENOTSUP) */ int pass_hal_get_max_freq(struct pass_resource *res) { - struct pass_resource_dvfs_ops *dvfs; - if (!res) return -EINVAL; - dvfs = get_dvfs(res, res->config_data.res_type); - if (!dvfs) - return -EPERM; - - if (!dvfs->get_max_freq) - return -ENODEV; - - return dvfs->get_max_freq(res->config_data.res_name); + return hal_power_dvfs_get_max_freq(res->config_data.res_type, + res->config_data.res_name); } /** @@ -263,23 +160,16 @@ int pass_hal_get_max_freq(struct pass_resource *res) * @return @c positive integer on success, otherwise error value * @retval -22 Invalid argument (-EINVAL) * @retval -1 Operation not permitted (-EPERM) - * @retval -19 Operation not supported (-ENODEV) + * @retval -19 Operation not supported (-ENOTSUP) */ int pass_hal_set_max_freq(struct pass_resource *res, int freq) { - struct pass_resource_dvfs_ops *dvfs; - if (!res || freq < 0) return -EINVAL; - dvfs = get_dvfs(res, res->config_data.res_type); - if (!dvfs) - return -EPERM; - - if (!dvfs->set_max_freq) - return -ENODEV; - - return dvfs->set_max_freq(res->config_data.res_name, freq); + return hal_power_dvfs_set_max_freq(res->config_data.res_type, + res->config_data.res_name, + freq); } /** @@ -289,23 +179,15 @@ int pass_hal_set_max_freq(struct pass_resource *res, int freq) * @return @c positive integer on success, otherwise error value * @retval -22 Invalid argument (-EINVAL) * @retval -1 Operation not permitted (-EPERM) - * @retval -19 Operation not supported (-ENODEV) + * @retval -19 Operation not supported (-ENOTSUP) */ int pass_hal_get_available_min_freq(struct pass_resource *res) { - struct pass_resource_dvfs_ops *dvfs; - if (!res) return -EINVAL; - dvfs = get_dvfs(res, res->config_data.res_type); - if (!dvfs) - return -EPERM; - - if (!dvfs->get_available_min_freq) - return -ENODEV; - - return dvfs->get_available_min_freq(res->config_data.res_name); + return hal_power_dvfs_get_available_min_freq(res->config_data.res_type, + res->config_data.res_name); } /** @@ -315,23 +197,15 @@ int pass_hal_get_available_min_freq(struct pass_resource *res) * @return @c positive integer on success, otherwise error value * @retval -22 Invalid argument (-EINVAL) * @retval -1 Operation not permitted (-EPERM) - * @retval -19 Operation not supported (-ENODEV) + * @retval -19 Operation not supported (-ENOTSUP) */ int pass_hal_get_available_max_freq(struct pass_resource *res) { - struct pass_resource_dvfs_ops *dvfs; - if (!res) return -EINVAL; - dvfs = get_dvfs(res, res->config_data.res_type); - if (!dvfs) - return -EPERM; - - if (!dvfs->get_available_max_freq) - return -ENODEV; - - return dvfs->get_available_max_freq(res->config_data.res_name); + return hal_power_dvfs_get_available_max_freq(res->config_data.res_type, + res->config_data.res_name); } /** @@ -341,23 +215,15 @@ int pass_hal_get_available_max_freq(struct pass_resource *res) * @return @c positive integer on success, otherwise error value * @retval -22 Invalid argument (-EINVAL) * @retval -1 Operation not permitted (-EPERM) - * @retval -19 Operation not supported (-ENODEV) + * @retval -19 Operation not supported (-ENOTSUP) */ int pass_hal_get_up_threshold(struct pass_resource *res) { - struct pass_resource_dvfs_ops *dvfs; - if (!res) return -EINVAL; - dvfs = get_dvfs(res, res->config_data.res_type); - if (!dvfs) - return -EPERM; - - if (!dvfs->get_up_threshold) - return -ENODEV; - - return dvfs->get_up_threshold(res->config_data.res_name); + return hal_power_dvfs_get_up_threshold(res->config_data.res_type, + res->config_data.res_name); } /** @@ -368,23 +234,16 @@ int pass_hal_get_up_threshold(struct pass_resource *res) * @return @c positive integer on success, otherwise error value * @retval -22 Invalid argument (-EINVAL) * @retval -1 Operation not permitted (-EPERM) - * @retval -19 Operation not supported (-ENODEV) + * @retval -19 Operation not supported (-ENOTSUP) */ int pass_hal_set_up_threshold(struct pass_resource *res, int up_threshold) { - struct pass_resource_dvfs_ops *dvfs; - if (!res || up_threshold < 0) return -EINVAL; - dvfs = get_dvfs(res, res->config_data.res_type); - if (!dvfs) - return -EPERM; - - if (!dvfs->set_up_threshold) - return -ENODEV; - - return dvfs->set_up_threshold(res->config_data.res_name, up_threshold); + return hal_power_dvfs_set_up_threshold(res->config_data.res_type, + res->config_data.res_name, + up_threshold); } /** @@ -394,23 +253,16 @@ int pass_hal_set_up_threshold(struct pass_resource *res, int up_threshold) * @return @c positive integer on success, otherwise error value * @retval -22 Invalid argument (-EINVAL) * @retval -1 Operation not permitted (-EPERM) - * @retval -19 Operation not supported (-ENODEV) + * @retval -19 Operation not supported (-ENOTSUP) */ int pass_hal_get_online_state(struct pass_resource *res, int cpu) { - struct pass_resource_hotplug_ops *hotplug; - if (!res || cpu < 0) return -EINVAL; - hotplug = get_hotplug(res, res->config_data.res_type); - if (!hotplug) - return -EPERM; - - if (!hotplug->get_online_state) - return -ENODEV; - - return hotplug->get_online_state(res->config_data.res_name, cpu); + return hal_power_hotplug_get_online_state(res->config_data.res_type, + res->config_data.res_name, + cpu); } /** @@ -421,23 +273,16 @@ int pass_hal_get_online_state(struct pass_resource *res, int cpu) * @return @c 0 on success, otherwise error value * @retval -22 Invalid argument (-EINVAL) * @retval -1 Operation not permitted (-EPERM) - * @retval -19 Operation not supported (-ENODEV) + * @retval -19 Operation not supported (-ENOTSUP) */ int pass_hal_set_online_state(struct pass_resource *res, int cpu, int on) { - struct pass_resource_hotplug_ops *hotplug; - if (!res || cpu < 0 || on < 0) return -EINVAL; - hotplug = get_hotplug(res, res->config_data.res_type); - if (!hotplug) - return -EPERM; - - if (!hotplug->set_online_state) - return -ENODEV; - - return hotplug->set_online_state(res->config_data.res_name, cpu, on); + return hal_power_hotplug_set_online_state(res->config_data.res_type, + res->config_data.res_name, + cpu, on); } /** @@ -446,23 +291,15 @@ int pass_hal_set_online_state(struct pass_resource *res, int cpu, int on) * @return @c positive integer on success, otherwise error value * @retval -22 Invalid argument (-EINVAL) * @retval -1 Operation not permitted (-EPERM) - * @retval -19 Operation not supported (-ENODEV) + * @retval -19 Operation not supported (-ENOTSUP) */ int pass_hal_get_online_min_num(struct pass_resource *res) { - struct pass_resource_hotplug_ops *hotplug; - if (!res) return -EINVAL; - hotplug = get_hotplug(res, res->config_data.res_type); - if (!hotplug) - return -EPERM; - - if (!hotplug->get_online_min_num) - return -ENODEV; - - return hotplug->get_online_min_num(res->config_data.res_name); + return hal_power_hotplug_get_online_min_num(res->config_data.res_type, + res->config_data.res_name); } /** @@ -472,23 +309,16 @@ int pass_hal_get_online_min_num(struct pass_resource *res) * @return @c 0 on success, otherwise error value * @retval -22 Invalid argument (-EINVAL) * @retval -1 Operation not permitted (-EPERM) - * @retval -19 Operation not supported (-ENODEV) + * @retval -19 Operation not supported (-ENOTSUP) */ int pass_hal_set_online_min_num(struct pass_resource *res, int num) { - struct pass_resource_hotplug_ops *hotplug; - if ((!res) || (num < 0)) return -EINVAL; - hotplug = get_hotplug(res, res->config_data.res_type); - if (!hotplug) - return -EPERM; - - if (!hotplug->set_online_min_num) - return -ENODEV; - - return hotplug->set_online_min_num(res->config_data.res_name, num); + return hal_power_hotplug_set_online_min_num(res->config_data.res_type, + res->config_data.res_name, + num); } /** @@ -497,23 +327,15 @@ int pass_hal_set_online_min_num(struct pass_resource *res, int num) * @return @c positive integer on success, otherwise error value * @retval -22 Invalid argument (-EINVAL) * @retval -1 Operation not permitted (-EPERM) - * @retval -19 Operation not supported (-ENODEV) + * @retval -19 Operation not supported (-ENOTSUP) */ int pass_hal_get_online_max_num(struct pass_resource *res) { - struct pass_resource_hotplug_ops *hotplug; - if (!res) return -EINVAL; - hotplug = get_hotplug(res, res->config_data.res_type); - if (!hotplug) - return -EPERM; - - if (!hotplug->get_online_max_num) - return -ENODEV; - - return hotplug->get_online_max_num(res->config_data.res_name); + return hal_power_hotplug_get_online_max_num(res->config_data.res_type, + res->config_data.res_name); } /** @@ -523,23 +345,16 @@ int pass_hal_get_online_max_num(struct pass_resource *res) * @return @c 0 on success, otherwise error value * @retval -22 Invalid argument (-EINVAL) * @retval -1 Operation not permitted (-EPERM) - * @retval -19 Operation not supported (-ENODEV) + * @retval -19 Operation not supported (-ENOTSUP) */ int pass_hal_set_online_max_num(struct pass_resource *res, int num) { - struct pass_resource_hotplug_ops *hotplug; - if ((!res) || (num < 0)) return -EINVAL; - hotplug = get_hotplug(res, res->config_data.res_type); - if (!hotplug) - return -EPERM; - - if (!hotplug->set_online_max_num) - return -ENODEV; - - return hotplug->set_online_max_num(res->config_data.res_name, num); + return hal_power_hotplug_set_online_max_num(res->config_data.res_type, + res->config_data.res_name, + num); } /** @@ -548,27 +363,19 @@ int pass_hal_set_online_max_num(struct pass_resource *res, int num) * @return @c integer (both positive and negative are possible) on success * @retval -22 Invalid argument (-EINVAL) * @retval -1 Operation not permitted (-EPERM) - * @retval -19 Operation not supported (-ENODEV) + * @retval -19 Operation not supported (-ENOTSUP) */ int pass_hal_get_temp(struct pass_resource *res) { - struct pass_resource_tmu_ops *tmu; - if (!res) return -EINVAL; - tmu = get_tmu(res, res->config_data.res_type); - if (!tmu) - return -EPERM; - - if (!tmu->get_temp) - return -ENODEV; - /* * In the case of the HAL TMU ops, res_thermal_name is used * as the first argument instead of res_name. */ - return tmu->get_temp(res->config_data.res_thermal_name); + return hal_power_thermal_get_temp(res->config_data.res_type, + res->config_data.res_thermal_name); } /** @@ -578,27 +385,20 @@ int pass_hal_get_temp(struct pass_resource *res) * @return @c 0 on success, otherwise error value * @retval -22 Invalid argument (-EINVAL) * @retval -1 Operation not permitted (-EPERM) - * @retval -19 Operation not supported (-ENODEV) + * @retval -19 Operation not supported (-ENOTSUP) */ int pass_hal_get_tmu_policy(struct pass_resource *res, char *policy) { - struct pass_resource_tmu_ops *tmu; - if (!res || !policy) return -EINVAL; - tmu = get_tmu(res, res->config_data.res_type); - if (!tmu) - return -EPERM; - - if (!tmu->get_policy) - return -ENODEV; - /* * In the case of the HAL TMU ops, res_thermal_name is used * as the first argument instead of res_name. */ - return tmu->get_policy(res->config_data.res_thermal_name, policy); + return hal_power_thermal_get_policy(res->config_data.res_type, + res->config_data.res_thermal_name, + policy); } /** @@ -609,28 +409,17 @@ int pass_hal_get_tmu_policy(struct pass_resource *res, char *policy) * @return @c 0 on success, otherwise error value * @retval -22 Invalid argument (-EINVAL) * @retval -1 Operation not permitted (-EPERM) - * @retval -19 Operation not supported (-ENODEV) + * @retval -19 Operation not supported (-ENOTSUP) */ int pass_hal_set_fault_around_bytes(struct pass_resource *res, int fault_around_bytes) { - struct pass_resource_memory *memory; - if (!res) return -EINVAL; - switch (res->config_data.res_type) { - case PASS_RESOURCE_MEMORY_ID: - memory = res->hal.memory; - break; - default: - return -EPERM; - } - - if (!memory->set_fault_around_bytes) - return -ENODEV; - - return memory->set_fault_around_bytes(res->config_data.res_name, fault_around_bytes); + return hal_power_memory_set_fault_around_bytes(res->config_data.res_type, + res->config_data.res_name, + fault_around_bytes); } /** @@ -639,27 +428,15 @@ int pass_hal_set_fault_around_bytes(struct pass_resource *res, * @return @c positive integer on success, otherwise error value * @retval -22 Invalid argument (-EINVAL) * @retval -1 Operation not permitted (-EPERM) - * @retval -19 Operation not supported (-ENODEV) + * @retval -19 Operation not supported (-ENOTSUP) */ int pass_hal_get_fault_around_bytes(struct pass_resource *res) { - struct pass_resource_memory *memory; - if (!res) return -EINVAL; - switch (res->config_data.res_type) { - case PASS_RESOURCE_MEMORY_ID: - memory = res->hal.memory; - break; - default: - return -EPERM; - } - - if (!memory->get_fault_around_bytes) - return -ENODEV; - - return memory->get_fault_around_bytes(res->config_data.res_name); + return hal_power_memory_get_fault_around_bytes(res->config_data.res_type, + res->config_data.res_name); } /** @@ -668,27 +445,15 @@ int pass_hal_get_fault_around_bytes(struct pass_resource *res) * @return @c 0 on success, otherwise error value * @retval -22 Invalid argument (-EINVAL) * @retval -1 Operation not permitted (-EPERM) - * @retval -19 Operation not supported (-ENODEV) + * @retval -19 Operation not supported (-ENOTSUP) */ int pass_hal_set_pmqos_data(struct pass_resource *res, void *data) { - struct pass_resource_nonstandard *nonstandard = NULL; - if (!res || !data) return -EINVAL; - switch (res->config_data.res_type) { - case PASS_RESOURCE_NONSTANDARD_ID: - nonstandard = (res->hal.nonstandard); - break; - default: - return -EPERM; - } - - if (!nonstandard->set_pmqos_data) - return -ENODEV; - - return nonstandard->set_pmqos_data(res->config_data.res_name, data); + return hal_power_misc_set_pmqos_data(res->config_data.res_type, + res->config_data.res_name, data); } /** @@ -990,79 +755,10 @@ int pass_hal_restore_initdata(struct pass_resource *res) */ int pass_hal_get_resource(struct pass_resource *res) { - struct pass_resource_info *info; - const char *name; - int ret; - if (!res) return -EINVAL; - switch (res->config_data.res_type) { - case PASS_RESOURCE_CPU_ID: - name = PASS_RESOURCE_CPU_NAME; - break; - case PASS_RESOURCE_BUS_ID: - name = PASS_RESOURCE_BUS_NAME; - break; - case PASS_RESOURCE_GPU_ID: - name = PASS_RESOURCE_GPU_NAME; - break; - case PASS_RESOURCE_MEMORY_ID: - name = PASS_RESOURCE_MEMORY_NAME; - break; - case PASS_RESOURCE_NONSTANDARD_ID: - name = PASS_RESOURCE_NONSTANDARD_NAME; - break; - default: - _E("Unsupported resource type (type: %d)\n", - res->config_data.res_type); - return -EINVAL; - }; - - ret = pass_get_hal_info(name, - (const struct pass_resource_info **)&info); - if (ret < 0) { - _E("Failed to get %s.so for '%s' resource\n", - name, res->config_data.res_name); - return -EINVAL; - } - - if (!info->open || !info->close) { - _E("Failed to get functions of %s.so for '%s' resource\n", - name, res->config_data.res_name); - return -EPERM; - } - - switch (res->config_data.res_type) { - case PASS_RESOURCE_CPU_ID: - ret = info->open(res->config_data.res_name, info, - (struct pass_resource_common**)&res->hal.cpu); - break; - case PASS_RESOURCE_BUS_ID: - ret = info->open(res->config_data.res_name, info, - (struct pass_resource_common**)&res->hal.bus); - break; - case PASS_RESOURCE_GPU_ID: - ret = info->open(res->config_data.res_name, info, - (struct pass_resource_common**)&res->hal.gpu); - break; - case PASS_RESOURCE_MEMORY_ID: - ret = info->open(res->config_data.res_name, info, - (struct pass_resource_common**)&res->hal.memory); - break; - case PASS_RESOURCE_NONSTANDARD_ID: - ret = info->open(res->config_data.res_name, info, - (struct pass_resource_common**)&res->hal.nonstandard); - break; - }; - - if (ret < 0) { - _E("Failed to open %s.so for '%s' resource\n", - name, res->config_data.res_name); - return -EINVAL; - } - - return 0; + return hal_power_get_backend(res->config_data.res_type); } /** @@ -1073,48 +769,8 @@ int pass_hal_get_resource(struct pass_resource *res) */ int pass_hal_put_resource(struct pass_resource *res) { - struct pass_resource_common *common; - struct pass_resource_info *info; - int ret; - if (!res) return -EINVAL; - switch (res->config_data.res_type) { - case PASS_RESOURCE_CPU_ID: - common = (struct pass_resource_common*)res->hal.cpu; - info = res->hal.cpu->common.info; - ret = info->close(res->config_data.res_name, common); - break; - case PASS_RESOURCE_BUS_ID: - common = (struct pass_resource_common*)res->hal.bus; - info = res->hal.bus->common.info; - ret = info->close(res->config_data.res_name, common); - break; - case PASS_RESOURCE_GPU_ID: - common = (struct pass_resource_common*)res->hal.gpu; - info = res->hal.gpu->common.info; - ret = info->close(res->config_data.res_name, common); - break; - case PASS_RESOURCE_MEMORY_ID: - common = (struct pass_resource_common*)res->hal.memory; - info = res->hal.memory->common.info; - ret = info->close(res->config_data.res_name, common); - break; - case PASS_RESOURCE_NONSTANDARD_ID: - common = (struct pass_resource_common*)res->hal.nonstandard; - info = res->hal.nonstandard->common.info; - ret = info->close(res->config_data.res_name, common); - break; - default: - return -EINVAL; - }; - - if (ret < 0) { - _E("Failed to close %s.so for '%s' resource\n", - info->name, res->config_data.res_name); - return -EINVAL; - } - - return 0; + return hal_power_put_backend(); } diff --git a/src/pass/pass-hal.h b/src/pass/pass-hal.h index 6329602..43b45e3 100644 --- a/src/pass/pass-hal.h +++ b/src/pass/pass-hal.h @@ -31,7 +31,9 @@ #ifndef __PASS_HAL__ #define __PASS_HAL__ -#include +#include + +struct pass_resource; /*** * Functions for all H/W resources diff --git a/src/pass/pass-parser.c b/src/pass/pass-parser.c index 38c6392..dac9724 100644 --- a/src/pass/pass-parser.c +++ b/src/pass/pass-parser.c @@ -40,7 +40,7 @@ #include #include -#include +#include #include "pass.h" diff --git a/src/pass/pass-resmon.c b/src/pass/pass-resmon.c index faf7fc7..8c42e08 100644 --- a/src/pass/pass-resmon.c +++ b/src/pass/pass-resmon.c @@ -40,7 +40,7 @@ #include #include -#include +#include #include "pass.h" #include "pass-hal.h" diff --git a/src/pass/pass-thermal.c b/src/pass/pass-thermal.c index fc3b088..5ef9eb3 100644 --- a/src/pass/pass-thermal.c +++ b/src/pass/pass-thermal.c @@ -26,8 +26,8 @@ */ #include -#include #include +#include #include "pass.h" #include "pass-rescon.h" diff --git a/src/pass/pass.c b/src/pass/pass.c index 764df84..ae9592f 100644 --- a/src/pass/pass.c +++ b/src/pass/pass.c @@ -42,7 +42,7 @@ #include "pass-parser.h" #include "pass-hal.h" -#define PASS_CONF_PATH "/etc/pass/pass.conf" +#define PASS_CONF_PATH "/hal/etc/pass/pass.conf" /** * @brief Specify the supported modules according to the type of h/w diff --git a/systemd/pass.service b/systemd/pass.service.in similarity index 84% rename from systemd/pass.service rename to systemd/pass.service.in index 13b8bcf..a774f5f 100644 --- a/systemd/pass.service +++ b/systemd/pass.service.in @@ -10,6 +10,7 @@ RestartSec=0 KillSignal=SIGUSR1 User=system_fw Group=system_fw +Environment=LD_LIBRARY_PATH=@LIBDIR@/hal [Install] WantedBy=delayed.target diff --git a/unittest/CMakeLists.txt b/unittest/CMakeLists.txt index 99c5bdc..7aeae05 100644 --- a/unittest/CMakeLists.txt +++ b/unittest/CMakeLists.txt @@ -1,7 +1,6 @@ PROJECT(pass C CXX) -SET(SRCS ${CMAKE_SOURCE_DIR}/src/hal/hal.c - ${CMAKE_SOURCE_DIR}/src/pass/pass-hal.c +SET(SRCS ${CMAKE_SOURCE_DIR}/src/pass/pass-hal.c ${CMAKE_SOURCE_DIR}/src/pass/pass-parser.c ${CMAKE_SOURCE_DIR}/src/core/common.c ${CMAKE_SOURCE_DIR}/src/core/config-parser.c @@ -13,7 +12,14 @@ INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/src/pass) INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/include) INCLUDE(FindPkgConfig) -pkg_check_modules(gtest_pkgs REQUIRED glib-2.0 gio-2.0 gmock dlog) +pkg_check_modules(gtest_pkgs REQUIRED + glib-2.0 + gio-2.0 + gmock + dlog + hal-api-common + hal-api-power +) FOREACH(flag ${gtest_pkgs_CFLAGS}) SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} ${flag}") @@ -29,6 +35,6 @@ FOREACH(src ${sources}) GET_FILENAME_COMPONENT(src_name ${src} NAME_WE) MESSAGE("${src_name}") ADD_EXECUTABLE(${src_name} ${SRCS} ${src}) - TARGET_LINK_LIBRARIES(${src_name} ${gtest_LDFLAGS} ${gtest_pkgs_LDFLAGS} -ldl) + TARGET_LINK_LIBRARIES(${src_name} ${gtest_LDFLAGS} ${gtest_pkgs_LDFLAGS} -ldl -L${LIBDIR}/hal) INSTALL(TARGETS ${src_name} DESTINATION bin) ENDFOREACH() diff --git a/unittest/pass_haltests.cpp b/unittest/pass_haltests.cpp index de98ee0..3cb6f7b 100644 --- a/unittest/pass_haltests.cpp +++ b/unittest/pass_haltests.cpp @@ -57,7 +57,7 @@ TEST_F(PowerMgntHalTest, GetResourceConfig_HandlesValidInput) { int ret = 0; unsigned int i; - char path[] = "/etc/pass/pass.conf"; + char path[] = "/hal/etc/pass/pass.conf"; /* Stop PASS daemon before HAL testing */ ret = system("/bin/systemctl stop pass.service"); -- 2.7.4 From 38271a8ac002d0b7330876d7237bf22aee82edce Mon Sep 17 00:00:00 2001 From: Chanwoo Choi Date: Tue, 19 Jan 2021 10:59:40 +0900 Subject: [PATCH 02/16] pass: Remove hal-api-common dependency /etc/ld.so.conf.d/libhal-api.conf contains the '/usr/lib/hal and /usr/lib64/hal' path for loading the shard library. So that PASS daemon doesn't need to specify the dependency of hal-api-common. Change-Id: I56a254f9d4baa3c5f252c99fdf4f4e7bdb0f5307 Signed-off-by: Chanwoo Choi --- CMakeLists.txt | 1 - packaging/pass.spec | 1 - systemd/pass.service.in | 1 - unittest/CMakeLists.txt | 1 - 4 files changed, 4 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index d8f2591..9f5c08a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -50,7 +50,6 @@ SET(PKG_MODULES gio-unix-2.0 libudev libsystemd - hal-api-common hal-api-power ) diff --git a/packaging/pass.spec b/packaging/pass.spec index 9e16a7a..b822c33 100644 --- a/packaging/pass.spec +++ b/packaging/pass.spec @@ -22,7 +22,6 @@ BuildRequires: pkgconfig(glib-2.0) BuildRequires: pkgconfig(gmock) BuildRequires: pkgconfig(libudev) BuildRequires: pkgconfig(libsystemd) -BuildRequires: pkgconfig(hal-api-common) BuildRequires: pkgconfig(hal-api-power) %description diff --git a/systemd/pass.service.in b/systemd/pass.service.in index a774f5f..13b8bcf 100644 --- a/systemd/pass.service.in +++ b/systemd/pass.service.in @@ -10,7 +10,6 @@ RestartSec=0 KillSignal=SIGUSR1 User=system_fw Group=system_fw -Environment=LD_LIBRARY_PATH=@LIBDIR@/hal [Install] WantedBy=delayed.target diff --git a/unittest/CMakeLists.txt b/unittest/CMakeLists.txt index 7aeae05..e2d13d4 100644 --- a/unittest/CMakeLists.txt +++ b/unittest/CMakeLists.txt @@ -17,7 +17,6 @@ pkg_check_modules(gtest_pkgs REQUIRED gio-2.0 gmock dlog - hal-api-common hal-api-power ) -- 2.7.4 From ba5072765a6f2ef6b618a07482499bd3ff7e331f Mon Sep 17 00:00:00 2001 From: Chanwoo Choi Date: Tue, 26 Jan 2021 10:03:35 +0900 Subject: [PATCH 03/16] PASS v1.2.0 - Changes from v1.1.0 1. Use hal-api-power (/platform/hal/api/power) instead of loading the HAL backend library directly. Change-Id: I53d30b334e307f3320346114a61d45889e59a104 Signed-off-by: Chanwoo Choi --- packaging/pass.spec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packaging/pass.spec b/packaging/pass.spec index b822c33..cab50e1 100644 --- a/packaging/pass.spec +++ b/packaging/pass.spec @@ -6,7 +6,7 @@ Name: %{daemon_name} Summary: Power Aware System Service -Version: 1.1.0 +Version: 1.2.0 Release: 1 Group: System/Kernel License: Apache-2.0 -- 2.7.4 From dcf1429f0eaf1f38dd205eb53e574a55d32ab3bb Mon Sep 17 00:00:00 2001 From: Seung-Woo Kim Date: Fri, 29 Jan 2021 18:21:15 +0900 Subject: [PATCH 04/16] pass: resmon: Fix memory leak of udev_monitor in error path The resmon_uevent_add() has memory leak in error path. Fix the memory leak. Change-Id: I53c07b891b888cd1bdd596f872dd204f620d5b7c Signed-off-by: Seung-Woo Kim --- src/pass/pass-resmon.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pass/pass-resmon.c b/src/pass/pass-resmon.c index 8c42e08..24c8acc 100644 --- a/src/pass/pass-resmon.c +++ b/src/pass/pass-resmon.c @@ -586,7 +586,7 @@ static int resmon_uevent_add(struct resmon *monitor) _E("failed to invoke .init of resmon source " \ "(res_name:%s, src_type: 0x%x)\n", res->config_data.res_name, monitor->src_type); - return ret; + goto err_udev_monitor_fd; } } -- 2.7.4 From abdc072a244a1ca230b0530ae7a367c64b2d6647 Mon Sep 17 00:00:00 2001 From: Chanwoo Choi Date: Mon, 1 Feb 2021 10:32:35 +0900 Subject: [PATCH 05/16] pass: rescon: Handle -ENOTSUP error instad of -ENODEV The Power HAL API (hal-api-power) uses the -ENOTSUP error when HAL function is not implemented instead of -ENODEV error. So that handle -ENOTSUP error instad of -ENODEV Change-Id: I7637f78d76e2350d95091cf216757b1ce53416e4 Signed-off-by: Chanwoo Choi --- src/pass/pass-rescon.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/pass/pass-rescon.c b/src/pass/pass-rescon.c index be4e06d..cb934e2 100644 --- a/src/pass/pass-rescon.c +++ b/src/pass/pass-rescon.c @@ -177,10 +177,10 @@ static int rescon_update(struct pass_resource *res) limit_min_cpu = limit_max_cpu; ret = pass_hal_set_online_min_num(res, limit_min_cpu); - if (ret == -EPERM || ret == -ENODEV) { + if (ret == -EPERM || ret == -ENOTSUP) { /* * If -EPERM, function is not supported according to - * h/w resource type. And if -ENODEV, function is not + * h/w resource type. And if -ENOTSUP, function is not * implemented on HAL package. It means that this * function is not necessary on two error case * when calling the HAL functions. @@ -194,7 +194,7 @@ static int rescon_update(struct pass_resource *res) } ret = pass_hal_set_online_max_num(res, limit_max_cpu); - if (ret == -EPERM || ret == -ENODEV) { + if (ret == -EPERM || ret == -ENOTSUP) { ; } else if (ret < 0) { _W("failed to set the maximum number of cpu(%d) of %s", @@ -207,7 +207,7 @@ static int rescon_update(struct pass_resource *res) ret = pass_hal_set_online_state(res, res->config_data.cpu + i, (i < limit_min_cpu) ? 1 : 0); - if (ret == -EPERM || ret == -ENODEV) { + if (ret == -EPERM || ret == -ENOTSUP) { ; } else if (ret < 0) { _W("failed to turn %s of cpu%d of %s", -- 2.7.4 From 8166d6e26633b3f6ac137844ec80e6811594c709 Mon Sep 17 00:00:00 2001 From: lokilee73 Date: Thu, 4 Feb 2021 12:57:45 +0900 Subject: [PATCH 06/16] pmqos: add AppLaunchHome and HomeScreen Two scenarios are added to support C# APIs. ex) DevicePmQosAppLaunchHome DevicePmQosHomeScreen Change-Id: I93ffd4fb0f2e91b00ba3fdaeb7b14b00a4eaa444 Signed-off-by: lokilee73 --- scripts/pass-pmqos.conf | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/scripts/pass-pmqos.conf b/scripts/pass-pmqos.conf index c616e62..3dc3332 100644 --- a/scripts/pass-pmqos.conf +++ b/scripts/pass-pmqos.conf @@ -2,7 +2,7 @@ # set to "yes" scenario_support (Default value is no) # set scenario_num to be tested scenario_support=yes -scenario_num=3 +scenario_num=5 # describe the scenario section as follows #[Scenario0] @@ -23,3 +23,13 @@ support=yes [Scenario2] name=Doze support=yes + +[Scenario3] +name=AppLaunchHome +max_duration_ms=3000 +support=yes + +[Scenario4] +name=HomeScreen +max_duration_ms=3000 +support=yes \ No newline at end of file -- 2.7.4 From 01ad94bded43fc7f2ce29c5d141fe604c7f2e484 Mon Sep 17 00:00:00 2001 From: Chanwoo Choi Date: Mon, 1 Feb 2021 13:43:51 +0900 Subject: [PATCH 07/16] pass: unittest: Change install path and test file name Change install path and test file name. Tizen 6.5 requires the install and naming format as '/usr/bin/hal/[module name]-haltests'. [Detailed changes] - /usr/bin/pass_haltests -> /usr/bin/hal/power-haltests - /usr/bin/pass_gtest -> /usr/bin/pass-unittests And replace -ENODEV with -ENOTSUP because hal-api-power uses the more correct error value of -ENOTSUP. Change-Id: Ia2c8fd772d10e8b55db4dc66d9ee4f6d2be511e4 Signed-off-by: Chanwoo Choi --- packaging/pass.spec | 4 +- unittest/CMakeLists.txt | 21 +++++---- unittest/{pass_gtest.cpp => pass-unittests.cpp} | 0 unittest/{pass_haltests.cpp => power-haltests.cpp} | 54 +++++++++++----------- 4 files changed, 42 insertions(+), 37 deletions(-) rename unittest/{pass_gtest.cpp => pass-unittests.cpp} (100%) rename unittest/{pass_haltests.cpp => power-haltests.cpp} (86%) diff --git a/packaging/pass.spec b/packaging/pass.spec index cab50e1..6f2f77d 100644 --- a/packaging/pass.spec +++ b/packaging/pass.spec @@ -99,8 +99,8 @@ systemctl daemon-reload %files -n %{haltest_name} %defattr(-,root,root,-) -%{_bindir}/pass_haltests +%{_bindir}/hal/power-haltests %files -n %{unittest_name} %defattr(-,root,root,-) -%{_bindir}/pass_gtest +%{_bindir}/pass-unittests diff --git a/unittest/CMakeLists.txt b/unittest/CMakeLists.txt index e2d13d4..bf34e78 100644 --- a/unittest/CMakeLists.txt +++ b/unittest/CMakeLists.txt @@ -29,11 +29,16 @@ SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${EXTRA_CFLAGS}") SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${EXTRA_CFLAGS}") SET(CMAKE_EXE_LINKER_FLAGS "-Wl,--as-needed -pie") -aux_source_directory(. sources) -FOREACH(src ${sources}) - GET_FILENAME_COMPONENT(src_name ${src} NAME_WE) - MESSAGE("${src_name}") - ADD_EXECUTABLE(${src_name} ${SRCS} ${src}) - TARGET_LINK_LIBRARIES(${src_name} ${gtest_LDFLAGS} ${gtest_pkgs_LDFLAGS} -ldl -L${LIBDIR}/hal) - INSTALL(TARGETS ${src_name} DESTINATION bin) -ENDFOREACH() +SET(src ${CMAKE_SOURCE_DIR}/unittest/power-haltests.cpp) +GET_FILENAME_COMPONENT(src_name ${src} NAME_WE) +MESSAGE("${src_name}") +ADD_EXECUTABLE(${src_name} ${SRCS} ${src}) +TARGET_LINK_LIBRARIES(${src_name} ${gtest_LDFLAGS} ${gtest_pkgs_LDFLAGS} -ldl -L${LIBDIR}/hal) +INSTALL(TARGETS ${src_name} DESTINATION /usr/bin/hal) + +SET(src ${CMAKE_SOURCE_DIR}/unittest/pass-unittests.cpp) +GET_FILENAME_COMPONENT(src_name ${src} NAME_WE) +MESSAGE("${src_name}") +ADD_EXECUTABLE(${src_name} ${SRCS} ${src}) +TARGET_LINK_LIBRARIES(${src_name} ${gtest_LDFLAGS} ${gtest_pkgs_LDFLAGS} -ldl -L${LIBDIR}/hal) +INSTALL(TARGETS ${src_name} DESTINATION /usr/bin/) diff --git a/unittest/pass_gtest.cpp b/unittest/pass-unittests.cpp similarity index 100% rename from unittest/pass_gtest.cpp rename to unittest/pass-unittests.cpp diff --git a/unittest/pass_haltests.cpp b/unittest/power-haltests.cpp similarity index 86% rename from unittest/pass_haltests.cpp rename to unittest/power-haltests.cpp index 3cb6f7b..47b7a30 100644 --- a/unittest/pass_haltests.cpp +++ b/unittest/power-haltests.cpp @@ -26,7 +26,7 @@ extern "C" { using namespace std; -class PowerMgntHalTest : public testing::Test { +class PowerHaltest : public testing::Test { public: virtual void SetUp() {} virtual void TearDown() {} @@ -39,12 +39,12 @@ static int haltest_is_failed(struct pass_resource *res, int ret) char *res_name = res->config_data.res_name; /* * If -EPERM, function is not supported according to h/w resource type. - * And if -ENODEV, function is not implemented on hal package. + * And if -ENOTSUP, function is not implemented on hal package. * It means that this function is not necessary on two error case * when calling the HAL functions. */ if (ret < 0) { - if (ret == -EPERM || ret == -ENODEV) + if (ret == -EPERM || ret == -ENOTSUP) return 0; cout << "Failed to test HAL of '" << res_name << "'" << endl; @@ -53,7 +53,7 @@ static int haltest_is_failed(struct pass_resource *res, int ret) return 0; } -TEST_F(PowerMgntHalTest, GetResourceConfig_HandlesValidInput) +TEST_F(PowerHaltest, GetResourceConfig_HandlesValidInput) { int ret = 0; unsigned int i; @@ -76,7 +76,7 @@ TEST_F(PowerMgntHalTest, GetResourceConfig_HandlesValidInput) } } -TEST_F(PowerMgntHalTest, GetCurrGovernor_HandlesValidInput) +TEST_F(PowerHaltest, GetCurrGovernor_HandlesValidInput) { int ret = 0; unsigned int i; @@ -92,7 +92,7 @@ TEST_F(PowerMgntHalTest, GetCurrGovernor_HandlesValidInput) } } -TEST_F(PowerMgntHalTest, SetCurrGovernor_HandlesValidInput) +TEST_F(PowerHaltest, SetCurrGovernor_HandlesValidInput) { int ret = 0; unsigned int i; @@ -113,7 +113,7 @@ TEST_F(PowerMgntHalTest, SetCurrGovernor_HandlesValidInput) } } -TEST_F(PowerMgntHalTest, GetCurrFreq_HandlesValidInput) +TEST_F(PowerHaltest, GetCurrFreq_HandlesValidInput) { int ret = 0; unsigned int i; @@ -128,7 +128,7 @@ TEST_F(PowerMgntHalTest, GetCurrFreq_HandlesValidInput) } } -TEST_F(PowerMgntHalTest, GetMinFreq_HandlesValidInput) +TEST_F(PowerHaltest, GetMinFreq_HandlesValidInput) { int ret = 0; unsigned int i; @@ -143,7 +143,7 @@ TEST_F(PowerMgntHalTest, GetMinFreq_HandlesValidInput) } } -TEST_F(PowerMgntHalTest, SetMinFreq_HandlesValidInput) +TEST_F(PowerHaltest, SetMinFreq_HandlesValidInput) { int ret = 0; int min_freq = 0; @@ -166,7 +166,7 @@ TEST_F(PowerMgntHalTest, SetMinFreq_HandlesValidInput) } } -TEST_F(PowerMgntHalTest, GetMaxFreq_HandlesValidInput) +TEST_F(PowerHaltest, GetMaxFreq_HandlesValidInput) { int ret = 0; unsigned int i; @@ -181,7 +181,7 @@ TEST_F(PowerMgntHalTest, GetMaxFreq_HandlesValidInput) } } -TEST_F(PowerMgntHalTest, SetMaxFreq_HandlesValidInput) +TEST_F(PowerHaltest, SetMaxFreq_HandlesValidInput) { int ret = 0; int max_freq = 0; @@ -204,7 +204,7 @@ TEST_F(PowerMgntHalTest, SetMaxFreq_HandlesValidInput) } } -TEST_F(PowerMgntHalTest, GetAvailableMinFreq_HandlesValidInput) +TEST_F(PowerHaltest, GetAvailableMinFreq_HandlesValidInput) { int ret = 0; unsigned int i; @@ -219,7 +219,7 @@ TEST_F(PowerMgntHalTest, GetAvailableMinFreq_HandlesValidInput) } } -TEST_F(PowerMgntHalTest, GetAvailableMaxFreq_HandlesValidInput) +TEST_F(PowerHaltest, GetAvailableMaxFreq_HandlesValidInput) { int ret = 0; unsigned int i; @@ -235,7 +235,7 @@ TEST_F(PowerMgntHalTest, GetAvailableMaxFreq_HandlesValidInput) } -TEST_F(PowerMgntHalTest, GetUpThreshold_HandlesValidInput) +TEST_F(PowerHaltest, GetUpThreshold_HandlesValidInput) { int ret = 0; unsigned int i; @@ -250,7 +250,7 @@ TEST_F(PowerMgntHalTest, GetUpThreshold_HandlesValidInput) } } -TEST_F(PowerMgntHalTest, SetUpThreshold_HandlesValidInput) +TEST_F(PowerHaltest, SetUpThreshold_HandlesValidInput) { int ret = 0; int up_threshold = 0; @@ -273,7 +273,7 @@ TEST_F(PowerMgntHalTest, SetUpThreshold_HandlesValidInput) } } -TEST_F(PowerMgntHalTest, GetTemperature_HandlesValidInput) +TEST_F(PowerHaltest, GetTemperature_HandlesValidInput) { int ret = 0; unsigned int i; @@ -288,7 +288,7 @@ TEST_F(PowerMgntHalTest, GetTemperature_HandlesValidInput) } } -TEST_F(PowerMgntHalTest, GetTmuPolicy_HandlesValidInput) +TEST_F(PowerHaltest, GetTmuPolicy_HandlesValidInput) { int ret = 0; unsigned int i; @@ -304,7 +304,7 @@ TEST_F(PowerMgntHalTest, GetTmuPolicy_HandlesValidInput) } } -TEST_F(PowerMgntHalTest, GetOnlineState_HandlesValidInput) +TEST_F(PowerHaltest, GetOnlineState_HandlesValidInput) { int ret = 0; unsigned int i, j; @@ -325,7 +325,7 @@ TEST_F(PowerMgntHalTest, GetOnlineState_HandlesValidInput) } } -TEST_F(PowerMgntHalTest, SetOnlineState_HandlesValidInput) +TEST_F(PowerHaltest, SetOnlineState_HandlesValidInput) { int ret = 0; int online_state = 0; @@ -351,7 +351,7 @@ TEST_F(PowerMgntHalTest, SetOnlineState_HandlesValidInput) } -TEST_F(PowerMgntHalTest, GetOnlineMinNum_HandlesValidInput) +TEST_F(PowerHaltest, GetOnlineMinNum_HandlesValidInput) { int ret = 0; unsigned int i; @@ -366,7 +366,7 @@ TEST_F(PowerMgntHalTest, GetOnlineMinNum_HandlesValidInput) } } -TEST_F(PowerMgntHalTest, SetOnlineMinNum_HandlesValidInput) +TEST_F(PowerHaltest, SetOnlineMinNum_HandlesValidInput) { int ret = 0; int online_min_num = 0; @@ -389,7 +389,7 @@ TEST_F(PowerMgntHalTest, SetOnlineMinNum_HandlesValidInput) } } -TEST_F(PowerMgntHalTest, GetOnlineMaxNum_HandlesValidInput) +TEST_F(PowerHaltest, GetOnlineMaxNum_HandlesValidInput) { int ret = 0; unsigned int i; @@ -404,7 +404,7 @@ TEST_F(PowerMgntHalTest, GetOnlineMaxNum_HandlesValidInput) } } -TEST_F(PowerMgntHalTest, SetOnlineMaxNum_HandlesValidInput) +TEST_F(PowerHaltest, SetOnlineMaxNum_HandlesValidInput) { int ret = 0; int online_max_num = 0; @@ -427,7 +427,7 @@ TEST_F(PowerMgntHalTest, SetOnlineMaxNum_HandlesValidInput) } } -TEST_F(PowerMgntHalTest, GetFaultAroundBytes_HandlesValidInput) +TEST_F(PowerHaltest, GetFaultAroundBytes_HandlesValidInput) { int ret = 0; unsigned int i; @@ -442,7 +442,7 @@ TEST_F(PowerMgntHalTest, GetFaultAroundBytes_HandlesValidInput) } } -TEST_F(PowerMgntHalTest, SetFaultAroundBytes_HandlesValidInput) +TEST_F(PowerHaltest, SetFaultAroundBytes_HandlesValidInput) { int ret = 0; int fault_around_bytes = 0; @@ -465,7 +465,7 @@ TEST_F(PowerMgntHalTest, SetFaultAroundBytes_HandlesValidInput) } } -TEST_F(PowerMgntHalTest, SetPmqosData_HandlesValidInput) +TEST_F(PowerHaltest, SetPmqosData_HandlesValidInput) { int ret = 0; unsigned int i; @@ -481,7 +481,7 @@ TEST_F(PowerMgntHalTest, SetPmqosData_HandlesValidInput) } } -TEST_F(PowerMgntHalTest, PutResourceConfig_HandlesValidInput) +TEST_F(PowerHaltest, PutResourceConfig_HandlesValidInput) { int ret = 0; unsigned int i; -- 2.7.4 From 7aa237a0c030256ac6ca99e5d10fcb29edd96ff0 Mon Sep 17 00:00:00 2001 From: Chanwoo Choi Date: Wed, 3 Mar 2021 12:56:18 +0900 Subject: [PATCH 08/16] pass: pmqos: Add new Performance mode Add new 'Performance' mode in order to support the highest performance. There are always requirements to test the device with high-performance. Change-Id: I5d2eadefeedd8d0d56e08f37c68fd0664c2ffb8b Signed-off-by: Chanwoo Choi --- scripts/pass-pmqos.conf | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/scripts/pass-pmqos.conf b/scripts/pass-pmqos.conf index 3dc3332..4a4259a 100644 --- a/scripts/pass-pmqos.conf +++ b/scripts/pass-pmqos.conf @@ -2,7 +2,7 @@ # set to "yes" scenario_support (Default value is no) # set scenario_num to be tested scenario_support=yes -scenario_num=5 +scenario_num=6 # describe the scenario section as follows #[Scenario0] @@ -32,4 +32,8 @@ support=yes [Scenario4] name=HomeScreen max_duration_ms=3000 -support=yes \ No newline at end of file +support=yes + +[Scenario5] +name=Performance +support=yes -- 2.7.4 From dac64c780db5c517f3a9c42ebbe3d98813c59c74 Mon Sep 17 00:00:00 2001 From: Chanwoo Choi Date: Thu, 17 Jun 2021 10:59:01 +0900 Subject: [PATCH 09/16] pass: rescon: Add missing lock for scenario_level_list scenario_level_list variables should be protected by mutext. So thath add missing lock for scenario_level_list Change-Id: Ib4590fd3b76e3e9f6953234cbb1f7b21c7af7520 Signed-off-by: Chanwoo Choi --- src/pass/pass-rescon.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/pass/pass-rescon.c b/src/pass/pass-rescon.c index cb934e2..79d3a1a 100644 --- a/src/pass/pass-rescon.c +++ b/src/pass/pass-rescon.c @@ -516,9 +516,12 @@ int pass_rescon_init(struct pass_resource *res) res->config_data.default_max_level = rescon->max_level; /* Initialize g_list of scenario_level */ - rescon->scenario_level_list = NULL; g_mutex_init(&rescon->scenario_level_mutex); + g_mutex_lock(&rescon->scenario_level_mutex); + rescon->scenario_level_list = NULL; + g_mutex_unlock(&rescon->scenario_level_mutex); + /* * Save the current data of h/w resource. The saved data * will be used for restoring the h/w resource on exit(). @@ -592,8 +595,11 @@ int pass_rescon_exit(struct pass_resource *res) rescon->init_level = 0; /* Free g_list of scenario_level */ + g_mutex_lock(&rescon->scenario_level_mutex); g_list_free(rescon->scenario_level_list); rescon->scenario_level_list = NULL; + g_mutex_unlock(&rescon->scenario_level_mutex); + g_mutex_clear(&rescon->scenario_level_mutex); rescon->state = PASS_OFF; -- 2.7.4 From 327b5661f2e66d9f2ecc3bc75f814e562781f1af Mon Sep 17 00:00:00 2001 From: Chanwoo Choi Date: Thu, 17 Jun 2021 16:23:14 +0900 Subject: [PATCH 10/16] scripts: dbus: Allow root to use core d-bus interface Allow 'root' to use core d-bus interface provided by PASS. The 'root' have to control all d-bus interface without any restrictions. Change-Id: Ie322e426cbc945209cd9188ffa642444ce69880a Signed-off-by: Chanwoo Choi --- scripts/pass.conf | 2 ++ 1 file changed, 2 insertions(+) diff --git a/scripts/pass.conf b/scripts/pass.conf index b96f2af..abfdfdd 100644 --- a/scripts/pass.conf +++ b/scripts/pass.conf @@ -3,6 +3,8 @@ + -- 2.7.4 From 085a28368ba8df42b437b5e2844fbd35909fc267 Mon Sep 17 00:00:00 2001 From: Chanwoo Choi Date: Thu, 17 Jun 2021 16:34:01 +0900 Subject: [PATCH 11/16] unittest: Replace system command with dbus signal system() command causes the security issue. So that fix issue to replace system command with dbus signal. Change-Id: I83843697c9b64bd1c14fc54d1e9773dcfbdc5a3b Signed-off-by: Chanwoo Choi --- unittest/pass-unittests.cpp | 9 +++++--- unittest/power-haltests.cpp | 56 +++++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 60 insertions(+), 5 deletions(-) diff --git a/unittest/pass-unittests.cpp b/unittest/pass-unittests.cpp index 9dd723e..5711c01 100644 --- a/unittest/pass-unittests.cpp +++ b/unittest/pass-unittests.cpp @@ -228,13 +228,16 @@ TEST_F(PowerMgntTest, RestartsPowerMgntService) { gint32 ret; - ret = system("/bin/systemctl start pass.service"); + ret = pass_test_method_call(DBUS_CORE_PATH, DBUS_CORE_INTERFACE, + "start", NULL); ASSERT_EQ(ret, 0) << "PassServiceStart Failed"; - ret = system("/bin/systemctl stop pass.service"); + ret = pass_test_method_call(DBUS_CORE_PATH, DBUS_CORE_INTERFACE, + "stop", NULL); ASSERT_EQ(ret, 0) << "PassServiceStop Failed"; - ret = system("/bin/systemctl start pass.service"); + ret = pass_test_method_call(DBUS_CORE_PATH, DBUS_CORE_INTERFACE, + "start", NULL); ASSERT_EQ(ret, 0) << "PassServiceStart Failed"; } diff --git a/unittest/power-haltests.cpp b/unittest/power-haltests.cpp index 47b7a30..8e475e5 100644 --- a/unittest/power-haltests.cpp +++ b/unittest/power-haltests.cpp @@ -17,7 +17,9 @@ #include #include +#include #include +#include extern "C" { #include "pass-hal.h" @@ -53,6 +55,54 @@ static int haltest_is_failed(struct pass_resource *res, int ret) return 0; } +static gint32 pass_test_method_call(const gchar *path, const gchar *intf, + const gchar *method, GVariant *body) +{ + const gchar *type; + GVariant *ret; + GError *err = NULL; + GDBusMessage *msg, *reply; + GDBusConnection *conn; + gint32 r; + + conn = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, &err); + if (err) + return -1; + + msg = g_dbus_message_new_method_call(DBUS_PASS_BUS_NAME, path, + intf, method); + if (!msg) + return -1; + + if (body) + g_dbus_message_set_body(msg, body); + + reply = g_dbus_connection_send_message_with_reply_sync(conn, msg, + G_DBUS_SEND_MESSAGE_FLAGS_NONE, + G_MAXINT, NULL, NULL, &err); + if (err) { + g_object_unref(msg); + g_clear_error(&err); + return -1; + } + + ret = g_variant_get_child_value(g_dbus_message_get_body(reply), 0); + type = g_variant_get_type_string(ret); + if (type[0] == 'i') + r = g_variant_get_int32(ret); + else + r = -1; + + g_variant_unref(ret); + + g_dbus_connection_flush(conn, NULL, NULL, NULL); + g_object_unref(msg); + g_object_unref(reply); + g_clear_error(&err); + + return r; +} + TEST_F(PowerHaltest, GetResourceConfig_HandlesValidInput) { int ret = 0; @@ -60,7 +110,8 @@ TEST_F(PowerHaltest, GetResourceConfig_HandlesValidInput) char path[] = "/hal/etc/pass/pass.conf"; /* Stop PASS daemon before HAL testing */ - ret = system("/bin/systemctl stop pass.service"); + ret = pass_test_method_call(DBUS_CORE_PATH, DBUS_CORE_INTERFACE, + "stop", NULL); ASSERT_EQ(ret, 0) << "PassServiceStop Failed"; ret = pass_parser_get_resource_config(&g_pass, path); @@ -497,7 +548,8 @@ TEST_F(PowerHaltest, PutResourceConfig_HandlesValidInput) } /* Restart PASS daemon before HAL testing */ - ret = system("/bin/systemctl start pass.service"); + ret = pass_test_method_call(DBUS_CORE_PATH, DBUS_CORE_INTERFACE, + "start", NULL); ASSERT_EQ(ret, 0) << "PassServiceStart Failed"; } -- 2.7.4 From 3364431b71ad3d0c38b7c5971bd7647869a4c49a Mon Sep 17 00:00:00 2001 From: INSUN PYO Date: Wed, 21 Jul 2021 10:05:55 +0900 Subject: [PATCH 12/16] pass: resmon: Remove unused code Change-Id: I0e4f5e61fe5ed0ab8a58ec69c02f0115b16a247f Signed-off-by: INSUN PYO --- src/pass/pass-resmon.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/pass/pass-resmon.c b/src/pass/pass-resmon.c index 24c8acc..aa4852e 100644 --- a/src/pass/pass-resmon.c +++ b/src/pass/pass-resmon.c @@ -498,8 +498,6 @@ out: return G_SOURCE_CONTINUE; } -#define UDEV_MONITOR_SIZE (128 * 1024) - /** * @brief Add an uevent-based resource monitor. * @param [in] monitor Instance of a resource monitor -- 2.7.4 From 45f5c07684b5346e9f79660a2c640d7cff6746f7 Mon Sep 17 00:00:00 2001 From: Chanwoo Choi Date: Thu, 29 Jul 2021 21:38:13 +0900 Subject: [PATCH 13/16] pmqos: Convert pass-pmqos.conf format to json to improve readability The legacy pass-pmqos.conf file format is not better on side of readability. So that change the configuration file format to json style to improve readability. Change-Id: I4898d431b1d0f8bc3b50b1d1ea764c87992cdf6c Signed-off-by: Chanwoo Choi --- CMakeLists.txt | 3 +- include/pass/common.h | 12 ++- packaging/pass.spec | 3 +- scripts/pass-pmqos.conf | 39 ---------- scripts/pass-pmqos.json | 24 ++++++ src/core/common.c | 46 ++++++++++- src/pmqos/pmqos-parser.c | 193 +++++++++++++++++++---------------------------- src/pmqos/pmqos.c | 4 +- unittest/CMakeLists.txt | 1 + 9 files changed, 160 insertions(+), 165 deletions(-) delete mode 100644 scripts/pass-pmqos.conf create mode 100644 scripts/pass-pmqos.json diff --git a/CMakeLists.txt b/CMakeLists.txt index 9f5c08a..6bd9240 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -50,6 +50,7 @@ SET(PKG_MODULES gio-unix-2.0 libudev libsystemd + json-c hal-api-power ) @@ -97,7 +98,7 @@ ADD_EXECUTABLE(${PROJECT_NAME} ${SRCS}) TARGET_LINK_LIBRARIES(${PROJECT_NAME} ${pkgs_LDFLAGS} -ldl -lm) INSTALL(TARGETS ${PROJECT_NAME} DESTINATION bin) INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/scripts/${PROJECT_NAME}.conf DESTINATION /etc/dbus-1/system.d) -INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/scripts/pass-pmqos.conf DESTINATION /etc/pass) +INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/scripts/pass-pmqos.json DESTINATION /etc/pass) INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/scripts/pass-thermal.conf DESTINATION /etc/pass) CONFIGURE_FILE(${CMAKE_SOURCE_DIR}/systemd/${PROJECT_NAME}.service.in ${CMAKE_SOURCE_DIR}/systemd/${PROJECT_NAME}.service @ONLY) INSTALL(FILES ${CMAKE_SOURCE_DIR}/systemd/org.tizen.system.pass.service DESTINATION /usr/share/dbus-1/system-services) diff --git a/include/pass/common.h b/include/pass/common.h index 3bef731..851212c 100644 --- a/include/pass/common.h +++ b/include/pass/common.h @@ -26,6 +26,9 @@ #include #include +#include +#include + typedef unsigned int uint32; typedef unsigned long long uint64; @@ -90,6 +93,11 @@ typedef unsigned long long uint64; #define USEC_TO_MSEC(x) ((double)x/1000) #endif -int sys_get_str(char *fname, char *str); -int sys_strtol(char *str); +int sys_get_str(const char *fname, char *str); +int sys_strtol(const char *str); + +const char *get_string_from_object(json_object *obj, const char *key); +const int get_int_from_object(json_object *obj, const char *key); +const double get_double_from_object(json_object *obj, const char *key); +const int get_boolean_from_object(json_object *obj, const char *key); #endif /* __CORE_COMMON_H__ */ diff --git a/packaging/pass.spec b/packaging/pass.spec index 6f2f77d..b1fd8a0 100644 --- a/packaging/pass.spec +++ b/packaging/pass.spec @@ -22,6 +22,7 @@ BuildRequires: pkgconfig(glib-2.0) BuildRequires: pkgconfig(gmock) BuildRequires: pkgconfig(libudev) BuildRequires: pkgconfig(libsystemd) +BuildRequires: pkgconfig(json-c) BuildRequires: pkgconfig(hal-api-power) %description @@ -89,7 +90,7 @@ systemctl daemon-reload %manifest %{name}.manifest %license LICENSE %config %{_sysconfdir}/dbus-1/system.d/%{daemon_name}.conf -%config %{_sysconfdir}/pass/pass-pmqos.conf +%config %{_sysconfdir}/pass/pass-pmqos.json %config %{_sysconfdir}/pass/pass-thermal.conf %{_bindir}/%{daemon_name} %{_unitdir}/delayed.target.wants/%{daemon_name}.service diff --git a/scripts/pass-pmqos.conf b/scripts/pass-pmqos.conf deleted file mode 100644 index 4a4259a..0000000 --- a/scripts/pass-pmqos.conf +++ /dev/null @@ -1,39 +0,0 @@ -[PassScenario] -# set to "yes" scenario_support (Default value is no) -# set scenario_num to be tested -scenario_support=yes -scenario_num=6 - -# describe the scenario section as follows -#[Scenario0] -#[Mandatory properties] -# name=AppLaunch # (dbus method name) -# support=yes -#[Optional properties] -# max_duration_ms=3000 # (unit:millisecond, max dururation is 3000ms) -[Scenario0] -name=AppLaunch -max_duration_ms=3000 -support=yes - -[Scenario1] -name=UltraPowerSaving -support=yes - -[Scenario2] -name=Doze -support=yes - -[Scenario3] -name=AppLaunchHome -max_duration_ms=3000 -support=yes - -[Scenario4] -name=HomeScreen -max_duration_ms=3000 -support=yes - -[Scenario5] -name=Performance -support=yes diff --git a/scripts/pass-pmqos.json b/scripts/pass-pmqos.json new file mode 100644 index 0000000..34f1032 --- /dev/null +++ b/scripts/pass-pmqos.json @@ -0,0 +1,24 @@ +{ + "pmqos_support" : true, + "pmqos_scenario_list" : + [ + { + "name" : "AppLaunch", + "max_duration_ms" : 3000, + "support" : true + }, { + "name" : "AppLaunchHome", + "max_duration_ms" : 3000, + "support" : true + }, { + "name" : "UltraPowerSaving", + "support" : true + }, { + "name" : "Doze", + "support" : true + }, { + "name" : "Performance", + "support" : true + } + ] +} diff --git a/src/core/common.c b/src/core/common.c index bf1a81b..66fe952 100644 --- a/src/core/common.c +++ b/src/core/common.c @@ -40,7 +40,7 @@ #define BUFF_MAX 255 -static int sys_read_buf(char *file, char *buf) +static int sys_read_buf(const char *file, char *buf) { int fd; int r; @@ -61,7 +61,7 @@ static int sys_read_buf(char *file, char *buf) return ret; } -int sys_get_str(char *fname, char *str) +int sys_get_str(const char *fname, char *str) { char buf[BUFF_MAX] = {0}; @@ -73,7 +73,7 @@ int sys_get_str(char *fname, char *str) return -1; } -int sys_strtol(char *str) +int sys_strtol(const char *str) { long value; @@ -83,3 +83,43 @@ int sys_strtol(char *str) return (int)value; } + +const char *get_string_from_object(json_object *obj, const char *key) +{ + json_object *tmp = NULL; + + if (!json_object_object_get_ex(obj, key, &tmp)) + return NULL; + + return json_object_get_string(tmp); +} + +const int get_int_from_object(json_object *obj, const char *key) +{ + json_object *tmp = NULL; + + if (!json_object_object_get_ex(obj, key, &tmp)) + return -EINVAL; + + return json_object_get_int(tmp); +} + +const double get_double_from_object(json_object *obj, const char *key) +{ + json_object *tmp = NULL; + + if (!json_object_object_get_ex(obj, key, &tmp)) + return -EINVAL; + + return json_object_get_double(tmp); +} + +const int get_boolean_from_object(json_object *obj, const char *key) +{ + json_object *tmp = NULL; + + if (!json_object_object_get_ex(obj, key, &tmp)) + return -EINVAL; + + return (int)json_object_get_boolean(tmp); +} diff --git a/src/pmqos/pmqos-parser.c b/src/pmqos/pmqos-parser.c index 3e8ee97..d0fec49 100644 --- a/src/pmqos/pmqos-parser.c +++ b/src/pmqos/pmqos-parser.c @@ -34,98 +34,42 @@ #include #include +#include +#include + #include #include -#include #include "pmqos.h" -#define MAX_NUM_OF_SCENARIOS 255 - -static bool is_supported(const char *value) -{ - assert(value); - - if (MATCH(value, "yes")) - return true; - return false; -} - /** * @brief Parse scenario section to get a scenario information * for PMQoS(Power Management Quality of Service). - * @param [in] result Parsed raw data from configuration - * @param [in] user_data Instance for each scenario - * @param [in] index Index of each scenario + * @param [in] obj Instance of json_object for each scenario + * @param [in] scenario Instance for each scenario * @return @c 0 on success, otherwise error value */ -static int pmqos_parse_scenario(struct parse_result *result, void *user_data, unsigned int index) +static int pmqos_parse_scenario(json_object *obj, struct scenario *scenario) { - struct pmqos_scenario *scenarios = (struct pmqos_scenario *)user_data; - - assert(result); - assert(result->section && result->name && result->value); - - /* Parse 'PassScenario' section */ - if (MATCH(result->section, "PassScenario")) { - if (MATCH(result->name, "scenario_support")) - scenarios->support = is_supported(result->value); - else if (MATCH(result->name, "scenario_num")) { - int num; - - num = sys_strtol(result->value); - if (num < 0) - return num; - - if (num > MAX_NUM_OF_SCENARIOS) - return -EINVAL; - - if (num > 0) { - scenarios->list = calloc(num, - sizeof(struct scenario)); - if (!scenarios->list) { - _E("failed to allocate memory for scenario"); - return -errno; - } - - scenarios->num = num; - } - } + const char *name; + int max_duration_ms; + int support; + + /* Get property values */ + name = get_string_from_object(obj, "name"); + max_duration_ms = get_int_from_object(obj, "max_duration_ms"); + support = get_boolean_from_object(obj, "support"); + + /* Check the mandatory property values are valid or not */ + if (!name) { + _E("Failed to get 'name' property of scenario section\n"); + return -EINVAL; } - /* Do not support pmqos scenario */ - if (!scenarios->support) - return 0; - - /* Do not have pmqos scenario */ - if (!scenarios->num) - return 0; - - /* No item to parse */ - if (index >= scenarios->num) - return 0; - - /* Parse 'Scenario' section */ - if (MATCH(result->name, "name")) - snprintf(scenarios->list[index].name, strlen(result->value) + 1, - "%s", result->value); - else if (MATCH(result->name, "support")) - scenarios->list[index].support = is_supported(result->value); - else if (MATCH(result->name, "max_duration_ms")) { - int max_duration_ms = sys_strtol(result->value); - - if (max_duration_ms < 0) { - _E("failed to parse max_duration_ms property (%d)\n", - max_duration_ms); - return -EINVAL; - } - - /* - * If maximum duration is zero, it measn that this scenario is - * mode without any maximum duration. - */ - scenarios->list[index].max_duration_ms = max_duration_ms; - } + /* Initialize config_data from property values of confiugartion file */ + snprintf(scenario->name, strlen(name) + 1, "%s", name); + scenario->max_duration_ms = (max_duration_ms < 0) ? 0 : max_duration_ms; + scenario->support = (support < 0) ? 1 : support; return 0; } @@ -134,49 +78,56 @@ static int pmqos_parse_scenario(struct parse_result *result, void *user_data, un * @brief Parse configuration to get information of supported scenarios * for PMQoS(Power Management Quality of Service) such as * AppLaunch, UltraPowerSaving. - * @param [in] result Parsed raw data from configuration - * @param [in] user_data Instance for each scenario + * @param [in] obj Instance of json_object of thermal configuration file + * @param [in] scenarios Instance for all scenarios * @return @c 0 on success, otherwise error value */ -static int pmqos_load_config(struct parse_result *result, void *user_data) +static int pmqos_load_config(json_object *obj, struct pmqos_scenario *scenarios) { - struct pmqos_scenario *scenarios = (struct pmqos_scenario *)user_data; - char name[NAME_MAX]; - int ret; - static int index; - - if (!result) - return 0; - - if (!result->section || !result->name || !result->value) + int pmqos_support; + json_object *pmqos_scenario_list = NULL; + int num_scenarios = 0, ret, i; + + /* Get property values */ + pmqos_support = get_boolean_from_object(obj, "pmqos_support"); + if (json_object_object_get_ex(obj, "pmqos_scenario_list", + &pmqos_scenario_list)) + num_scenarios = json_object_array_length(pmqos_scenario_list); + + /* Check the mandatory property values are valid or not */ + if (pmqos_support <= 0 || num_scenarios <= 0) { + _I("Disable PMQOS module\n"); return 0; + } - /* Parsing 'PassScenario' section */ - if (MATCH(result->section, "PassScenario")) { - ret = pmqos_parse_scenario(result, user_data, -1); - if (ret < 0) { - _E("failed to parse [PassScenario] section : %d", ret); - return ret; - } - goto out; + /* Initialize config_data from property values of confiugartion file */ + scenarios->support = pmqos_support; + scenarios->list = calloc(num_scenarios, sizeof(struct scenario)); + if (!scenarios->list) { + _E("failed to allocate memory for scenario"); + return -ENOMEM; } + scenarios->num = num_scenarios; - /* Parsing 'Scenario' section */ - for (index = 0; index < scenarios->num; ++index) { - snprintf(name, sizeof(name), "Scenario%d", index); - - if (MATCH(result->section, name)) { - ret = pmqos_parse_scenario(result, user_data, index); - if (ret < 0) { - _E("failed to parse [Scenario%d] section : %d", index, ret); - return ret; - } - goto out; + for (i = 0; i < scenarios->num ; i++) { + json_object *scenario_obj + = json_object_array_get_idx(pmqos_scenario_list, i); + struct scenario *scenario = &(scenarios->list[i]); + + ret = pmqos_parse_scenario(scenario_obj, scenario); + if (ret < 0) { + _E("cannot parse 'pmqos.scenario%d' section\n", i); + goto err; } } -out: return 0; +err: + free(scenarios->list); + scenarios->list = NULL; + scenarios->num = 0; + + return ret; } /** @@ -209,16 +160,24 @@ int pmqos_put_scenario(struct pmqos_scenario *scenarios) int pmqos_get_scenario(const char *path, struct pmqos_scenario *scenarios) { int ret; + json_object *obj = NULL; /* Initialize the variables before parsing the pass-pmqos.conf */ scenarios->num = 0; - /* get configuration file */ - ret = config_parse(path, pmqos_load_config, scenarios); - if (ret < 0) { - pmqos_put_scenario(scenarios); - return ret; + /* Parse configuration file */ + obj = json_object_from_file(path); + if (!obj) { + _E("Failed to get json_object from %s (%s)\n", + path, json_util_get_last_err()); + return -EINVAL; } - return 0; + ret = pmqos_load_config(obj, scenarios); + if (ret < 0) + pmqos_put_scenario(scenarios); + + json_object_put(obj); + + return ret; } diff --git a/src/pmqos/pmqos.c b/src/pmqos/pmqos.c index eb40199..ec64276 100644 --- a/src/pmqos/pmqos.c +++ b/src/pmqos/pmqos.c @@ -39,7 +39,7 @@ #include "pmqos.h" -#define PMQOS_CONF_PATH "/etc/pass/pass-pmqos.conf" +#define PMQOS_JSON_PATH "/etc/pass/pass-pmqos.json" #define MILLISECONDS(tv) ((tv.tv_sec)*1000 + (tv.tv_nsec)/1000000) #define DELTA(a, b) (MILLISECONDS(a) - MILLISECONDS(b)) @@ -520,7 +520,7 @@ static int pmqos_init_done(void *data, void *user_data) if (!g_pmqos) return -ENOMEM; - ret = pmqos_get_scenario(PMQOS_CONF_PATH, g_pmqos); + ret = pmqos_get_scenario(PMQOS_JSON_PATH, g_pmqos); if (ret < 0) { _E("failed to get PMQoS scenario\n"); return ret; diff --git a/unittest/CMakeLists.txt b/unittest/CMakeLists.txt index bf34e78..12a56db 100644 --- a/unittest/CMakeLists.txt +++ b/unittest/CMakeLists.txt @@ -17,6 +17,7 @@ pkg_check_modules(gtest_pkgs REQUIRED gio-2.0 gmock dlog + json-c hal-api-power ) -- 2.7.4 From 3d8374d30debda17f4068213d20a18c9ed4710d9 Mon Sep 17 00:00:00 2001 From: Chanwoo Choi Date: Thu, 29 Jul 2021 21:44:15 +0900 Subject: [PATCH 14/16] thermal: Convert pass-thermal.conf format to json to improve readability The legacy pass-thermal.conf file format is not better on side of readability. So that change the configuration file format to json style to improve readability. Change-Id: I228559fbc348b097284263a6bd8c57c1b2e6fa37 Signed-off-by: Chanwoo Choi --- CMakeLists.txt | 2 +- packaging/pass.spec | 2 +- scripts/pass-thermal.conf | 25 ------- scripts/pass-thermal.json | 19 +++++ src/thermal/thermal-parser.c | 167 ++++++++++++++++++------------------------- src/thermal/thermal.c | 4 +- 6 files changed, 92 insertions(+), 127 deletions(-) delete mode 100644 scripts/pass-thermal.conf create mode 100644 scripts/pass-thermal.json diff --git a/CMakeLists.txt b/CMakeLists.txt index 6bd9240..be26532 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -99,7 +99,7 @@ TARGET_LINK_LIBRARIES(${PROJECT_NAME} ${pkgs_LDFLAGS} -ldl -lm) INSTALL(TARGETS ${PROJECT_NAME} DESTINATION bin) INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/scripts/${PROJECT_NAME}.conf DESTINATION /etc/dbus-1/system.d) INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/scripts/pass-pmqos.json DESTINATION /etc/pass) -INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/scripts/pass-thermal.conf DESTINATION /etc/pass) +INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/scripts/pass-thermal.json DESTINATION /etc/pass) CONFIGURE_FILE(${CMAKE_SOURCE_DIR}/systemd/${PROJECT_NAME}.service.in ${CMAKE_SOURCE_DIR}/systemd/${PROJECT_NAME}.service @ONLY) INSTALL(FILES ${CMAKE_SOURCE_DIR}/systemd/org.tizen.system.pass.service DESTINATION /usr/share/dbus-1/system-services) INSTALL(FILES ${CMAKE_SOURCE_DIR}/systemd/org.tizen.system.thermal.service DESTINATION /usr/share/dbus-1/system-services) diff --git a/packaging/pass.spec b/packaging/pass.spec index b1fd8a0..3856fc3 100644 --- a/packaging/pass.spec +++ b/packaging/pass.spec @@ -91,7 +91,7 @@ systemctl daemon-reload %license LICENSE %config %{_sysconfdir}/dbus-1/system.d/%{daemon_name}.conf %config %{_sysconfdir}/pass/pass-pmqos.json -%config %{_sysconfdir}/pass/pass-thermal.conf +%config %{_sysconfdir}/pass/pass-thermal.json %{_bindir}/%{daemon_name} %{_unitdir}/delayed.target.wants/%{daemon_name}.service %{_unitdir}/%{daemon_name}.service diff --git a/scripts/pass-thermal.conf b/scripts/pass-thermal.conf deleted file mode 100644 index f15ad2c..0000000 --- a/scripts/pass-thermal.conf +++ /dev/null @@ -1,25 +0,0 @@ -[thermal] -# set to "yes" thermal_support (Default value is no) -# set thermal_number_of_scenario to be tested -thermal_support=yes -thermal_number_of_scenario=4 - -# describe the scenario section as follows -#[Scenario0] -#name=Release -#support=yes -[thermal.scenario0] -name=Release -support=yes - -[thermal.scenario1] -name=Warning -support=yes - -[thermal.scenario2] -name=LimitAction -support=yes - -[thermal.scenario3] -name=Shutdown -support=yes diff --git a/scripts/pass-thermal.json b/scripts/pass-thermal.json new file mode 100644 index 0000000..83fe051 --- /dev/null +++ b/scripts/pass-thermal.json @@ -0,0 +1,19 @@ +{ + "thermal_support" : true, + "thermal_scenario_list" : + [ + { + "name" : "Release", + "support" : true + }, { + "name" : "Warning", + "support" : true + }, { + "name" : "LimitAction", + "support" : true + }, { + "name" : "Shutdown", + "support" : true + } + ] +} diff --git a/src/thermal/thermal-parser.c b/src/thermal/thermal-parser.c index 58df42e..8a4a9f0 100644 --- a/src/thermal/thermal-parser.c +++ b/src/thermal/thermal-parser.c @@ -37,76 +37,34 @@ #include #include -#include #include "thermal.h" -#define MAX_NUM_OF_SCENARIOS 255 - -static bool is_supported(const char *value) -{ - assert(value); - - if (MATCH(value, "yes")) - return true; - return false; -} - /** * @brief Parse scenario section to get a scenario information * for Thermal Monitor. - * @param [in] result Parsed raw data from configuration - * @param [in] user_data Instance for each scenario - * @param [in] index Index of each scenario + * @param [in] obj Instance of json_object for each scenario + * @param [in] scenario Instance for each scenario * @return @c 0 on success, otherwise error value */ -static int thermal_parse_scenario(struct parse_result *result, void *user_data, - unsigned int index) +static int thermal_parse_scenario(json_object *obj, struct scenario *scenario) { - struct thermal_scenario *scenarios = (struct thermal_scenario *)user_data; - - assert(result); - assert(result->section && result->name && result->value); - - /* Parse 'thermal' section */ - if (MATCH(result->section, "thermal")) { - if (MATCH(result->name, "thermal_support")) - scenarios->support = is_supported(result->value); - else if (MATCH(result->name, "thermal_number_of_scenario")) { - int num; - - num = sys_strtol(result->value); - if (num < 0) - return num; - - if (num > MAX_NUM_OF_SCENARIOS) - return -EINVAL; - - if (num > 0) { - scenarios->list = calloc(num, - sizeof(struct scenario)); - if (!scenarios->list) { - _E("failed to allocate scenario memory"); - return -errno; - } - - scenarios->num = num; - } - } - } + const char *name; + int support; - if (!scenarios->support || !scenarios->num) - return 0; + /* Get property values */ + name = get_string_from_object(obj, "name"); + support = get_boolean_from_object(obj, "support"); - if (index >= scenarios->num) - return 0; + /* Check the mandatory property values are valid or not */ + if (!name) { + _E("Failed to get 'name' property of scenario section\n"); + return -EINVAL; + } - /* Parse 'Scenario' section */ - if (MATCH(result->name, "name")) - snprintf(scenarios->list[index].name, - strlen(result->value) + 1, "%s", result->value); - else if (MATCH(result->name, "support")) - scenarios->list[index].support = is_supported(result->value); + /* Initialize config_data from property values of confiugartion file */ + snprintf(scenario->name, strlen(name) + 1, "%s", name); + scenario->support = (support < 0) ? 1 : support; return 0; } @@ -114,51 +72,56 @@ static int thermal_parse_scenario(struct parse_result *result, void *user_data, /** * @brief Parse configuration to get information of supported scenarios * for Thermal Monitor such as Release, Warning. - * @param [in] result Parsed raw data from configuration - * @param [in] user_data Instance for each scenario + * @param [in] obj Instance of json_object of thermal configuration file + * @param [in] scenarios Instance for all scenarios * @return @c 0 on success, otherwise error value */ -static int thermal_load_config(struct parse_result *result, void *user_data) +static int thermal_load_config(json_object *obj, struct thermal_scenario *scenarios) { - struct thermal_scenario *scenarios - = (struct thermal_scenario *)user_data; - char name[NAME_MAX]; - int ret; - static int index; - - if (!result) - return 0; - - if (!result->section || !result->name || !result->value) + int thermal_support; + json_object *thermal_scenario_list = NULL; + int num_scenarios = 0, ret, i; + + /* Get property values */ + thermal_support = get_boolean_from_object(obj, "thermal_support"); + if (json_object_object_get_ex(obj, "thermal_scenario_list", + &thermal_scenario_list)) + num_scenarios = json_object_array_length(thermal_scenario_list); + + /* Check the mandatory property values are valid or not */ + if (thermal_support <= 0 || num_scenarios <= 0) { + _I("Disable thermal module\n"); return 0; + } - /* Parsing 'thermal' section */ - if (MATCH(result->section, "thermal")) { - ret = thermal_parse_scenario(result, user_data, -1); - if (ret < 0) { - _E("failed to parse [thermal] section : %d", ret); - return ret; - } - goto out; + /* Initialize config_data from property values of confiugartion file */ + scenarios->support = thermal_support; + scenarios->list = calloc(num_scenarios, sizeof(struct scenario)); + if (!scenarios->list) { + _E("failed to allocate memory for scenario"); + return -ENOMEM; } + scenarios->num = num_scenarios; - /* Parsing 'thermal.scenario' section */ - for (index = 0; index < scenarios->num; ++index) { - snprintf(name, sizeof(name), "thermal.scenario%d", index); - - if (MATCH(result->section, name)) { - ret = thermal_parse_scenario(result, user_data, index); - if (ret < 0) { - _E("failed to parse [thermal.scenario%d] section : %d", - index, ret); - return ret; - } - goto out; + for (i = 0; i < scenarios->num ; i++) { + json_object *scenario_obj + = json_object_array_get_idx(thermal_scenario_list, i); + struct scenario *scenario = &(scenarios->list[i]); + + ret = thermal_parse_scenario(scenario_obj, scenario); + if (ret < 0) { + _E("cannot parse 'thermal.scenario%d' section\n", i); + goto err; } } -out: return 0; +err: + free(scenarios->list); + scenarios->list = NULL; + scenarios->num = 0; + + return ret; } /** @@ -189,16 +152,24 @@ int thermal_put_scenario(struct thermal_scenario *scenarios) int thermal_get_scenario(const char *path, struct thermal_scenario *scenarios) { int ret; + json_object *obj = NULL; /* Initialize the variables before parsing the pass-thermal.conf */ scenarios->num = 0; - /* get configuration file */ - ret = config_parse(path, thermal_load_config, scenarios); - if (ret < 0) { - thermal_put_scenario(scenarios); - return ret; + /* Parse configuration file */ + obj = json_object_from_file(path); + if (!obj) { + _E("Failed to get json_object from %s (%s)\n", + path, json_util_get_last_err()); + return -EINVAL; } - return 0; + ret = thermal_load_config(obj, scenarios); + if (ret < 0) + thermal_put_scenario(scenarios); + + json_object_put(obj); + + return ret; } diff --git a/src/thermal/thermal.c b/src/thermal/thermal.c index 4d43fd2..cca20dc 100644 --- a/src/thermal/thermal.c +++ b/src/thermal/thermal.c @@ -38,7 +38,7 @@ #include "thermal.h" -#define THERMAL_CONF_PATH "/etc/pass/pass-thermal.conf" +#define THERMAL_JSON_PATH "/etc/pass/pass-thermal.json" /** * @brief Global instance indicating the Thermal Monitor D-Bus interface @@ -116,7 +116,7 @@ static int thermal_init_done(void *data, void *user_data) return -ENOMEM; } - ret = thermal_get_scenario(THERMAL_CONF_PATH, g_thermal); + ret = thermal_get_scenario(THERMAL_JSON_PATH, g_thermal); if (ret < 0) { _E("failed to get Thermal Monitor scenario\n"); free(g_thermal); -- 2.7.4 From 284147ad7bbdbb0b9ee98d9be0f31ec85221de79 Mon Sep 17 00:00:00 2001 From: Chanwoo Choi Date: Wed, 28 Jul 2021 10:01:07 +0900 Subject: [PATCH 15/16] pass: parser: Convert script format to json to improve readability The legacy .conf file format is not better on side of readability. So that change the configuration file format to json style to improve readability. Change-Id: I056971e4674ccfee703d3b55636575f8a0d83fbd Signed-off-by: Chanwoo Choi --- CMakeLists.txt | 1 - include/pass/common.h | 1 - include/pass/config-parser.h | 42 -- src/core/common.c | 11 - src/core/config-parser.c | 125 ----- src/pass/pass-cpuhp.c | 1 - src/pass/pass-parser.c | 1225 +++++++++++++++++++----------------------- src/pass/pass-pmqos.c | 3 +- src/pass/pass.c | 9 +- unittest/CMakeLists.txt | 1 - unittest/power-haltests.cpp | 4 +- 11 files changed, 570 insertions(+), 853 deletions(-) delete mode 100644 include/pass/config-parser.h delete mode 100644 src/core/config-parser.c diff --git a/CMakeLists.txt b/CMakeLists.txt index be26532..b381166 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -25,7 +25,6 @@ SET(SRCS src/thermal/thermal.c src/thermal/thermal-parser.c src/core/common.c - src/core/config-parser.c src/core/device-notifier.c src/core/devices.c src/core/main.c diff --git a/include/pass/common.h b/include/pass/common.h index 851212c..25d079e 100644 --- a/include/pass/common.h +++ b/include/pass/common.h @@ -94,7 +94,6 @@ typedef unsigned long long uint64; #endif int sys_get_str(const char *fname, char *str); -int sys_strtol(const char *str); const char *get_string_from_object(json_object *obj, const char *key); const int get_int_from_object(json_object *obj, const char *key); diff --git a/include/pass/config-parser.h b/include/pass/config-parser.h deleted file mode 100644 index 32a0d9b..0000000 --- a/include/pass/config-parser.h +++ /dev/null @@ -1,42 +0,0 @@ -/* - * PASS - * - * Copyright (c) 2017 Samsung Electronics Co., Ltd. - * - * Licensed under the Apache License, Version 2.0 (the License); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - - -#ifndef __CONFIG_PARSER_H__ -#define __CONFIG_PARSER_H__ - -#define MATCH(a, b) (!strncmp(a, b, strlen(a))) -#define SET_CONF(a, b) (a = (b > 0.0 ? b : a)) - -struct parse_result { - char *section; - char *name; - char *value; -}; - -/** - * @brief Parse config file and call callback\n - * @param[in] file_name conf file. - * @param[in] cb cb is called when conf file is parsed line by line. - * @param[in] user_data user data is passed to cb. - * @return 0 on success, negative if failed - */ -int config_parse(const char *file_name, int cb(struct parse_result *result, - void *user_data), void *user_data); - -#endif diff --git a/src/core/common.c b/src/core/common.c index 66fe952..17f9f23 100644 --- a/src/core/common.c +++ b/src/core/common.c @@ -73,17 +73,6 @@ int sys_get_str(const char *fname, char *str) return -1; } -int sys_strtol(const char *str) -{ - long value; - - value = strtol(str, (char**)NULL, 10); - if (value > INT_MAX || value < INT_MIN) - return -EINVAL; - - return (int)value; -} - const char *get_string_from_object(json_object *obj, const char *key) { json_object *tmp = NULL; diff --git a/src/core/config-parser.c b/src/core/config-parser.c deleted file mode 100644 index b13a5b2..0000000 --- a/src/core/config-parser.c +++ /dev/null @@ -1,125 +0,0 @@ -/* - * PASS - * - * Copyright (c) 2017 Samsung Electronics Co., Ltd. - * - * Licensed under the Apache License, Version 2.0 (the License); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include -#include -#include - -#include -#include - -#define BUFF_MAX 255 -#define MAX_SECTION 64 -#define WHITESPACE " \t" -#define NEWLINE "\n\r" -#define COMMENT '#' - -static inline char *trim_str(char *s) -{ - char *t; - /* left trim */ - s += strspn(s, WHITESPACE); - - /* right trim */ - for (t = strchr(s, 0); t > s; t--) - if (!strchr(WHITESPACE, t[-1])) - break; - *t = 0; - return s; -} - -int config_parse(const char *file_name, int cb(struct parse_result *result, - void *user_data), void *user_data) -{ - FILE *f = NULL; - struct parse_result result; - /* use stack for parsing */ - char line[BUFF_MAX]; - char section[MAX_SECTION]; - char *start, *end, *name, *value; - int lineno = 0, ret = 0; - - if (!file_name || !cb) { - ret = -EINVAL; - goto error; - } - - /* open conf file */ - f = fopen(file_name, "r"); - if (!f) { - ret = -EIO; - goto error; - } - - /* parsing line by line */ - while (fgets(line, BUFF_MAX, f) != NULL) { - lineno++; - - start = line; - start[strcspn(start, NEWLINE)] = '\0'; - start = trim_str(start); - - if (*start == COMMENT) { - continue; - } else if (*start == '[') { - /* parse section */ - end = strchr(start, ']'); - if (!end || *end != ']') { - ret = -EBADMSG; - goto error; - } - - *end = '\0'; - strncpy(section, start + 1, sizeof(section)); - section[MAX_SECTION-1] = '\0'; - } else if (*start) { - /* parse name & value */ - end = strchr(start, '='); - if (!end || *end != '=') { - ret = -EBADMSG; - goto error; - } - *end = '\0'; - name = trim_str(start); - value = trim_str(end + 1); - end = strchr(value, COMMENT); - if (end && *end == COMMENT) { - *end = '\0'; - value = trim_str(value); - } - - result.section = section; - result.name = name; - result.value = value; - /* callback with parse result */ - ret = cb(&result, user_data); - if (ret < 0) { - ret = -EBADMSG; - goto error; - } - } - } - - fclose(f); - return 0; - -error: - if (f) - fclose(f); - return ret; -} diff --git a/src/pass/pass-cpuhp.c b/src/pass/pass-cpuhp.c index 5345e03..7aaadb9 100644 --- a/src/pass/pass-cpuhp.c +++ b/src/pass/pass-cpuhp.c @@ -42,7 +42,6 @@ #include #include -#include #include "pass.h" #include "pass-rescon.h" diff --git a/src/pass/pass-parser.c b/src/pass/pass-parser.c index dac9724..77ebfd4 100644 --- a/src/pass/pass-parser.c +++ b/src/pass/pass-parser.c @@ -39,7 +39,6 @@ #include #include -#include #include #include "pass.h" @@ -49,7 +48,8 @@ #define MAX_TIMEOUT_SEC 3600.0 /* 1 hour */ #define INIT_VALUE -1 -static int compare_compatible_name(char *compatible, char *path_compatible) +static int compare_compatible_name(const char *compatible, + const char *path_compatible) { char buf[BUFF_MAX]; int len, ret; @@ -76,23 +76,6 @@ static int compare_compatible_name(char *compatible, char *path_compatible) return 0; } -static enum pass_state is_supported(char *value) -{ - enum pass_state state; - - if (!value) - return -EINVAL; - - if (MATCH(value, "yes")) - state = PASS_ON; - else if (MATCH(value, "no")) - state = PASS_OFF; - else - state = PASS_UNUSED; - - return state; -} - static void init_scenario(struct pass_scenario *scenario) { scenario->state = PASS_UNUSED; @@ -111,58 +94,56 @@ static void init_scenario(struct pass_scenario *scenario) /** * @brief Parse scenario section to get scenario name and information - * @param [in] result Parsed raw data from configuration + * @param [in] res Instance of h/w resource + * @param [in] obj Instance of json_object for h/w resource * @param [in] scenario Parsed data of a scenario will be saved to it * @return @c 0 on success, otherwise error value */ -static int parse_scenario(struct parse_result *result, +static int parse_scenario(struct pass_resource *res, json_object *obj, struct pass_scenario *scenario) { - int ret; - - if (!result || !scenario) - return 0; - - if (!result->section || !result->name || !result->value) - return 0; + const char *name = NULL; + int support; + int target_level; + int cpuhp_min_level; + int cpuhp_max_level; + int temperature; + int timer_interval_ms; + + /* Get property values */ + name = get_string_from_object(obj, "name"); + support = get_boolean_from_object(obj, "support"); + target_level= get_int_from_object(obj, "target_level"); + + /* - property for only pmqos module */ + cpuhp_min_level = get_int_from_object(obj, "cpuhp_min_level"); + cpuhp_max_level = get_int_from_object(obj, "cpuhp_max_level"); + + /* - property for only thermal module */ + temperature = get_int_from_object(obj, "temperature"); + timer_interval_ms = get_int_from_object(obj, "timer_interval_ms"); + + /* Check the mandatory property values are valid or not */ + if (!name) { + _E("Failed to get 'name' property in scenario section\n"); + return -EINVAL; + } else if (target_level < 0) { + _E("Failed to get 'target_level' property in scenario section\n"); + return -EINVAL; + } - /* Parse 'Scenario' section */ - if (MATCH(result->name, "name")) { - snprintf(scenario->name, BUFF_MAX, "%s", result->value); - } else if (MATCH(result->name, "support")) { - scenario->state = is_supported(result->value); - if (scenario->state < 0) - return -EINVAL; - } else if (MATCH(result->name, "scenario_level")) { - ret = sys_strtol(result->value); - if (ret < 0) - return ret; - scenario->level = ret; + /* Initialize config_data from property values of confiugartion file */ + snprintf(scenario->name, NAME_MAX, "%s", name); + scenario->state = (support < 0) ? 1 : support; + scenario->level = target_level; - /* Parse properties for only PASS_MODULE_PMQOS */ - } else if (MATCH(result->name, "min_level")) { - ret = sys_strtol(result->value); - if (ret < 0) - return ret; - scenario->pmqos.min_level = ret; - } else if (MATCH(result->name, "max_level")) { - ret = sys_strtol(result->value); - if (ret < 0) - return ret; - scenario->pmqos.max_level = ret; + /* - property for only pmqos module */ + scenario->pmqos.min_level = cpuhp_min_level; + scenario->pmqos.max_level = cpuhp_max_level; - /* Parse properties for only PASS_MODULE_THERMAL */ - } else if (MATCH(result->name, "temperature")) { - ret = sys_strtol(result->value); - if (ret < 0) - return ret; - scenario->thermal.temperature = ret; - } else if (MATCH(result->name, "timer_interval_ms")) { - ret = sys_strtol(result->value); - if (ret < 0) - return ret; - scenario->thermal.timer_interval = ret; - } + /* - property for only thermal module */ + scenario->thermal.temperature = temperature; + scenario->thermal.timer_interval = timer_interval_ms; return 0; } @@ -206,7 +187,7 @@ static int verify_level(int res_type, int level_idx, struct pass_level *level) return 0; } -static void init_level(struct pass_level *level) +static void initialize_level(struct pass_level *level) { level->limit_max_freq = INIT_VALUE; level->limit_min_freq = INIT_VALUE; @@ -234,16 +215,75 @@ static void init_level(struct pass_level *level) level->fault_around_bytes = INIT_VALUE; } -static int parse_level(struct parse_result *result, - struct pass_level *level) +static int parse_level(struct pass_resource *res, json_object *obj, + struct pass_level *target_level, int level_idx) { - int ret; - - if (!result || !level) - return 0; + int level; + int minimum_frequency_khz; + int maximum_frequency_khz; + int number_of_minimum_cpu; + int number_of_maximum_cpu; + int num_down_cond; + int num_down_cond_freq; + int num_down_cond_nr_running; + int num_down_cond_busy_cpu; + int num_up_cond; + int num_up_cond_freq; + int num_up_cond_nr_running; + int num_up_cond_busy_cpu; + int num_right_cond; + int num_right_cond_freq; + int num_right_cond_nr_running; + int num_right_cond_busy_cpu; + int num_left_cond; + int num_left_cond_freq; + int num_left_cond_nr_running; + int num_left_cond_busy_cpu; + double governor_timeout_sec; + int fault_around_bytes; + + /* Get property values */ + level = get_int_from_object(obj, "level"); + minimum_frequency_khz = get_int_from_object(obj, "dvfs,minimum_frequency_khz"); + maximum_frequency_khz = get_int_from_object(obj, "dvfs,maximum_frequency_khz"); + number_of_minimum_cpu = get_int_from_object(obj, "hotplug,number_of_minimum_cpu"); + number_of_maximum_cpu = get_int_from_object(obj, "hotplug,number_of_maximum_cpu"); + + num_down_cond = get_int_from_object(obj, "hotplug,num_down_cond"); + num_down_cond_freq = get_int_from_object(obj, "hotplug,num_down_cond_freq"); + num_down_cond_nr_running = get_int_from_object(obj, "hotplug,num_down_cond_nr_running"); + num_down_cond_busy_cpu = get_int_from_object(obj, "hotplug,num_down_cond_busy_cpu"); + + num_up_cond = get_int_from_object(obj, "hotplug,num_up_cond"); + num_up_cond_freq = get_int_from_object(obj, "hotplug,num_up_cond_freq"); + num_up_cond_nr_running = get_int_from_object(obj, "hotplug,num_up_cond_nr_running"); + num_up_cond_busy_cpu = get_int_from_object(obj, "hotplug,num_up_cond_busy_cpu"); + + num_right_cond = get_int_from_object(obj, "hotplug,num_right_cond"); + num_right_cond_freq = get_int_from_object(obj, "hotplug,num_right_cond_freq"); + num_right_cond_nr_running = get_int_from_object(obj, "hotplug,num_right_cond_nr_running"); + num_right_cond_busy_cpu = get_int_from_object(obj, "hotplug,num_right_cond_busy_cpu"); + + num_left_cond = get_int_from_object(obj, "hotplug,num_left_cond"); + num_left_cond_freq = get_int_from_object(obj, "hotplug,num_left_cond_freq"); + num_left_cond_nr_running = get_int_from_object(obj, "hotplug,num_left_cond_nr_running"); + num_left_cond_busy_cpu = get_int_from_object(obj, "hotplug,num_left_cond_busy_cpu"); + + governor_timeout_sec = get_double_from_object(obj, "hotplug,governor_timeout_sec"); + + fault_around_bytes = get_int_from_object(obj, "memory,fault_around_bytes"); + + /* Check the mandatory property values are valid or not */ + if (level < 0) { + _E("Failed to get 'level' property in 'level_list' section\n"); + return -EINVAL; + } else if (level != level_idx) { + _E("Invalid 'level' property value(%d) in 'level_list' section\n", + level); + return -EINVAL; + } - if (!result->section || !result->name || !result->value) - return 0; + /* Initialize config_data from property values of confiugartion file */ /* * Properties for the following h/w resources: @@ -251,189 +291,115 @@ static int parse_level(struct parse_result *result, * - PASS_RESOURCE_BUS_ID * - PASS_RESOURCE_GPU_ID */ - if (MATCH(result->name, "limit_max_freq")) { - ret = sys_strtol(result->value); - if (ret < 0) - return ret; - level->limit_max_freq = ret; - } else if (MATCH(result->name, "limit_min_freq")) { - ret = sys_strtol(result->value); - if (ret < 0) - return ret; - level->limit_min_freq = ret; + if (minimum_frequency_khz >= 0) + target_level->limit_min_freq = minimum_frequency_khz; + if (maximum_frequency_khz >= 0) + target_level->limit_max_freq = maximum_frequency_khz; /* * Properties for the following h/w resources: * - PASS_RESOURCE_CPU_ID */ - } else if (MATCH(result->name, "limit_max_cpu")) { - ret = sys_strtol(result->value); - if (ret < 0) - return ret; - level->limit_max_cpu = ret; - } else if (MATCH(result->name, "limit_min_cpu")) { - ret = sys_strtol(result->value); - if (ret < 0) - return ret; - level->limit_min_cpu = ret; - } else if (MATCH(result->name, "num_down_cond")) { - ret = sys_strtol(result->value); - if (ret < 0) - return ret; - level->num_down_cond = ret; - } else if (MATCH(result->name, "num_down_cond_freq")) { - ret = sys_strtol(result->value); - if (ret < 0) - return ret; - level->down_cond[0].freq = ret; - } else if (MATCH(result->name, "num_down_cond_nr_running")) { - ret = sys_strtol(result->value); - if (ret < 0) - return ret; - level->down_cond[0].nr_running = ret; - } else if (MATCH(result->name, "num_down_cond_busy_cpu")) { - ret = sys_strtol(result->value); - if (ret < 0) - return ret; - level->down_cond[0].busy_cpu = ret; - - } else if (MATCH(result->name, "num_up_cond")) { - ret = sys_strtol(result->value); - if (ret < 0) - return ret; - level->num_up_cond = ret; - } else if (MATCH(result->name, "num_up_cond_freq")) { - ret = sys_strtol(result->value); - if (ret < 0) - return ret; - level->up_cond[0].freq = ret; - } else if (MATCH(result->name, "num_up_cond_nr_running")) { - ret = sys_strtol(result->value); - if (ret < 0) - return ret; - level->up_cond[0].nr_running = ret; - } else if (MATCH(result->name, "num_up_cond_busy_cpu")) { - ret = sys_strtol(result->value); - if (ret < 0) - return ret; - level->up_cond[0].busy_cpu = ret; - - } else if (MATCH(result->name, "num_left_cond")) { - ret = sys_strtol(result->value); - if (ret < 0) - return ret; - level->num_left_cond = ret; - } else if (MATCH(result->name, "num_left_cond_freq")) { - ret = sys_strtol(result->value); - if (ret < 0) - return ret; - level->left_cond[0].freq = ret; - } else if (MATCH(result->name, "num_left_cond_nr_running")) { - ret = sys_strtol(result->value); - if (ret < 0) - return ret; - level->left_cond[0].nr_running = ret; - } else if (MATCH(result->name, "num_left_cond_busy_cpu")) { - ret = sys_strtol(result->value); - if (ret < 0) - return ret; - level->left_cond[0].busy_cpu = ret; - - } else if (MATCH(result->name, "num_right_cond")) { - ret = sys_strtol(result->value); - if (ret < 0) - return ret; - level->num_right_cond = ret; - } else if (MATCH(result->name, "num_right_cond_freq")) { - ret = sys_strtol(result->value); - if (ret < 0) - return ret; - level->right_cond[0].freq = ret; - } else if (MATCH(result->name, "num_right_cond_nr_running")) { - ret = sys_strtol(result->value); - if (ret < 0) - return ret; - level->right_cond[0].nr_running = ret; - } else if (MATCH(result->name, "num_right_cond_busy_cpu")) { - ret = sys_strtol(result->value); - if (ret < 0) - return ret; - level->right_cond[0].busy_cpu = ret; - - } else if (MATCH(result->name, "gov_timeout")) { - double gov_timeout = strtod(result->value, (char **)NULL); - - if (gov_timeout < MIN_TIMEOUT_SEC - || gov_timeout > MAX_TIMEOUT_SEC) - gov_timeout = MIN_TIMEOUT_SEC; - - level->gov_timeout = gov_timeout; + if (number_of_minimum_cpu >= 0) + target_level->limit_min_cpu = number_of_minimum_cpu; + if (number_of_maximum_cpu >= 0) + target_level->limit_max_cpu = number_of_maximum_cpu; + + if (num_down_cond >= 0) + target_level->num_down_cond = num_down_cond; + if (num_down_cond_freq >= 0) + target_level->down_cond[0].freq = num_down_cond_freq; + if (num_down_cond_nr_running >= 0) + target_level->down_cond[0].nr_running = num_down_cond_nr_running; + if (num_down_cond_busy_cpu >= 0) + target_level->down_cond[0].busy_cpu = num_down_cond_busy_cpu; + + if (num_up_cond >= 0) + target_level->num_up_cond = num_up_cond; + if (num_up_cond_freq >= 0) + target_level->up_cond[0].freq = num_up_cond_freq; + if (num_up_cond_nr_running >= 0) + target_level->up_cond[0].nr_running = num_up_cond_nr_running; + if (num_up_cond_busy_cpu >= 0) + target_level->up_cond[0].busy_cpu = num_up_cond_busy_cpu; + + if (num_left_cond >= 0) + target_level->num_left_cond = num_left_cond; + if (num_left_cond_freq >= 0) + target_level->left_cond[0].freq = num_left_cond_freq; + if (num_left_cond_nr_running >= 0) + target_level->left_cond[0].nr_running = num_left_cond_nr_running; + if (num_left_cond_busy_cpu >= 0) + target_level->left_cond[0].busy_cpu = num_left_cond_busy_cpu; + + if (num_right_cond >= 0) + target_level->num_right_cond = num_right_cond; + if (num_right_cond_freq >= 0) + target_level->right_cond[0].freq = num_right_cond_freq; + if (num_right_cond_nr_running >= 0) + target_level->right_cond[0].nr_running = num_right_cond_nr_running; + if (num_right_cond_busy_cpu >= 0) + target_level->right_cond[0].busy_cpu = num_right_cond_busy_cpu; + + if (governor_timeout_sec >= 0) { + if (governor_timeout_sec < MIN_TIMEOUT_SEC + || governor_timeout_sec > MAX_TIMEOUT_SEC) + governor_timeout_sec = MIN_TIMEOUT_SEC; + target_level->gov_timeout = governor_timeout_sec; + } /* * Properties for the following h/w resources: * - PASS_RESOURCE_MEMORY_ID */ - } else if (MATCH(result->name, "fault_around_bytes")) { - ret = sys_strtol(result->value); - if (ret < 0) - return ret; - level->fault_around_bytes = ret; - } + if (fault_around_bytes >= 0) + target_level->fault_around_bytes = fault_around_bytes; return 0; } /** * @brief Parse pmqos section to get PASS_MODULE_PMQOS information - * @param [in] result Parsed raw data from configuration - * @param [in] user_data Instance of h/w resource + * @param [in] res Instance of h/w resource + * @param [in] obj Instance of json_object for h/w resource * @return @c 0 on success, otherwise error value */ -static int parse_pmqos(struct parse_result *result, void *user_data) +static int parse_pmqos(struct pass_resource *res, json_object *obj) { - struct pass_resource *res = user_data; - struct pass_pmqos *pmqos = &res->pmqos; - - if (!result) - return 0; - - if (!result->section || !result->name || !result->value) + int pmqos_support; + json_object *pmqos_scenario_list = NULL; + int num_scenarios = 0, ret, i; + + /* Get property values */ + pmqos_support = get_boolean_from_object(obj, "pmqos_support"); + if (json_object_object_get_ex(obj, "pmqos_scenario_list", + &pmqos_scenario_list)) + num_scenarios = json_object_array_length(pmqos_scenario_list); + + /* Check the mandatory property values are valid or not */ + if (pmqos_support <= 0) return 0; - /* Parse 'PassScenario' section */ - if (MATCH(result->name, "pass_scenario_support")) { - pmqos->state = is_supported(result->value); - if (pmqos->state < 0) - return -EINVAL; + /* Initialize config_data from property values of confiugartion file */ + res->pmqos.state = pmqos_support; + res->pmqos.scenarios = calloc(num_scenarios, + sizeof(struct pass_scenario)); + if (!res->pmqos.scenarios) { + _E("cannot allocate memory for Scenario\n"); + return -EINVAL; + } + res->pmqos.num_scenarios = num_scenarios; - } else if (MATCH(result->name, "pass_num_scenarios")) { - unsigned int num_scenarios; - int ret; + for (i = 0; i < res->pmqos.num_scenarios; i++) { + json_object *scenario_obj + = json_object_array_get_idx(pmqos_scenario_list, i); + struct pass_scenario *scenario = &(res->pmqos.scenarios[i]); - ret = sys_strtol(result->value); - if (ret < 0) + init_scenario(scenario); + ret = parse_scenario(res, scenario_obj, scenario); + if (ret < 0) { + _E("cannot parse 'pmqos.scenario%d' section\n", i); return ret; - num_scenarios = ret; - - if (num_scenarios > MAX_NUM) { - _E("cannot parse %s\n", result->name); - return -EINVAL; - } - - if (num_scenarios > 0 && !pmqos->scenarios) { - int i; - - pmqos->scenarios = calloc(num_scenarios, - sizeof(struct pass_scenario)); - if (!pmqos->scenarios) { - _E("cannot allocate memory for Scenario\n"); - return -EINVAL; - } - - pmqos->num_scenarios = num_scenarios; - - for (i = 0; i < num_scenarios; i++) - init_scenario(&pmqos->scenarios[i]); } } @@ -442,515 +408,419 @@ static int parse_pmqos(struct parse_result *result, void *user_data) /** * @brief Parse thermal section to get PASS_MODULE_THERMAL information - * @param [in] result Parsed raw data from configuration - * @param [in] user_data Instance of h/w resource + * @param [in] res Instance of h/w resource + * @param [in] obj Instance of json_object for h/w resource * @return @c 0 on success, otherwise error value */ -static int parse_thermal(struct parse_result *result, void *user_data) +static int parse_thermal(struct pass_resource *res, json_object *obj) { - struct pass_resource *res = user_data; - struct pass_thermal *thermal = &res->thermal; - int ret; - - if (!result) - return 0; - - if (!result->section || !result->name || !result->value) + int thermal_support; + int thermal_timer_interval_ms; + json_object *thermal_scenario_list = NULL; + int num_scenarios = 0, ret, i; + + /* Get property values */ + thermal_support = get_boolean_from_object(obj, "thermal_support"); + thermal_timer_interval_ms + = get_int_from_object(obj, "thermal_timer_interval_ms"); + if (json_object_object_get_ex(obj, "thermal_scenario_list", + &thermal_scenario_list)) + num_scenarios = json_object_array_length(thermal_scenario_list); + + /* Check the mandatory property values are valid or not */ + if (thermal_support <= 0) return 0; - /* Parse 'thermal' section */ - if (MATCH(result->name, "thermal_support")) { - thermal->state = is_supported(result->value); - if (thermal->state < 0) - return -EINVAL; - } else if (MATCH(result->name, "thermal_number_of_scenario")) { - unsigned int num_scenarios; - - ret = sys_strtol(result->value); - if (ret < 0) - return ret; - num_scenarios = ret; + /* Initialize config_data from property values of confiugartion file */ + res->thermal.state = thermal_support; + res->thermal.timer_interval = thermal_timer_interval_ms; - if (num_scenarios > MAX_NUM) { - _E("cannot parse %s\n", result->name); - return -EINVAL; - } - - if (num_scenarios > 0 && !thermal->scenarios) { - int i; + res->thermal.scenarios = calloc(num_scenarios, + sizeof(struct pass_scenario)); + if (!res->thermal.scenarios) { + _E("cannot allocate memory for Scenario\n"); + return -EINVAL; + } + res->thermal.num_scenarios = num_scenarios; - thermal->scenarios = calloc(num_scenarios, - sizeof(struct pass_scenario)); - if (!thermal->scenarios) { - _E("cannot allocate memory for Scenario\n"); - return -EINVAL; - } - thermal->num_scenarios = num_scenarios; + for (i = 0; i < res->thermal.num_scenarios; i++) { + json_object *scenario_obj + = json_object_array_get_idx(thermal_scenario_list, i); + struct pass_scenario *scenario = &(res->thermal.scenarios[i]); - for (i = 0; i < num_scenarios; i++) - init_scenario(&thermal->scenarios[i]); - } - } else if (MATCH(result->name, "thermal_timer_interval_ms")) { - ret = sys_strtol(result->value); - if (ret < 0) + init_scenario(scenario); + ret = parse_scenario(res, scenario_obj, scenario); + if (ret < 0) { + _E("cannot parse 'thermal.scenario%d' section\n", i); return ret; - thermal->timer_interval = ret; + } } return 0; } /** - * @brief Parse core section to get module information - * @param [in] result Parsed raw data from configuration - * @param [in] user_data Instance of h/w resource + * @brief Parse cpuhp section to get module information + * @param [in] res Instance of h/w resource + * @param [in] obj Instance of json_object for h/w resource * @return @c 0 on success, otherwise error value */ -static int parse_core(struct parse_result *result, void *user_data) +static int parse_cpuhp(struct pass_resource *res, json_object *obj) { - struct pass_resource *res = user_data; - int ret; - - if (!result) + int cpuhp_support; + int cpuhp_governor; + double cpuhp_timer_interval_sec; + int cpuhp_min_level; + int cpuhp_max_level; + int cpuhp_init_level; + int cpuhp_cpu_threshold; + int cpuhp_up_threshold; + int cpuhp_down_threshold; + json_object *cpuhp_level_list = NULL; + int cpuhp_num_levels = 0, ret, i; + + /* Get property values */ + cpuhp_support = get_int_from_object(obj, "cpuhp_support"); + cpuhp_governor = get_int_from_object(obj, "cpuhp_governor"); + cpuhp_timer_interval_sec = get_int_from_object(obj, "cpuhp_timer_interval_sec"); + cpuhp_min_level = get_int_from_object(obj, "cpuhp_min_level"); + cpuhp_max_level = get_int_from_object(obj, "cpuhp_max_level"); + cpuhp_init_level = get_int_from_object(obj, "cpuhp_init_level"); + cpuhp_cpu_threshold = get_int_from_object(obj, "cpuhp_cpu_threshold"); + cpuhp_up_threshold = get_int_from_object(obj, "cpuhp_up_threshold"); + cpuhp_down_threshold= get_int_from_object(obj, "cpuhp_down_threshold"); + + if (json_object_object_get_ex(obj, "cpuhp_level_list", &cpuhp_level_list)) + cpuhp_num_levels = json_object_array_length(cpuhp_level_list); + + /* Check the mandatory property values are valid or not */ + if (cpuhp_support <= 0) { return 0; - - if (!result->section || !result->name || !result->value) - return 0; - - if (MATCH(result->name, "pass_support")) { - int state; - - state = sys_strtol(result->value); - if (state < 0) - return state; - res->config_data.state = state; - } else if (MATCH(result->name, "pass_gov_type")) { - int gov_type; - - gov_type = sys_strtol(result->value); - if (gov_type < 0) - return gov_type; - res->config_data.gov_type = gov_type; - } else if (MATCH(result->name, "pass_num_levels")) { - int num_levels; - - num_levels = sys_strtol(result->value); - if (num_levels < 0) - return num_levels; - if (num_levels > MAX_NUM) { - _E("cannot parse %s\n", result->name); - return -EINVAL; - } - res->config_data.num_levels = num_levels; - } else if (MATCH(result->name, "pass_min_level")) { - ret = sys_strtol(result->value); - if (ret < 0) - return ret; - res->rescon.min_level = ret; - } else if (MATCH(result->name, "pass_max_level")) { - ret = sys_strtol(result->value); - if (ret < 0) - return ret; - res->rescon.max_level = ret; - } else if (MATCH(result->name, "pass_init_level")) { - ret = sys_strtol(result->value); - if (ret < 0) - return ret; - res->rescon.init_level = ret; - - } else if (MATCH(result->name, "pass_num_scenario_levels")) { - int num_scenario_levels; - - num_scenario_levels = sys_strtol(result->value); - if (num_scenario_levels < 0) - return num_scenario_levels; - if (num_scenario_levels > MAX_NUM) { - _E("cannot parse %s\n", result->name); - return -EINVAL; - } - res->config_data.num_scenario_levels = num_scenario_levels; - } else if (MATCH(result->name, "pass_init_scenario_level")) { - unsigned int init_level; - - ret = sys_strtol(result->value); - if (ret < 0) - return ret; - init_level = ret; - - if (init_level > MAX_NUM) { - _E("cannot parse %s\n", result->name); - return -EINVAL; - } - res->rescon.init_scenario_level = init_level; - - } else if (MATCH(result->name, "pass_cpu_threshold")) { - ret = sys_strtol(result->value); - if (ret < 0) - return ret; - res->cpuhp.pass_cpu_threshold = ret; - } else if (MATCH(result->name, "pass_up_threshold")) { - ret = sys_strtol(result->value); - if (ret < 0) - return ret; - res->cpuhp.up_threshold = ret; - } else if (MATCH(result->name, "pass_down_threshold")) { - ret = sys_strtol(result->value); - if (ret < 0) - return ret; - res->cpuhp.down_threshold = ret; - } else if (MATCH(result->name, "pass_governor_timeout")) { - res->config_data.gov_timeout - = strtod(result->value, (char **)NULL); - - if (res->config_data.gov_timeout < MIN_TIMEOUT_SEC - || res->config_data.gov_timeout > MAX_TIMEOUT_SEC) - res->config_data.gov_timeout = MIN_TIMEOUT_SEC; + } else if (cpuhp_governor < 0) { + _E("Failed to get 'cpuhp_governor' property\n"); + return -EINVAL; + } else if (!cpuhp_level_list) { + _E("Failed to get 'cpuhp_level_list' property\n"); + return -EINVAL; + } else if (cpuhp_num_levels <= 0) { + _E("Must need to add at least one level in 'cpuhp_level_list' section\n"); + return -EINVAL; } - if (res->config_data.num_levels > 0 && !res->config_data.levels) { - int i; + /* Initialize config_data from property values of confiugartion file */ + /* - core */ + res->config_data.state = cpuhp_support; + res->config_data.gov_type = cpuhp_governor; + res->config_data.gov_timeout = cpuhp_timer_interval_sec; + if (res->config_data.gov_timeout < MIN_TIMEOUT_SEC + || res->config_data.gov_timeout > MAX_TIMEOUT_SEC) + res->config_data.gov_timeout = MIN_TIMEOUT_SEC; + + /* - properties for rescon module */ + res->rescon.min_level = cpuhp_min_level; + res->rescon.max_level = cpuhp_max_level; + res->rescon.init_level = cpuhp_init_level; + + /* - properties for cpuhp module */ + res->cpuhp.pass_cpu_threshold = cpuhp_cpu_threshold; + res->cpuhp.up_threshold = cpuhp_up_threshold; + res->cpuhp.down_threshold = cpuhp_down_threshold; + + res->config_data.num_levels = cpuhp_num_levels; + res->config_data.levels = calloc(res->config_data.num_levels, + sizeof(struct pass_level)); + if (!res->config_data.levels) { + _E("cannot allocate memory for cpuhp level list\n"); + return -EINVAL; + } - res->config_data.levels = calloc(res->config_data.num_levels, - sizeof(struct pass_level)); - if (!res->config_data.levels) { - _E("cannot allocate memory for levels\n"); - return -EINVAL; - } + for (i = 0; i < res->config_data.num_levels; i++) { + json_object *level_obj = json_object_array_get_idx(cpuhp_level_list, i); + struct pass_level *level = &res->config_data.levels[i]; - /* Initialize pass_level before parsing */ - for (i = 0; i < res->config_data.num_levels; i++) - init_level(&res->config_data.levels[i]); - } else if (res->config_data.num_scenario_levels > 0 - && !res->config_data.scenario_levels) { - int i; - - res->config_data.scenario_levels = - calloc(res->config_data.num_scenario_levels, - sizeof(struct pass_level)); - if (!res->config_data.scenario_levels) { - _E("cannot allocate memory for levels\n"); - return -EINVAL; + initialize_level(level); + ret = parse_level(res, level_obj, level, i); + if (ret < 0) { + _E("cannot parse level%d in 'level_list' section\n", i); + return ret; } - - /* Initialize scenariop pass_level before parsing */ - for (i = 0; i < res->config_data.num_scenario_levels; i++) - init_level(&res->config_data.scenario_levels[i]); } return 0; } + /** - * @brief Parse configuration for each h/w resource - * @param [in] result Parsed raw data from configuration - * @param [in] user_data Instance of h/w resource + * @brief Parse core section to get module information + * @param [in] res Instance of h/w resource + * @param [in] obj Instance of json_object for h/w resource * @return @c 0 on success, otherwise error value */ -static int parse_each_resource(struct parse_result *result, void *user_data) +static int parse_header(struct pass_resource *res, json_object *obj) { - struct pass_resource *res = user_data; - struct pass_pmqos *pmqos = &res->pmqos; - struct pass_thermal *thermal = &res->thermal; - struct pass_level *level; - char section_name[BUFF_MAX]; - int i, ret; - - if (!result) - return 0; - - if (!result->section || !result->name || !result->value) - return 0; - - /* Parsing 'PASS' section */ - if (MATCH(result->section, "Pass")) { - ret = parse_core(result, user_data); - if (ret < 0) { - _E("cannot parse the core part\n"); - return ret; - } - - goto out; + int support; + int init_level; + json_object *level_list = NULL; + int num_levels = 0, ret, i; + + /* Get property values */ + support = get_boolean_from_object(obj, "support"); + init_level = get_int_from_object(obj, "init_level"); + if (json_object_object_get_ex(obj, "level_list", &level_list)) + num_levels = json_object_array_length(level_list); + + /* Check the mandatory property values are valid or not */ + if (support < 0) { + _E("Failed to get 'support' property\n"); + return -EINVAL; + } else if (!level_list) { + _E("Failed to get 'level_list' property\n"); + return -EINVAL; + } else if (num_levels <= 0) { + _E("Must need to add at least one level in 'level_list' section\n"); + return -EINVAL; + } else if (init_level > num_levels) { + _E("Invalid 'init_level' in core section\n"); + return -EINVAL; } - /* Parsing 'Level' section */ - for (i = 0; i < res->config_data.num_levels; i++) { - ret = snprintf(section_name, BUFF_MAX, "Level%d", i); + if (init_level < 0) + init_level = 0; - if (MATCH(result->section, section_name)) { - ret = parse_level(result, &res->config_data.levels[i]); - if (ret < 0) { - _E("cannot parse 'Level%d' section\n", i); - return ret; - } - goto out; - } + /* Initialize config_data from property values of confiugartion file */ + res->config_data.state = support; + res->config_data.num_scenario_levels = num_levels; + res->rescon.init_scenario_level = init_level; + res->config_data.scenario_levels = calloc( + res->config_data.num_scenario_levels, + sizeof(struct pass_level)); + if (!res->config_data.scenario_levels) { + _E("cannot allocate memory for scenario level list\n"); + return -EINVAL; } - /* Parsing 'ScenarioLevel' section */ for (i = 0; i < res->config_data.num_scenario_levels; i++) { - ret = snprintf(section_name, BUFF_MAX, "ScenarioLevel%d", i); - - if (MATCH(result->section, section_name)) { - level = &res->config_data.scenario_levels[i]; - - ret = parse_level(result, level); - if (ret < 0) { - _E("cannot parse 'ScenarioLevel%d' section\n", i); - return ret; - } + json_object *level_obj = json_object_array_get_idx(level_list, i); + struct pass_level *level = &res->config_data.scenario_levels[i]; - goto out; - } - } - - /* Parsing 'PassScenario' section */ - if (MATCH(result->section, "PassScenario")) { - ret = parse_pmqos(result, user_data); + initialize_level(level); + ret = parse_level(res, level_obj, level, i); if (ret < 0) { - _E("cannot parse 'PassScenario' section\n"); + _E("cannot parse level%d in 'level_list' section\n", i); return ret; } - - goto out; } - /* Parsing 'Scenario' section */ - for (i = 0; i < pmqos->num_scenarios; i++) { - ret = snprintf(section_name, BUFF_MAX, "Scenario%d", i); + return 0; +} - if (MATCH(result->section, section_name)) { - ret = parse_scenario(result, &pmqos->scenarios[i]); - if (ret < 0) { - _E("cannot parse 'Scenario%d' section\n", i); - return ret; - } +/** + * @brief Parse configuration for each h/w resource + * @param [in] res Instance of h/w resource + * @param [in] obj Instance of json_object for h/w resource + * @return @c 0 on success, otherwise error value + */ +static int parse_each_resource(struct pass_resource *res, json_object *obj) +{ + int ret; - goto out; - } + /* Parse header */ + ret = parse_header(res, obj); + if (ret < 0) { + _E("cannot parse the core part\n"); + return ret; } - /* Parsing 'thermal' section */ - if (MATCH(result->section, "thermal")) { - ret = parse_thermal(result, user_data); - if (ret < 0) { - _E("cannot parse 'thermal' section\n"); - return ret; - } - - goto out; + /* Parse pmqos module */ + ret = parse_pmqos(res, obj); + if (ret < 0) { + _E("cannot parse 'PassScenario' section\n"); + return ret; } - /* Parsing 'thermal.scenario' section */ - for (i = 0; i < thermal->num_scenarios; i++) { - ret = snprintf(section_name, BUFF_MAX, "thermal.scenario%d", i); - - if (MATCH(result->section, section_name)) { - ret = parse_scenario(result, &thermal->scenarios[i]); - if (ret < 0) { - _E("cannot parse 'thermal.scenario%d' section\n", i); - return ret; - } + /* Parse thermal module */ + ret = parse_thermal(res, obj); + if (ret < 0) { + _E("cannot parse 'thermal' section\n"); + return ret; + } - goto out; - } + /* Parse cpuhp module */ + ret = parse_cpuhp(res, obj); + if (ret < 0) { + _E("cannot parse the cpuhp part\n"); + return ret; } -out: return 0; } /** * @brief Parse resource section in pass.conf for each h/w resource - * @param [in] result Parsed raw data from configuration - * @param [in] user_data Instance of h/w resource - * @param [in] id Resource index number + * @param [in] pass Instance of struct pass + * @param [in] obj Instance of json_object for h/w resource * @return @c 0 on success, otherwise error value */ -static int parse_resource_data(struct parse_result *result, - void *user_data, int id) +static int parse_resource_data(struct pass *pass, int id, json_object *obj) { - char buf[BUFF_MAX]; - struct pass *pass = user_data; struct pass_resource_config_data *config_data = &(pass->res[id].config_data); - int ret; - - if (!result) - return 0; + const char *device_type; + const char *device_name; + const char *thermal_device_name; + const char *device_config_path; + const char *cpu_load_path; + int number_of_cpus; + int first_cpu; + + /* Get property values */ + /* - mandatory properties */ + device_type = get_string_from_object(obj, "device_type"); + device_name = get_string_from_object(obj, "device_name"); + device_config_path = get_string_from_object(obj, "device_config_path"); + + /* - optional properties */ + thermal_device_name = get_string_from_object(obj, "thermal_device_name"); + + /* - optional properties for only CPU */ + cpu_load_path = get_string_from_object(obj, "cpu,cpu_load_path"); + number_of_cpus = get_int_from_object(obj, "cpu,number_of_cpus"); + first_cpu = get_int_from_object(obj, "cpu,first_cpu"); + + /* Check the mandatory property values are valid or not */ + if (!device_type) { + _E("Failed to get 'device_type' property of resource in 'device_list' of %s\n", + config_data->res_name); + return -EINVAL; + } else if (!device_name) { + _E("Failed to get 'device_name' property of resource in 'device_list' of %s\n", + config_data->res_name); + return -EINVAL; + } else if (!device_config_path) { + _E("Failed to get 'device_config_path' property of resource in 'device_list' of %s\n", + config_data->res_name); + return -EINVAL; + } - if (MATCH(result->name, "pass_res_type")) { - int i; - - memset(buf, 0, BUFF_MAX); - for (i = 0; i < strlen(result->value); i++) - buf[i] = tolower(result->value[i]); - - if (!strncmp(buf, PASS_RESOURCE_CPU_NAME, strlen(buf))) - config_data->res_type = PASS_RESOURCE_CPU_ID; - else if (!strncmp(buf, PASS_RESOURCE_GPU_NAME, strlen(buf))) - config_data->res_type = PASS_RESOURCE_GPU_ID; - else if (!strncmp(buf, PASS_RESOURCE_BUS_NAME, strlen(buf))) - config_data->res_type = PASS_RESOURCE_BUS_ID; - else if (!strncmp(buf, PASS_RESOURCE_MEMORY_NAME, strlen(buf))) - config_data->res_type = PASS_RESOURCE_MEMORY_ID; - else if (!strncmp(buf, PASS_RESOURCE_NONSTANDARD_NAME, strlen(buf))) - config_data->res_type = PASS_RESOURCE_NONSTANDARD_ID; - else - return -EINVAL; - } else if (MATCH(result->name, "pass_res_name")) { - snprintf(config_data->res_name, BUFF_MAX, "%s", result->value); - } else if (MATCH(result->name, "pass_res_thermal_name")) { - snprintf(config_data->res_thermal_name, BUFF_MAX, "%s", result->value); - } else if (MATCH(result->name, "pass_path_conf_file")) { - snprintf(config_data->path_conf_file, BUFF_MAX, "%s", result->value); - } else if (MATCH(result->name, "pass_path_load_table")) { - snprintf(config_data->path_load_table, BUFF_MAX, "%s", result->value); - } else if (MATCH(result->name, "pass_first_cpu")) { - int res_type = config_data->res_type; - - switch (res_type) { - case PASS_RESOURCE_CPU_ID: - ret = sys_strtol(result->value); - if (ret < 0) - return ret; - config_data->cpu = ret; - break; - default: - return -EINVAL; - } - } else if (MATCH(result->name, "pass_num_cpus")) { - int res_type = config_data->res_type; - - switch (res_type) { - case PASS_RESOURCE_CPU_ID: - ret = sys_strtol(result->value); - if (ret < 0) - return ret; - config_data->num_cpus = ret; - break; - default: + switch (config_data->res_type) { + case PASS_RESOURCE_CPU_ID: + if (number_of_cpus < 0 || first_cpu < 0) { + _E("Invalid 'number_of_cpus'(%d) or 'first_cpu'(%d) property value of %s\n", + number_of_cpus, first_cpu, config_data->res_name); return -EINVAL; } + break; + default: + break; + } + + /* Initialize config_data from property values of confiugartion file */ + if (!strncmp(device_type, PASS_RESOURCE_CPU_NAME, strlen(device_type))) + config_data->res_type = PASS_RESOURCE_CPU_ID; + else if (!strncmp(device_type, PASS_RESOURCE_GPU_NAME, strlen(device_type))) + config_data->res_type = PASS_RESOURCE_GPU_ID; + else if (!strncmp(device_type, PASS_RESOURCE_BUS_NAME, strlen(device_type))) + config_data->res_type = PASS_RESOURCE_BUS_ID; + else if (!strncmp(device_type, PASS_RESOURCE_MEMORY_NAME, strlen(device_type))) + config_data->res_type = PASS_RESOURCE_MEMORY_ID; + else if (!strncmp(device_type, PASS_RESOURCE_NONSTANDARD_NAME, strlen(device_type))) + config_data->res_type = PASS_RESOURCE_NONSTANDARD_ID; + else { + _E("Unknown 'device_type' property value (%s)\n", device_type); + return -EINVAL; } + snprintf(config_data->res_name, BUFF_MAX, "%s", device_name); + snprintf(config_data->res_thermal_name, BUFF_MAX, "%s", thermal_device_name); + snprintf(config_data->path_conf_file, BUFF_MAX, "%s", device_config_path); + snprintf(config_data->path_load_table, BUFF_MAX, "%s", cpu_load_path); + config_data->num_cpus = number_of_cpus; + config_data->cpu = first_cpu; + return 0; } /** * @brief Parse pass.conf for all h/w resources to get list of supported * h/w resources - * @param [in] result Parsed raw data from configuration - * @param [in] user_data Instance of h/w resource + * @param [in] pass Instance of struct pass + * @param [in] obj Instance of json_object for h/w resource * @return @c 0 on success, otherwise error value */ -static int parse_resource(struct parse_result *result, void *user_data) +static int parse_resource(struct pass *pass, json_object *obj) { - static char path[BUFF_MAX]; - static bool is_compatible = false; - static char compatible[BUFF_MAX]; - struct pass *pass = user_data; - char section_name[BUFF_MAX]; - int id, len, ret; - - if (!result) - return 0; + json_object *device_list = NULL; + const char *board_name = NULL; + const char *board_name_path = NULL; + int num_resources = 0, ret, i; + + /* Get property values */ + /* - mandatory properties */ + board_name = get_string_from_object(obj, "board_name"); + board_name_path = get_string_from_object(obj, "board_name_path"); + if (json_object_object_get_ex(obj, "device_list", &device_list)) + num_resources = json_object_array_length(device_list); + + /* Check the mandatory property values are valid or not */ + if (!board_name || !board_name_path) { + _E("Failed to get 'board_name' property\n"); + return -EINVAL; + } else if (!device_list) { + _E("Failed to get 'device_list' property\n"); + return -EINVAL; + } else if (num_resources <= 0) { + _E("Must need to add at least one resource in 'device_list' section\n"); + return -EINVAL; + } - if (!result->section || !result->name || !result->value) - return 0; + ret = compare_compatible_name(board_name, board_name_path); + if (ret < 0) { + _E("Cannot match 'board_name' from 'board_name_path'\n"); + return -EINVAL; + } - /* Parsing 'PassResource' section */ - if (MATCH(result->section, "PassResource")) { - if (MATCH(result->name, "pass_compatible")) { - len = strlen(result->value); - snprintf(compatible, len + 1, "%s", result->value); - - len = strlen(path); - if (len > 0) { - ret = compare_compatible_name(compatible, path); - if (ret < 0) - return ret; - - is_compatible = true; - } - } else if (MATCH(result->name, "pass_path_compatible")) { - len = strlen(result->value); - snprintf(path, len + 1, "%s", result->value); - - len = strlen(compatible); - if (len > 0) { - ret = compare_compatible_name(compatible, path); - if (ret < 0) - return ret; - - is_compatible = true; - } - } else if (MATCH(result->name, "pass_num_resources")) { - unsigned int num_resources; - int i, ret; - - ret = sys_strtol(result->value); - if (ret < 0) - return ret; - num_resources = ret; - - if ((num_resources > MAX_NUM) || - (num_resources < 1)) { - _E("cannot parse %s\n", result->name); - return -EINVAL; - } - - pass->res = calloc(num_resources, - sizeof(struct pass_resource)); - if (!pass->res) { - _E("cannot allocate the memory for resource"); - return -ENOMEM; - } - - pass->num_resources = num_resources; - - /* Set init. value of initdata for each h/w resource */ - for (i = 0; i < num_resources ; i++) { - struct pass_resource *cur; - - cur = &pass->res[i]; - - cur->init_data.dvfs.governor = NULL; - cur->init_data.dvfs.min_freq = -1; - cur->init_data.dvfs.max_freq = -1; - cur->init_data.dvfs.up_threshold = -1; - - cur->init_data.hotplug.online_state = NULL; - cur->init_data.hotplug.online_min_num = -1; - cur->init_data.hotplug.online_max_num = -1; - - cur->init_data.memory.fault_around_bytes = -1; - } - } else { - _E("cannot parse the number of resource\n"); - return -ENOENT; - } + /* Initialize config_data from property values of confiugartion file */ + pass->res = calloc(num_resources, sizeof(struct pass_resource)); + if (!pass->res) { + _E("Cannot allocate the memory for resources"); + return -ENOMEM; } + pass->num_resources = num_resources; + + for (i = 0; i < num_resources ; i++) { + struct pass_resource *cur; + json_object *resource_obj = + json_object_array_get_idx(device_list, i); + + cur = &pass->res[i]; + + cur->init_data.dvfs.governor = NULL; + cur->init_data.dvfs.min_freq = -1; + cur->init_data.dvfs.max_freq = -1; + cur->init_data.dvfs.up_threshold = -1; - /* Parsing 'PassResource[X]' section */ - for (id = 0; id < pass->num_resources; id++) { - ret = snprintf(section_name, BUFF_MAX, "PassResource%d", id); - - if (MATCH(section_name, result->section)) { - if (!is_compatible) { - _E("cannot match [compatible] with the string read from [path]\n"); - return -EINVAL; - } - ret = parse_resource_data(result, pass, id); - if (ret < 0) { - _E("cannot parse 'PassResource%d' section\n", - id); - return ret; - } + cur->init_data.hotplug.online_state = NULL; + cur->init_data.hotplug.online_min_num = -1; + cur->init_data.hotplug.online_max_num = -1; + + cur->init_data.memory.fault_around_bytes = -1; + + ret = parse_resource_data(pass, i, resource_obj); + if (ret < 0) { + _E("cannot parse of %dth resource in 'device_list' section\n", i); + ret = -EINVAL; + goto err; } } return 0; + +err: + pass->num_resources = 0; + free(pass->res); + + return ret; } /** @@ -961,7 +831,23 @@ static int parse_resource(struct parse_result *result, void *user_data) */ int pass_parser_get_resource_config(struct pass *pass, char *path) { - return config_parse(path, parse_resource, pass); + int ret; + json_object *obj = NULL; + + obj = json_object_from_file(path); + if (!obj) { + _E("Failed to get json_object from %s (%s)\n", + path, json_util_get_last_err()); + return -EINVAL; + } + + ret = parse_resource(pass, obj); + if (ret < 0) + _E("Failed to parse resource from %s\n", path); + + json_object_put(obj); + + return ret; } /** @@ -988,6 +874,7 @@ int pass_parser_get_each_resource_config(struct pass_resource *res, char *path) struct pass_pmqos *pmqos; struct pass_thermal *thermal; int ret, i; + json_object *obj = NULL; if (!res) return -EINVAL; @@ -1021,13 +908,20 @@ int pass_parser_get_each_resource_config(struct pass_resource *res, char *path) /* Initialize the Thermal's data */ thermal->state = PASS_UNUSED; - /* Parse pass_level */ - ret = config_parse(path, parse_each_resource, res); - if (ret < 0) { - _E("cannot parse %s\n", path); + /* Parse configuration */ + obj = json_object_from_file(path); + if (!obj) { + _E("Failed to get json_object from %s (%s)\n", + path, json_util_get_last_err()); return -EINVAL; } + ret = parse_each_resource(res, obj); + if (ret < 0) { + _E("Failed to parse %s\n", path); + goto out; + } + /* Verify the parsed pass_level */ for (i = 0; i < res->config_data.num_levels; i++) ret |= verify_level(res->config_data.res_type, @@ -1036,7 +930,7 @@ int pass_parser_get_each_resource_config(struct pass_resource *res, char *path) if (ret < 0) { _E("failed to verify Level of '%s' resource\n", res->config_data.res_name); - return -EINVAL; + goto out; } /* Verify the parsed scenario pass_level */ @@ -1047,18 +941,23 @@ int pass_parser_get_each_resource_config(struct pass_resource *res, char *path) if (ret < 0) { _E("failed to verify ScenarioLevel of '%s' resource\n", res->config_data.res_name); - return -EINVAL; + goto out; } - if (res->config_data.state == PASS_UNUSED) - return -EINVAL; + if (res->config_data.state == PASS_UNUSED) { + ret = -EINVAL; + goto out; + } if (pmqos->state == PASS_UNUSED) _W("don't include the list of pass-scenario\n"); else if (pmqos->state == PASS_OFF) _I("cannot use pass-scenario"); - return 0; +out: + json_object_put(obj); + + return ret; } /** diff --git a/src/pass/pass-pmqos.c b/src/pass/pass-pmqos.c index 8ac9187..484377f 100644 --- a/src/pass/pass-pmqos.c +++ b/src/pass/pass-pmqos.c @@ -33,7 +33,6 @@ #include #include -#include #include "pass.h" #include "pass-rescon.h" @@ -60,7 +59,7 @@ static int find_scenario_index(struct pass_pmqos *pmqos, char *name) int index; for (index = 0; index < pmqos->num_scenarios; index++) - if (MATCH(pmqos->scenarios[index].name, name)) + if (!strncmp(pmqos->scenarios[index].name, name, strlen(name))) return index; return -EINVAL; diff --git a/src/pass/pass.c b/src/pass/pass.c index ae9592f..a92513f 100644 --- a/src/pass/pass.c +++ b/src/pass/pass.c @@ -42,7 +42,7 @@ #include "pass-parser.h" #include "pass-hal.h" -#define PASS_CONF_PATH "/hal/etc/pass/pass.conf" +#define PASS_JSON_PATH "/hal/etc/pass/pass.json" /** * @brief Specify the supported modules according to the type of h/w @@ -205,7 +205,8 @@ static int pass_init_resource(struct pass_resource *res) int i; /* Get configuration of each resource from pass-resource*.conf */ - ret = pass_parser_get_each_resource_config(res, res->config_data.path_conf_file); + ret = pass_parser_get_each_resource_config(res, + res->config_data.path_conf_file); if (ret < 0) { _E("cannot parse %s\n", res->config_data.path_conf_file); return -1; @@ -361,9 +362,9 @@ static int pass_init_done(void *data, void *user_data) int i, ret; /* Get configuration of resource list from pass.conf */ - ret = pass_parser_get_resource_config(&g_pass, PASS_CONF_PATH); + ret = pass_parser_get_resource_config(&g_pass, PASS_JSON_PATH); if (ret < 0) { - _E("cannot parse %s\n", PASS_CONF_PATH); + _E("cannot parse %s\n", PASS_JSON_PATH); return ret; } diff --git a/unittest/CMakeLists.txt b/unittest/CMakeLists.txt index 12a56db..b940c73 100644 --- a/unittest/CMakeLists.txt +++ b/unittest/CMakeLists.txt @@ -3,7 +3,6 @@ PROJECT(pass C CXX) SET(SRCS ${CMAKE_SOURCE_DIR}/src/pass/pass-hal.c ${CMAKE_SOURCE_DIR}/src/pass/pass-parser.c ${CMAKE_SOURCE_DIR}/src/core/common.c - ${CMAKE_SOURCE_DIR}/src/core/config-parser.c ) INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}) diff --git a/unittest/power-haltests.cpp b/unittest/power-haltests.cpp index 8e475e5..0e0e828 100644 --- a/unittest/power-haltests.cpp +++ b/unittest/power-haltests.cpp @@ -107,14 +107,14 @@ TEST_F(PowerHaltest, GetResourceConfig_HandlesValidInput) { int ret = 0; unsigned int i; - char path[] = "/hal/etc/pass/pass.conf"; + char path_json[] = "/hal/etc/pass/pass.json"; /* Stop PASS daemon before HAL testing */ ret = pass_test_method_call(DBUS_CORE_PATH, DBUS_CORE_INTERFACE, "stop", NULL); ASSERT_EQ(ret, 0) << "PassServiceStop Failed"; - ret = pass_parser_get_resource_config(&g_pass, path); + ret = pass_parser_get_resource_config(&g_pass, path_json); ASSERT_EQ(ret, 0) << "GetResourceConfig Failed"; for (i = 0; i < g_pass.num_resources; i++) { -- 2.7.4 From 288c9853eb692d61623ce5552129309654fb2baf Mon Sep 17 00:00:00 2001 From: Chanwoo Choi Date: Mon, 2 Aug 2021 19:09:40 +0900 Subject: [PATCH 16/16] pass: rescon: Fix wrong initial value to distinguish either property is added or not The commit d54cf9cc4588 ("pass: rescon: Add support for multiple scenario pass_level") has defined the MIN_INT (zeor) to inialize the property values in struct pass_level. But, some property values will have the zero value like cooling_device_state is zero. In that case, if MIN_INT is zero, cannot separate the following two cases: - propery is absence in configuration file -> 0 - property value is zero in configuration file -> 0 In order to separate the above two cases, change the MIN_INT value from 0 to -1. After changes, can separate the two cases as following: - propery is absence in configuration file -> -1 - property value is zero in configuration file -> 0 Change-Id: I2ee3fe9372c2deb82018949fc2b4b85eb3bb96ff Signed-off-by: Chanwoo Choi --- src/pass/pass-rescon.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pass/pass-rescon.c b/src/pass/pass-rescon.c index 79d3a1a..0d96475 100644 --- a/src/pass/pass-rescon.c +++ b/src/pass/pass-rescon.c @@ -34,7 +34,7 @@ #include "pass-hal.h" #define MAX_INT 1000000000 -#define MIN_INT 0 +#define MIN_INT -1 #define MIN_FAULT_AROUND_BYTES 4096 #define MAX_FAULT_AROUND_BYTES 65536 -- 2.7.4