aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPrakash, Prashanth <pprakash@codeaurora.org>2016-08-16 16:39:41 -0400
committerRafael J. Wysocki <rafael.j.wysocki@intel.com>2016-08-30 19:02:33 -0400
commitbe8b88d7d9877114172b32817d8eb3e85d3d8f99 (patch)
tree46cfd3c473ffcf900680952a437d137355eef6a2
parent80b8286aeec056d21bffed2d1ece3904516e9c91 (diff)
ACPI / CPPC: set a non-zero value for transition_latency
Compute the expected transition latency for frequency transitions using the values from the PCCT tables when the desired perf register is in PCC. Signed-off-by: Prashanth Prakash <pprakash@codeaurora.org> Reviewed-by: Alexey Klimov <alexey.klimov@arm.com> Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
-rw-r--r--drivers/acpi/cppc_acpi.c46
-rw-r--r--drivers/cpufreq/cppc_cpufreq.c1
-rw-r--r--include/acpi/cppc_acpi.h1
3 files changed, 46 insertions, 2 deletions
diff --git a/drivers/acpi/cppc_acpi.c b/drivers/acpi/cppc_acpi.c
index 5623fca54ca1..6c54a8f16706 100644
--- a/drivers/acpi/cppc_acpi.c
+++ b/drivers/acpi/cppc_acpi.c
@@ -85,7 +85,7 @@ static void __iomem *pcc_comm_addr;
85static int pcc_subspace_idx = -1; 85static int pcc_subspace_idx = -1;
86static bool pcc_channel_acquired; 86static bool pcc_channel_acquired;
87static ktime_t deadline; 87static ktime_t deadline;
88static unsigned int pcc_mpar, pcc_mrtt; 88static unsigned int pcc_mpar, pcc_mrtt, pcc_nominal;
89 89
90/* pcc mapped address + header size + offset within PCC subspace */ 90/* pcc mapped address + header size + offset within PCC subspace */
91#define GET_PCC_VADDR(offs) (pcc_comm_addr + 0x8 + (offs)) 91#define GET_PCC_VADDR(offs) (pcc_comm_addr + 0x8 + (offs))
@@ -473,7 +473,6 @@ static int register_pcc_channel(int pcc_subspace_idx)
473 return -ENODEV; 473 return -ENODEV;
474 } 474 }
475 475
476
477 /* 476 /*
478 * cppc_ss->latency is just a Nominal value. In reality 477 * cppc_ss->latency is just a Nominal value. In reality
479 * the remote processor could be much slower to reply. 478 * the remote processor could be much slower to reply.
@@ -483,6 +482,7 @@ static int register_pcc_channel(int pcc_subspace_idx)
483 deadline = ns_to_ktime(usecs_lat * NSEC_PER_USEC); 482 deadline = ns_to_ktime(usecs_lat * NSEC_PER_USEC);
484 pcc_mrtt = cppc_ss->min_turnaround_time; 483 pcc_mrtt = cppc_ss->min_turnaround_time;
485 pcc_mpar = cppc_ss->max_access_rate; 484 pcc_mpar = cppc_ss->max_access_rate;
485 pcc_nominal = cppc_ss->latency;
486 486
487 pcc_comm_addr = acpi_os_ioremap(cppc_ss->base_address, cppc_ss->length); 487 pcc_comm_addr = acpi_os_ioremap(cppc_ss->base_address, cppc_ss->length);
488 if (!pcc_comm_addr) { 488 if (!pcc_comm_addr) {
@@ -1048,3 +1048,45 @@ int cppc_set_perf(int cpu, struct cppc_perf_ctrls *perf_ctrls)
1048 return ret; 1048 return ret;
1049} 1049}
1050EXPORT_SYMBOL_GPL(cppc_set_perf); 1050EXPORT_SYMBOL_GPL(cppc_set_perf);
1051
1052/**
1053 * cppc_get_transition_latency - returns frequency transition latency in ns
1054 *
1055 * ACPI CPPC does not explicitly specifiy how a platform can specify the
1056 * transition latency for perfromance change requests. The closest we have
1057 * is the timing information from the PCCT tables which provides the info
1058 * on the number and frequency of PCC commands the platform can handle.
1059 */
1060unsigned int cppc_get_transition_latency(int cpu_num)
1061{
1062 /*
1063 * Expected transition latency is based on the PCCT timing values
1064 * Below are definition from ACPI spec:
1065 * pcc_nominal- Expected latency to process a command, in microseconds
1066 * pcc_mpar - The maximum number of periodic requests that the subspace
1067 * channel can support, reported in commands per minute. 0
1068 * indicates no limitation.
1069 * pcc_mrtt - The minimum amount of time that OSPM must wait after the
1070 * completion of a command before issuing the next command,
1071 * in microseconds.
1072 */
1073 unsigned int latency_ns = 0;
1074 struct cpc_desc *cpc_desc;
1075 struct cpc_register_resource *desired_reg;
1076
1077 cpc_desc = per_cpu(cpc_desc_ptr, cpu_num);
1078 if (!cpc_desc)
1079 return CPUFREQ_ETERNAL;
1080
1081 desired_reg = &cpc_desc->cpc_regs[DESIRED_PERF];
1082 if (!CPC_IN_PCC(desired_reg))
1083 return CPUFREQ_ETERNAL;
1084
1085 if (pcc_mpar)
1086 latency_ns = 60 * (1000 * 1000 * 1000 / pcc_mpar);
1087
1088 latency_ns = max(latency_ns, (pcc_nominal + pcc_mrtt) * 1000);
1089
1090 return latency_ns;
1091}
1092EXPORT_SYMBOL_GPL(cppc_get_transition_latency);
diff --git a/drivers/cpufreq/cppc_cpufreq.c b/drivers/cpufreq/cppc_cpufreq.c
index 8882b8e2ecd0..e6a33596dea3 100644
--- a/drivers/cpufreq/cppc_cpufreq.c
+++ b/drivers/cpufreq/cppc_cpufreq.c
@@ -98,6 +98,7 @@ static int cppc_cpufreq_cpu_init(struct cpufreq_policy *policy)
98 policy->max = cpu->perf_caps.highest_perf; 98 policy->max = cpu->perf_caps.highest_perf;
99 policy->cpuinfo.min_freq = policy->min; 99 policy->cpuinfo.min_freq = policy->min;
100 policy->cpuinfo.max_freq = policy->max; 100 policy->cpuinfo.max_freq = policy->max;
101 policy->cpuinfo.transition_latency = cppc_get_transition_latency(cpu_num);
101 policy->shared_type = cpu->shared_type; 102 policy->shared_type = cpu->shared_type;
102 103
103 if (policy->shared_type == CPUFREQ_SHARED_TYPE_ANY) 104 if (policy->shared_type == CPUFREQ_SHARED_TYPE_ANY)
diff --git a/include/acpi/cppc_acpi.h b/include/acpi/cppc_acpi.h
index d2101bcea013..42cbeb93ea32 100644
--- a/include/acpi/cppc_acpi.h
+++ b/include/acpi/cppc_acpi.h
@@ -131,5 +131,6 @@ extern int cppc_get_perf_ctrs(int cpu, struct cppc_perf_fb_ctrs *perf_fb_ctrs);
131extern int cppc_set_perf(int cpu, struct cppc_perf_ctrls *perf_ctrls); 131extern int cppc_set_perf(int cpu, struct cppc_perf_ctrls *perf_ctrls);
132extern int cppc_get_perf_caps(int cpu, struct cppc_perf_caps *caps); 132extern int cppc_get_perf_caps(int cpu, struct cppc_perf_caps *caps);
133extern int acpi_get_psd_map(struct cpudata **); 133extern int acpi_get_psd_map(struct cpudata **);
134extern unsigned int cppc_get_transition_latency(int cpu);
134 135
135#endif /* _CPPC_ACPI_H*/ 136#endif /* _CPPC_ACPI_H*/