msm_perf: Enable drag plh algo on firmware

Added scmi transaction for working of dplh algorithm
on firmware. Added few sysfs node to notify about start/stop
of drag and pass init data.

Change-Id: I150f6a4e1d13c09f84d415d9ef58a55e0d45a73e
Signed-off-by: Varun Garg <quic_gargv@quicinc.com>
This commit is contained in:
Varun Garg 2022-02-25 02:41:50 -08:00 committed by Gerrit - the friendly Code Review server
parent 568f709f2d
commit d60f8503a8
3 changed files with 151 additions and 13 deletions

View File

@ -12,6 +12,8 @@
#define SCMI_VENDOR_MSG_SPLH_END (31)
#define SCMI_VENDOR_MSG_LPLH_START (32) /* Each PLH module to use MAX 16 MSG */
#define SCMI_VENDOR_MSG_LPLH_END (47)
#define SCMI_VENDOR_MSG_DPLH_START (48) /* Each PLH module to use MAX 16 MSG */
#define SCMI_VENDOR_MSG_DPLH_END (53)
enum scmi_plh_protocol_cmd {
PERF_LOCK_SCROLL_INIT_IPC_FREQ_TBL_MSG_ID = SCMI_VENDOR_MSG_SPLH_START,
@ -26,6 +28,11 @@ enum scmi_plh_protocol_cmd {
PERF_LOCK_LAUNCH_SET_SAMPLE_MS,
PERF_LOCK_LAUNCH_SET_LOG_LEVEL,
PERF_LOCK_LAUNCH_MAX_MSG_ID = SCMI_VENDOR_MSG_LPLH_END,
PERF_LOCK_DRAG_INIT_IPC_FREQ_TBL_MSG_ID = SCMI_VENDOR_MSG_DPLH_START,
PERF_LOCK_DRAG_START_MSG_ID,
PERF_LOCK_DRAG_STOP_MSG_ID,
PERF_LOCK_DRAG_SET_LOG_LEVEL,
PERF_LOCK_DRAG_MAX_MSG_ID = SCMI_VENDOR_MSG_DPLH_END,
};
@ -50,6 +57,9 @@ static int scmi_plh_init_ipc_freq_tbl(const struct scmi_protocol_handle *ph,
else if (feature == PERF_LOCK_LAUNCH)
ret = ph->xops->xfer_get_init(ph, PERF_LOCK_LAUNCH_INIT_IPC_FREQ_TBL_MSG_ID,
(msg_size), sizeof(uint32_t), &t);
else if (feature == PERF_LOCK_DRAG)
ret = ph->xops->xfer_get_init(ph, PERF_LOCK_DRAG_INIT_IPC_FREQ_TBL_MSG_ID,
(msg_size), sizeof(uint32_t), &t);
else
return -EINVAL;
@ -100,6 +110,8 @@ static int scmi_plh_start_cmd(const struct scmi_protocol_handle *ph,
ret = scmi_plh_set_u16_val(ph, value, PERF_LOCK_SCROLL_START_MSG_ID);
else if (feature == PERF_LOCK_LAUNCH)
ret = scmi_plh_set_u16_val(ph, value, PERF_LOCK_LAUNCH_START_MSG_ID);
else if (feature == PERF_LOCK_DRAG)
ret = scmi_plh_set_u16_val(ph, value, PERF_LOCK_DRAG_START_MSG_ID);
else
ret = -EINVAL;
@ -114,6 +126,8 @@ static int scmi_plh_stop_cmd(const struct scmi_protocol_handle *ph, enum plh_fea
ret = scmi_plh_set_u16_val(ph, 0, PERF_LOCK_SCROLL_STOP_MSG_ID);
else if (feature == PERF_LOCK_LAUNCH)
ret = scmi_plh_set_u16_val(ph, 0, PERF_LOCK_LAUNCH_STOP_MSG_ID);
else if (feature == PERF_LOCK_DRAG)
ret = scmi_plh_set_u16_val(ph, 0, PERF_LOCK_DRAG_STOP_MSG_ID);
else
ret = -EINVAL;
@ -144,6 +158,8 @@ static int scmi_plh_set_log_level(const struct scmi_protocol_handle *ph,
ret = scmi_plh_set_u16_val(ph, log_level, PERF_LOCK_SCROLL_SET_LOG_LEVEL);
else if (feature == PERF_LOCK_LAUNCH)
ret = scmi_plh_set_u16_val(ph, log_level, PERF_LOCK_LAUNCH_SET_LOG_LEVEL);
else if (feature == PERF_LOCK_DRAG)
ret = scmi_plh_set_u16_val(ph, log_level, PERF_LOCK_DRAG_SET_LOG_LEVEL);
else
ret = -EINVAL;

View File

@ -145,6 +145,16 @@ static ssize_t get_gplaf_health(struct kobject *kobj,
static ssize_t set_gplaf_health(struct kobject *kobj,
struct kobj_attribute *attr, const char *buf,
size_t count);
static ssize_t get_dplh_notif(struct kobject *kobj,
struct kobj_attribute *attr, char *buf);
static ssize_t set_dplh_notif(struct kobject *kobj,
struct kobj_attribute *attr, const char *buf,
size_t count);
static ssize_t get_dplh_log_level(struct kobject *kobj,
struct kobj_attribute *attr, char *buf);
static ssize_t set_dplh_log_level(struct kobject *kobj,
struct kobj_attribute *attr, const char *buf,
size_t count);
static struct kobj_attribute cpu_min_freq_attr =
@ -178,6 +188,10 @@ static struct kobj_attribute gplaf_log_level_attr =
__ATTR(gplaf_log_level, 0644, get_gplaf_log_level, set_gplaf_log_level);
static struct kobj_attribute gplaf_health_attr =
__ATTR(gplaf_health, 0644, get_gplaf_health, set_gplaf_health);
static struct kobj_attribute dplh_notif_attr =
__ATTR(dplh_notif, 0644, get_dplh_notif, set_dplh_notif);
static struct kobj_attribute dplh_log_level_attr =
__ATTR(dplh_log_level, 0644, get_dplh_log_level, set_dplh_log_level);
static struct attribute *param_attrs[] = {
&cpu_min_freq_attr.attr,
@ -195,6 +209,8 @@ static struct attribute *param_attrs[] = {
&gplaf_data_node_attr.attr,
&gplaf_log_level_attr.attr,
&gplaf_health_attr.attr,
&dplh_notif_attr.attr,
&dplh_log_level_attr.attr,
NULL,
};
@ -1336,6 +1352,12 @@ static ssize_t set_gplaf_log_level(struct kobject *kobj,
}
/*******************************GFX Call************************************/
#define PLH_FPS_MAX_CNT 8
#define PLH_IPC_FREQ_VTBL_MAX_CNT 5 /* ipc freq pair */
#define PLH_INIT_IPC_FREQ_TBL_PARAMS \
(2 + PLH_FPS_MAX_CNT * (1 + (2 * PLH_IPC_FREQ_VTBL_MAX_CNT)))
static struct scmi_protocol_handle *plh_handle;
static const struct scmi_plh_vendor_ops *plh_ops;
int cpucp_plh_init(struct scmi_device *sdev)
@ -1354,14 +1376,11 @@ int cpucp_plh_init(struct scmi_device *sdev)
}
EXPORT_SYMBOL(cpucp_plh_init);
static int splh_notif, splh_init_done, splh_sample_ms, splh_log_level;
static int splh_notif, splh_init_done, splh_sample_ms, splh_log_level,
dplh_init_done;
#define SPLH_MIN_SAMPLE_MS 1
#define SPLH_MAX_SAMPLE_MS 30
#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 ssize_t get_splh_sample_ms(struct kobject *kobj,
struct kobj_attribute *attr, char *buf)
@ -1435,10 +1454,10 @@ static ssize_t set_splh_log_level(struct kobject *kobj,
return count;
}
static int init_splh_notif(const char *buf)
static int init_plh_notif(const char *buf, int feature_id)
{
int i, j, ret;
u16 tmp[SPLH_INIT_IPC_FREQ_TBL_PARAMS];
u16 tmp[PLH_INIT_IPC_FREQ_TBL_PARAMS];
u16 *ptmp = tmp, ntokens, nfps, n_ipc_freq_pair, tmp_valid_len = 0;
const char *cp, *cp1;
@ -1454,7 +1473,7 @@ static int init_splh_notif(const char *buf)
/* 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))
if ((nfps != ntokens-1) || (nfps == 0) || (nfps > PLH_FPS_MAX_CNT))
return -EINVAL;
cp = strnchr(cp, strlen(cp), ':'); /* skip INIT */
@ -1475,7 +1494,7 @@ static int init_splh_notif(const char *buf)
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))
if ((n_ipc_freq_pair == 0) || (n_ipc_freq_pair > PLH_IPC_FREQ_VTBL_MAX_CNT))
return -EINVAL;
*ptmp++ = n_ipc_freq_pair; /* n_ipc_freq_pair is second cmd param */
@ -1518,14 +1537,17 @@ static int init_splh_notif(const char *buf)
return -EINVAL;
}
ret = plh_ops->init_plh_ipc_freq_tbl(plh_handle, tmp, tmp_valid_len, PERF_LOCK_SCROLL);
ret = plh_ops->init_plh_ipc_freq_tbl(plh_handle, tmp, tmp_valid_len, feature_id);
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;
if (feature_id == PERF_LOCK_SCROLL)
splh_init_done = 1;
else if (feature_id == PERF_LOCK_DRAG)
dplh_init_done = 1;
return 0;
}
static void activate_splh_notif(void)
@ -1564,7 +1586,7 @@ static ssize_t set_splh_notif(struct kobject *kobj,
if (strnstr(buf, INIT, sizeof(INIT)) != NULL) {
splh_init_done = 0;
ret = init_splh_notif(buf);
ret = init_plh_notif(buf, PERF_LOCK_SCROLL);
if (ret < 0)
pr_err("msm_perf: splh ipc freq tbl init failed, ret=%d\n", ret);
@ -1819,6 +1841,105 @@ static ssize_t set_lplh_notif(struct kobject *kobj,
return count;
}
/*********** dplh(Drag Perf Lock hardening) code start from here ***********/
static int dplh_notif, dplh_log_level;
static ssize_t get_dplh_log_level(struct kobject *kobj,
struct kobj_attribute *attr, char *buf)
{
return scnprintf(buf, PAGE_SIZE, "%d\n", dplh_log_level);
}
static ssize_t set_dplh_log_level(struct kobject *kobj,
struct kobj_attribute *attr, const char *buf,
size_t count)
{
int ret, log_val_backup;
if (!plh_handle || !plh_ops) {
pr_err("msm_perf: plh scmi handle or vendor ops null\n");
return -EINVAL;
}
log_val_backup = dplh_log_level;
ret = sscanf(buf, "%du", &dplh_log_level);
if (ret < 0) {
pr_err("msm_perf: getting new dplh_log_level failed, ret=%d\n", ret);
return ret;
}
dplh_log_level = clamp(dplh_log_level, CPUCP_MIN_LOG_LEVEL, CPUCP_MAX_LOG_LEVEL);
ret = plh_ops->set_plh_log_level(plh_handle, dplh_log_level, PERF_LOCK_DRAG);
if (ret < 0) {
dplh_log_level = log_val_backup;
pr_err("msm_perf: setting new dplh_log_level failed, ret=%d\n", ret);
return ret;
}
return count;
}
static void activate_dplh_notif(void)
{
int ret;
/* received event notification here */
if (!plh_handle || !plh_ops) {
pr_err("msm_perf: dplh not supported\n");
return;
}
if (dplh_notif)
ret = plh_ops->start_plh(plh_handle,
dplh_notif, PERF_LOCK_DRAG); /* dplh_notif is fps */
else
ret = plh_ops->stop_plh(plh_handle, PERF_LOCK_DRAG);
if (ret < 0) {
pr_err("msm_perf: dplh start or stop failed, ret=%d\n", ret);
return;
}
}
static ssize_t get_dplh_notif(struct kobject *kobj,
struct kobj_attribute *attr, char *buf)
{
return scnprintf(buf, PAGE_SIZE, "%d\n", dplh_notif);
}
static ssize_t set_dplh_notif(struct kobject *kobj,
struct kobj_attribute *attr, const char *buf,
size_t count)
{
int ret;
if (strnstr(buf, INIT, sizeof(INIT)) != NULL) {
dplh_init_done = 0;
ret = init_plh_notif(buf, PERF_LOCK_DRAG);
if (ret < 0)
pr_err("msm_perf: dplh ipc freq tbl init failed, ret=%d\n", ret);
return count;
}
if (!dplh_init_done) {
pr_err("msm_perf: dplh ipc freq tbl not initialized\n");
return -EINVAL;
}
ret = sscanf(buf, "%du", &dplh_notif);
if (ret < 0)
return ret;
activate_dplh_notif();
return count;
}
static int __init msm_performance_init(void)
{
unsigned int cpu;

View File

@ -17,7 +17,8 @@
enum plh_features {
PERF_LOCK_SCROLL,
PERF_LOCK_LAUNCH
PERF_LOCK_LAUNCH,
PERF_LOCK_DRAG
};
struct scmi_protocol_handle;