Loading arch/arm64/configs/vendor/holi_QGKI.config +3 −0 Original line number Diff line number Diff line Loading @@ -179,6 +179,9 @@ CONFIG_QTI_HW_MEMLAT_SCMI_CLIENT=y CONFIG_SRAM=y CONFIG_QTI_HW_MEMLAT_LOG=y CONFIG_MSM_PERFORMANCE=y CONFIG_QTI_SCMI_PLH_PROTOCOL=y CONFIG_QTI_PLH=y CONFIG_QTI_PLH_SCMI_CLIENT=y # CONFIG_USB_CONFIGFS_RNDIS is not set CONFIG_QCOM_INITIAL_LOGBUF=y CONFIG_QCOM_MINIDUMP_FTRACE=y Loading drivers/soc/qcom/Kconfig +10 −0 Original line number Diff line number Diff line Loading @@ -600,6 +600,16 @@ config MSM_PERFORMANCE fmin and fmax. The user space can request the cpu freq change by writing cpu#:freq values config QTI_PLH bool "Qualcomm Technologies Inc. RIMPS PLH interface" depends on ARM_SCMI_PROTOCOL && MSM_PERFORMANCE default n help Interface between RIMPS PLH and userspace. This interface is responsible for handling the communication with RIMPS PLH such as passing tunables, enable and disable. config QMP_DEBUGFS_CLIENT bool "Debugfs Client to communicate with AOP using QMP protocol" depends on DEBUG_FS Loading drivers/soc/qcom/msm_performance.c +164 −10 Original line number Diff line number Diff line Loading @@ -25,6 +25,7 @@ #include <linux/perf_event.h> #include <linux/errno.h> #include <linux/topology.h> #include <linux/scmi_protocol.h> /* * Sched will provide the data for every 20ms window, Loading Loading @@ -926,20 +927,162 @@ static const struct kernel_param_ops param_ops_game_start_pid = { module_param_cb(evnt_gplaf_pid, ¶m_ops_game_start_pid, NULL, 0644); /*******************************GFX Call************************************/ #ifdef CONFIG_QTI_PLH static struct scmi_handle *plh_handle; void rimps_plh_init(struct scmi_handle *handle) { if (handle) plh_handle = handle; } EXPORT_SYMBOL(rimps_plh_init); static int splh_notif, splh_init_done, plh_log_level; #define PLH_MIN_LOG_LEVEL 0 #define PLH_MAX_LOG_LEVEL 0xF #define SPLH_FPS_MAX_CNT 8 #define SPLH_IPC_FREQ_VTBL_MAX_CNT 5 /* ipc freq pair */ #define SPLH_INIT_IPC_FREQ_TBL_PARAMS \ (2 + SPLH_FPS_MAX_CNT * (1 + (2 * SPLH_IPC_FREQ_VTBL_MAX_CNT))) static int set_plh_log_level(const char *buf, const struct kernel_param *kp) { int ret, log_val_backup; struct scmi_plh_vendor_ops *ops; if (!plh_handle || !plh_handle->plh_ops) { pr_err("msm_perf: plh scmi handle or vendor ops null\n"); return -EINVAL; } ops = plh_handle->plh_ops; log_val_backup = plh_log_level; ret = param_set_int(buf, kp); /* Updates plh_log_level */ if (ret < 0) { pr_err("msm_perf: getting new plh_log_level failed, ret=%d\n", ret); return ret; } plh_log_level = clamp(plh_log_level, PLH_MIN_LOG_LEVEL, PLH_MAX_LOG_LEVEL); ret = ops->set_plh_log_level(plh_handle, plh_log_level); if (ret < 0) { plh_log_level = log_val_backup; pr_err("msm_perf: setting new plh_log_level failed, ret=%d\n", ret); return ret; } return 0; } static const struct kernel_param_ops param_ops_plh_log_level = { .set = set_plh_log_level, .get = param_get_int, }; module_param_cb(plh_log_level, ¶m_ops_plh_log_level, &plh_log_level, 0644); static int splh_notif; static void init_splh_notif(const char *buf) static int init_splh_notif(const char *buf) { int i, j, ret; u16 tmp[SPLH_INIT_IPC_FREQ_TBL_PARAMS]; u16 *ptmp = tmp, ntokens, nfps, n_ipc_freq_pair, tmp_valid_len = 0; const char *cp, *cp1; struct scmi_plh_vendor_ops *ops; /* buf contains the init info from user */ if (buf == NULL) return; if (buf == NULL || !plh_handle || !plh_handle->plh_ops) return -EINVAL; cp = buf; ntokens = 0; while ((cp = strpbrk(cp + 1, ":"))) ntokens++; /* format of cmd nfps, n_ipc_freq_pair, <fps0, <ipc0, freq0>,...>,... */ cp = buf; if (sscanf(cp, INIT ":%hu", &nfps)) { if ((nfps != ntokens-1) || (nfps == 0) || (nfps > SPLH_FPS_MAX_CNT)) return -EINVAL; cp = strnchr(cp, strlen(cp), ':'); /* skip INIT */ cp++; cp = strnchr(cp, strlen(cp), ':'); /* skip nfps */ *ptmp++ = nfps; /* nfps is first cmd param */ tmp_valid_len++; cp1 = cp; ntokens = 0; /* get count of nfps * n_ipc_freq_pair * <ipc freq pair values> */ while ((cp1 = strpbrk(cp1 + 1, ","))) ntokens++; if (ntokens % (2 * nfps)) /* ipc freq pair values should be multiple of nfps */ return -EINVAL; n_ipc_freq_pair = ntokens / (2 * nfps); /* ipc_freq pair values for each FPS */ if ((n_ipc_freq_pair == 0) || (n_ipc_freq_pair > SPLH_IPC_FREQ_VTBL_MAX_CNT)) return -EINVAL; *ptmp++ = n_ipc_freq_pair; /* n_ipc_freq_pair is second cmd param */ tmp_valid_len++; cp1 = cp; for (i = 0; i < nfps; i++) { if (sscanf(cp1, ":%hu", ptmp) != 1) return -EINVAL; ptmp++; /* increment after storing FPS val */ tmp_valid_len++; cp1 = strnchr(cp1, strlen(cp1), ','); /* move to ,ipc */ for (j = 0; j < 2 * n_ipc_freq_pair; j++) { if (sscanf(cp1, ",%hu", ptmp) != 1) return -EINVAL; ptmp++; /* increment after storing ipc or freq */ tmp_valid_len++; cp1++; if (j != (2 * n_ipc_freq_pair - 1)) cp1 = strnchr(cp1, strlen(cp1), ','); /* move to next */ } if (i != (nfps - 1)) cp1 = strnchr(cp1, strlen(cp1), ':'); /* move to next FPS val */ pr_debug("msm_perf:Init info for scroll :: %s\n", buf); } } else { return -EINVAL; } ops = plh_handle->plh_ops; ret = ops->init_splh_ipc_freq_tbl(plh_handle, tmp, tmp_valid_len); if (ret < 0) return -EINVAL; pr_info("msm_perf: nfps=%hu n_ipc_freq_pair=%hu last_freq_val=%hu len=%hu\n", nfps, n_ipc_freq_pair, *--ptmp, tmp_valid_len); splh_init_done = 1; return 0; } static void activate_splh_notif(void) { int ret; struct scmi_plh_vendor_ops *ops; /* received event notification here */ if (!plh_handle || !plh_handle->plh_ops) { pr_err("msm_perf: splh not supported\n"); return; } ops = plh_handle->plh_ops; if (splh_notif) ret = ops->start_splh(plh_handle, splh_notif); /* splh_notif is fps */ else ret = ops->stop_splh(plh_handle); if (ret < 0) { pr_err("msm_perf: splh start or stop failed, ret=%d\n", ret); return; } } static int set_splh_notif(const char *buf, const struct kernel_param *kp) Loading @@ -947,8 +1090,17 @@ static int set_splh_notif(const char *buf, const struct kernel_param *kp) int ret; if (strnstr(buf, INIT, sizeof(INIT)) != NULL) { init_splh_notif(buf); return 0; splh_init_done = 0; ret = init_splh_notif(buf); if (ret < 0) pr_err("msm_perf: splh ipc freq tbl init failed, ret=%d\n", ret); return ret; } if (!splh_init_done) { pr_err("msm_perf: splh ipc freq tbl not initialized\n"); return -EINVAL; } ret = param_set_int(buf, kp); Loading @@ -957,7 +1109,7 @@ static int set_splh_notif(const char *buf, const struct kernel_param *kp) activate_splh_notif(); return ret; return 0; } static const struct kernel_param_ops param_ops_splh_notification = { Loading @@ -965,6 +1117,8 @@ static const struct kernel_param_ops param_ops_splh_notification = { .get = param_get_int, }; module_param_cb(splh_notif, ¶m_ops_splh_notification, &splh_notif, 0644); #endif /* CONFIG_QTI_PLH */ static int __init msm_performance_init(void) { Loading Loading
arch/arm64/configs/vendor/holi_QGKI.config +3 −0 Original line number Diff line number Diff line Loading @@ -179,6 +179,9 @@ CONFIG_QTI_HW_MEMLAT_SCMI_CLIENT=y CONFIG_SRAM=y CONFIG_QTI_HW_MEMLAT_LOG=y CONFIG_MSM_PERFORMANCE=y CONFIG_QTI_SCMI_PLH_PROTOCOL=y CONFIG_QTI_PLH=y CONFIG_QTI_PLH_SCMI_CLIENT=y # CONFIG_USB_CONFIGFS_RNDIS is not set CONFIG_QCOM_INITIAL_LOGBUF=y CONFIG_QCOM_MINIDUMP_FTRACE=y Loading
drivers/soc/qcom/Kconfig +10 −0 Original line number Diff line number Diff line Loading @@ -600,6 +600,16 @@ config MSM_PERFORMANCE fmin and fmax. The user space can request the cpu freq change by writing cpu#:freq values config QTI_PLH bool "Qualcomm Technologies Inc. RIMPS PLH interface" depends on ARM_SCMI_PROTOCOL && MSM_PERFORMANCE default n help Interface between RIMPS PLH and userspace. This interface is responsible for handling the communication with RIMPS PLH such as passing tunables, enable and disable. config QMP_DEBUGFS_CLIENT bool "Debugfs Client to communicate with AOP using QMP protocol" depends on DEBUG_FS Loading
drivers/soc/qcom/msm_performance.c +164 −10 Original line number Diff line number Diff line Loading @@ -25,6 +25,7 @@ #include <linux/perf_event.h> #include <linux/errno.h> #include <linux/topology.h> #include <linux/scmi_protocol.h> /* * Sched will provide the data for every 20ms window, Loading Loading @@ -926,20 +927,162 @@ static const struct kernel_param_ops param_ops_game_start_pid = { module_param_cb(evnt_gplaf_pid, ¶m_ops_game_start_pid, NULL, 0644); /*******************************GFX Call************************************/ #ifdef CONFIG_QTI_PLH static struct scmi_handle *plh_handle; void rimps_plh_init(struct scmi_handle *handle) { if (handle) plh_handle = handle; } EXPORT_SYMBOL(rimps_plh_init); static int splh_notif, splh_init_done, plh_log_level; #define PLH_MIN_LOG_LEVEL 0 #define PLH_MAX_LOG_LEVEL 0xF #define SPLH_FPS_MAX_CNT 8 #define SPLH_IPC_FREQ_VTBL_MAX_CNT 5 /* ipc freq pair */ #define SPLH_INIT_IPC_FREQ_TBL_PARAMS \ (2 + SPLH_FPS_MAX_CNT * (1 + (2 * SPLH_IPC_FREQ_VTBL_MAX_CNT))) static int set_plh_log_level(const char *buf, const struct kernel_param *kp) { int ret, log_val_backup; struct scmi_plh_vendor_ops *ops; if (!plh_handle || !plh_handle->plh_ops) { pr_err("msm_perf: plh scmi handle or vendor ops null\n"); return -EINVAL; } ops = plh_handle->plh_ops; log_val_backup = plh_log_level; ret = param_set_int(buf, kp); /* Updates plh_log_level */ if (ret < 0) { pr_err("msm_perf: getting new plh_log_level failed, ret=%d\n", ret); return ret; } plh_log_level = clamp(plh_log_level, PLH_MIN_LOG_LEVEL, PLH_MAX_LOG_LEVEL); ret = ops->set_plh_log_level(plh_handle, plh_log_level); if (ret < 0) { plh_log_level = log_val_backup; pr_err("msm_perf: setting new plh_log_level failed, ret=%d\n", ret); return ret; } return 0; } static const struct kernel_param_ops param_ops_plh_log_level = { .set = set_plh_log_level, .get = param_get_int, }; module_param_cb(plh_log_level, ¶m_ops_plh_log_level, &plh_log_level, 0644); static int splh_notif; static void init_splh_notif(const char *buf) static int init_splh_notif(const char *buf) { int i, j, ret; u16 tmp[SPLH_INIT_IPC_FREQ_TBL_PARAMS]; u16 *ptmp = tmp, ntokens, nfps, n_ipc_freq_pair, tmp_valid_len = 0; const char *cp, *cp1; struct scmi_plh_vendor_ops *ops; /* buf contains the init info from user */ if (buf == NULL) return; if (buf == NULL || !plh_handle || !plh_handle->plh_ops) return -EINVAL; cp = buf; ntokens = 0; while ((cp = strpbrk(cp + 1, ":"))) ntokens++; /* format of cmd nfps, n_ipc_freq_pair, <fps0, <ipc0, freq0>,...>,... */ cp = buf; if (sscanf(cp, INIT ":%hu", &nfps)) { if ((nfps != ntokens-1) || (nfps == 0) || (nfps > SPLH_FPS_MAX_CNT)) return -EINVAL; cp = strnchr(cp, strlen(cp), ':'); /* skip INIT */ cp++; cp = strnchr(cp, strlen(cp), ':'); /* skip nfps */ *ptmp++ = nfps; /* nfps is first cmd param */ tmp_valid_len++; cp1 = cp; ntokens = 0; /* get count of nfps * n_ipc_freq_pair * <ipc freq pair values> */ while ((cp1 = strpbrk(cp1 + 1, ","))) ntokens++; if (ntokens % (2 * nfps)) /* ipc freq pair values should be multiple of nfps */ return -EINVAL; n_ipc_freq_pair = ntokens / (2 * nfps); /* ipc_freq pair values for each FPS */ if ((n_ipc_freq_pair == 0) || (n_ipc_freq_pair > SPLH_IPC_FREQ_VTBL_MAX_CNT)) return -EINVAL; *ptmp++ = n_ipc_freq_pair; /* n_ipc_freq_pair is second cmd param */ tmp_valid_len++; cp1 = cp; for (i = 0; i < nfps; i++) { if (sscanf(cp1, ":%hu", ptmp) != 1) return -EINVAL; ptmp++; /* increment after storing FPS val */ tmp_valid_len++; cp1 = strnchr(cp1, strlen(cp1), ','); /* move to ,ipc */ for (j = 0; j < 2 * n_ipc_freq_pair; j++) { if (sscanf(cp1, ",%hu", ptmp) != 1) return -EINVAL; ptmp++; /* increment after storing ipc or freq */ tmp_valid_len++; cp1++; if (j != (2 * n_ipc_freq_pair - 1)) cp1 = strnchr(cp1, strlen(cp1), ','); /* move to next */ } if (i != (nfps - 1)) cp1 = strnchr(cp1, strlen(cp1), ':'); /* move to next FPS val */ pr_debug("msm_perf:Init info for scroll :: %s\n", buf); } } else { return -EINVAL; } ops = plh_handle->plh_ops; ret = ops->init_splh_ipc_freq_tbl(plh_handle, tmp, tmp_valid_len); if (ret < 0) return -EINVAL; pr_info("msm_perf: nfps=%hu n_ipc_freq_pair=%hu last_freq_val=%hu len=%hu\n", nfps, n_ipc_freq_pair, *--ptmp, tmp_valid_len); splh_init_done = 1; return 0; } static void activate_splh_notif(void) { int ret; struct scmi_plh_vendor_ops *ops; /* received event notification here */ if (!plh_handle || !plh_handle->plh_ops) { pr_err("msm_perf: splh not supported\n"); return; } ops = plh_handle->plh_ops; if (splh_notif) ret = ops->start_splh(plh_handle, splh_notif); /* splh_notif is fps */ else ret = ops->stop_splh(plh_handle); if (ret < 0) { pr_err("msm_perf: splh start or stop failed, ret=%d\n", ret); return; } } static int set_splh_notif(const char *buf, const struct kernel_param *kp) Loading @@ -947,8 +1090,17 @@ static int set_splh_notif(const char *buf, const struct kernel_param *kp) int ret; if (strnstr(buf, INIT, sizeof(INIT)) != NULL) { init_splh_notif(buf); return 0; splh_init_done = 0; ret = init_splh_notif(buf); if (ret < 0) pr_err("msm_perf: splh ipc freq tbl init failed, ret=%d\n", ret); return ret; } if (!splh_init_done) { pr_err("msm_perf: splh ipc freq tbl not initialized\n"); return -EINVAL; } ret = param_set_int(buf, kp); Loading @@ -957,7 +1109,7 @@ static int set_splh_notif(const char *buf, const struct kernel_param *kp) activate_splh_notif(); return ret; return 0; } static const struct kernel_param_ops param_ops_splh_notification = { Loading @@ -965,6 +1117,8 @@ static const struct kernel_param_ops param_ops_splh_notification = { .get = param_get_int, }; module_param_cb(splh_notif, ¶m_ops_splh_notification, &splh_notif, 0644); #endif /* CONFIG_QTI_PLH */ static int __init msm_performance_init(void) { Loading