diff options
author | Prakash, Prashanth <pprakash@codeaurora.org> | 2016-08-16 16:39:41 -0400 |
---|---|---|
committer | Rafael J. Wysocki <rafael.j.wysocki@intel.com> | 2016-08-30 19:02:33 -0400 |
commit | be8b88d7d9877114172b32817d8eb3e85d3d8f99 (patch) | |
tree | 46cfd3c473ffcf900680952a437d137355eef6a2 /drivers/acpi/cppc_acpi.c | |
parent | 80b8286aeec056d21bffed2d1ece3904516e9c91 (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>
Diffstat (limited to 'drivers/acpi/cppc_acpi.c')
-rw-r--r-- | drivers/acpi/cppc_acpi.c | 46 |
1 files changed, 44 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; | |||
85 | static int pcc_subspace_idx = -1; | 85 | static int pcc_subspace_idx = -1; |
86 | static bool pcc_channel_acquired; | 86 | static bool pcc_channel_acquired; |
87 | static ktime_t deadline; | 87 | static ktime_t deadline; |
88 | static unsigned int pcc_mpar, pcc_mrtt; | 88 | static 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 | } |
1050 | EXPORT_SYMBOL_GPL(cppc_set_perf); | 1050 | EXPORT_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 | */ | ||
1060 | unsigned 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 | } | ||
1092 | EXPORT_SYMBOL_GPL(cppc_get_transition_latency); | ||