From 69baed9a807363fb480f55b3af7a3ddd467e8133 Mon Sep 17 00:00:00 2001 From: Santosh Mardi Date: Mon, 23 Nov 2020 16:31:13 +0530 Subject: [PATCH 1/3] drivers: soc: qcom: rimps_memlat: update error checks set_event will return NULL if event_id is not valid, the caller is proceeding further without proper check for NULL. Update pmu event setup function to check pevent for NULL. From the RIMPS perspective, pmu counter IDs 0 and 1 correspond to 64bit cycle counter with ID 0 representing low 32 bit and ID 1 representing high 32bit, while the counter IDs from 2 to 7 correspond to remaining PMUs. At the time of storing pmu counter values to RIMPS shared memory, the function store_event_val() stores both low and high 32bit values of cycle counter when ID 0 is passed as argument to pmu index, hence no need to handle ID 1 separately. Update logic accordingly to drop check for ID 1. Change-Id: Idd345c825572710753f18306f565043347921216 Signed-off-by: Santosh Mardi --- drivers/soc/qcom/rimps_memlat.c | 26 +++++++++++++++++--------- 1 file changed, 17 insertions(+), 9 deletions(-) diff --git a/drivers/soc/qcom/rimps_memlat.c b/drivers/soc/qcom/rimps_memlat.c index 8cc14f4df437..957825e959ad 100644 --- a/drivers/soc/qcom/rimps_memlat.c +++ b/drivers/soc/qcom/rimps_memlat.c @@ -481,10 +481,14 @@ static struct perf_event *set_event(int event_id, unsigned int cpu, static int setup_common_pmu_events(struct memlat_cpu_grp *cpu_grp, cpumask_t *mask, bool cpu_online) { - struct perf_event_attr *attr = alloc_attr(); + struct perf_event_attr *attr; struct perf_event *pevent; unsigned int cpu; + attr = alloc_attr(); + if (!attr) + return -ENODEV; + for_each_cpu(cpu, mask) { struct pmu_map *pmu = to_common_pmu_map(cpu_grp, cpu); struct cpu_data *cpus_data = to_cpu_data(cpu_grp, cpu); @@ -494,7 +498,7 @@ static int setup_common_pmu_events(struct memlat_cpu_grp *cpu_grp, pevent = set_event(cpu_grp->common_ev_ids[INST_IDX], cpu, attr); - if (IS_ERR(pevent)) + if (!pevent || IS_ERR(pevent)) return -ENODEV; cpus_data->common_evs[INST_IDX] = pevent; @@ -502,7 +506,7 @@ static int setup_common_pmu_events(struct memlat_cpu_grp *cpu_grp, pmu[INST_IDX].hw_cntr_idx = pevent->hw.idx + 1; pevent = set_event(cpu_grp->common_ev_ids[CYC_IDX], cpu, attr); - if (IS_ERR(pevent)) { + if (!pevent || IS_ERR(pevent)) { perf_event_release_kernel( cpus_data->common_evs[INST_IDX]); return -ENODEV; @@ -514,7 +518,7 @@ static int setup_common_pmu_events(struct memlat_cpu_grp *cpu_grp, if (cpu_grp->common_ev_ids[STALL_IDX] != INVALID_PMU_EVENT_ID) { pevent = set_event(cpu_grp->common_ev_ids[STALL_IDX], cpu, attr); - if (IS_ERR(pevent)) { + if (!pevent || IS_ERR(pevent)) { perf_event_release_kernel( cpus_data->common_evs[INST_IDX]); perf_event_release_kernel( @@ -536,10 +540,14 @@ static int setup_common_pmu_events(struct memlat_cpu_grp *cpu_grp, static int setup_mon_pmu_events(struct memlat_mon *mon, cpumask_t *mask, bool cpu_online) { - struct perf_event_attr *attr = alloc_attr(); + struct perf_event_attr *attr; struct perf_event *pevent; unsigned int cpu; + attr = alloc_attr(); + if (!attr) + return -ENODEV; + for_each_cpu(cpu, mask) { struct pmu_map *pmu = to_mon_pmu_map(mon, cpu); struct mon_data *ev_data = to_mon_ev_data(mon, cpu); @@ -548,7 +556,7 @@ static int setup_mon_pmu_events(struct memlat_mon *mon, continue; pevent = set_event(mon->mon_ev_ids[MISS_IDX], cpu, attr); - if (IS_ERR(pevent)) + if (!pevent || IS_ERR(pevent)) return -ENODEV; ev_data->mon_evs[MISS_IDX] = pevent; @@ -558,7 +566,7 @@ static int setup_mon_pmu_events(struct memlat_mon *mon, if (mon->mon_ev_ids[L2WB_IDX] != INVALID_PMU_EVENT_ID) { pevent = set_event(mon->mon_ev_ids[L2WB_IDX], cpu, attr); - if (IS_ERR(pevent)) { + if (!pevent || IS_ERR(pevent)) { perf_event_release_kernel( ev_data->mon_evs[MISS_IDX]); return -ENODEV; @@ -576,7 +584,7 @@ static int setup_mon_pmu_events(struct memlat_mon *mon, pevent = set_event(mon->mon_ev_ids[L3_ACCESS_IDX], cpu, attr); - if (IS_ERR(pevent)) { + if (!pevent || IS_ERR(pevent)) { perf_event_release_kernel( ev_data->mon_evs[MISS_IDX]); if (ev_data->mon_evs[L2WB_IDX]) @@ -605,7 +613,7 @@ static inline void store_event_val(u64 val, u8 idx, u8 cpu) if (idx == 0) { writel_relaxed((val & (0xFFFFFFFF)), &base->ccntr_lo); writel_relaxed(((val >> 32) & (0xFFFFFFFF)), &base->ccntr_hi); - } else if (idx < MAX_PMU_CNTRS_RIMPS) { + } else if ((idx > 1) && (idx < MAX_PMU_CNTRS_RIMPS)) { writel_relaxed((val & (0xFFFFFFFF)), &base->evcntr[idx - 2]); } } From 3e84ab94dd5fd46417eab4b41775acc8cca133d9 Mon Sep 17 00:00:00 2001 From: Santosh Mardi Date: Mon, 23 Nov 2020 20:18:56 +0530 Subject: [PATCH 2/3] drivers: soc: qcom: rimps_log: remove unused character while printing Discard character printing in ipc log buf when get_next_logbuf() returns count value less than the size argument. Change-Id: I0ba388400c76c16da423a2ccb67d961ed31e87b4 Signed-off-by: Santosh Mardi --- drivers/soc/qcom/rimps_log.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/soc/qcom/rimps_log.c b/drivers/soc/qcom/rimps_log.c index 50d3a53d970c..0721b77186d3 100644 --- a/drivers/soc/qcom/rimps_log.c +++ b/drivers/soc/qcom/rimps_log.c @@ -126,7 +126,7 @@ static void rimps_log_work(struct work_struct *work) } } else { ipc_log_string(info->ipc_log_ctxt, - "%s\n", src, c); + "%s\n", src); } buf_start += cnt; From 2055929c91e21301488850448028b9aa7977f2fb Mon Sep 17 00:00:00 2001 From: Santosh Mardi Date: Mon, 23 Nov 2020 20:53:29 +0530 Subject: [PATCH 3/3] PM / devfreq: export functions to allow freeing of pmu counters Memlat and compute governors are made immutable to avoid governor switch at run time as the devices using these governors are tightly coupled with hardware features. These governors allocate pmu counters to count various events used in the algorithm. These counters are allocated exclusively for algorithm's use. This leaves limited counters available for other uses in the system such as profiling in user space using perf tool. Add and export a function in devfreq memlat governor to remove immutable flag to allow governor switch, which in turn can free pmu counters. Similarly add and export a function in rimps_memlat driver to free pmu counters. The intended use of these functions is to be called by test modules to allow freeing of pmu counters at runtime. Change-Id: I243a3201368d5a82aeaf820e775cdc1aecdfea07 Signed-off-by: Santosh Mardi --- drivers/devfreq/governor_memlat.c | 10 ++++++++++ drivers/soc/qcom/rimps_memlat.c | 15 +++++++++++++++ 2 files changed, 25 insertions(+) diff --git a/drivers/devfreq/governor_memlat.c b/drivers/devfreq/governor_memlat.c index 57640063c643..33ce6e2765ee 100644 --- a/drivers/devfreq/governor_memlat.c +++ b/drivers/devfreq/governor_memlat.c @@ -451,6 +451,16 @@ static struct devfreq_governor devfreq_gov_compute = { .event_handler = devfreq_memlat_ev_handler, }; +void memlat_set_immutable_flag(unsigned int flag) +{ + unsigned int *memlat_ptr = (unsigned int *)&devfreq_gov_memlat.immutable; + unsigned int *compute_ptr = (unsigned int *)&devfreq_gov_compute.immutable; + + *memlat_ptr = flag; + *compute_ptr = flag; +} +EXPORT_SYMBOL(memlat_set_immutable_flag); + #define NUM_COLS 2 static struct core_dev_map *init_core_dev_map(struct device *dev, struct device_node *of_node, diff --git a/drivers/soc/qcom/rimps_memlat.c b/drivers/soc/qcom/rimps_memlat.c index 957825e959ad..1c3de9aa69fd 100644 --- a/drivers/soc/qcom/rimps_memlat.c +++ b/drivers/soc/qcom/rimps_memlat.c @@ -807,6 +807,21 @@ static int memlat_event_cpu_hp_init(void) return ret; } +void rimps_force_free_pmu_events(unsigned int flag) +{ + unsigned int cpu; + + get_online_cpus(); + for_each_possible_cpu(cpu) { + if (flag) + memlat_event_hotplug_going_down(cpu); + else + memlat_event_hotplug_coming_up(cpu); + } + put_online_cpus(); +} +EXPORT_SYMBOL(rimps_force_free_pmu_events); + static int memlat_idle_notif(struct notifier_block *nb, unsigned long action, void *data)