Skip to content

Commit

Permalink
ACPI / CPPC: set a non-zero value for transition_latency
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Prakash, Prashanth authored and Rafael J. Wysocki committed Aug 30, 2016
1 parent 80b8286 commit be8b88d
Show file tree
Hide file tree
Showing 3 changed files with 46 additions and 2 deletions.
46 changes: 44 additions & 2 deletions drivers/acpi/cppc_acpi.c
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ static void __iomem *pcc_comm_addr;
static int pcc_subspace_idx = -1;
static bool pcc_channel_acquired;
static ktime_t deadline;
static unsigned int pcc_mpar, pcc_mrtt;
static unsigned int pcc_mpar, pcc_mrtt, pcc_nominal;

/* pcc mapped address + header size + offset within PCC subspace */
#define GET_PCC_VADDR(offs) (pcc_comm_addr + 0x8 + (offs))
Expand Down Expand Up @@ -473,7 +473,6 @@ static int register_pcc_channel(int pcc_subspace_idx)
return -ENODEV;
}


/*
* cppc_ss->latency is just a Nominal value. In reality
* the remote processor could be much slower to reply.
Expand All @@ -483,6 +482,7 @@ static int register_pcc_channel(int pcc_subspace_idx)
deadline = ns_to_ktime(usecs_lat * NSEC_PER_USEC);
pcc_mrtt = cppc_ss->min_turnaround_time;
pcc_mpar = cppc_ss->max_access_rate;
pcc_nominal = cppc_ss->latency;

pcc_comm_addr = acpi_os_ioremap(cppc_ss->base_address, cppc_ss->length);
if (!pcc_comm_addr) {
Expand Down Expand Up @@ -1048,3 +1048,45 @@ int cppc_set_perf(int cpu, struct cppc_perf_ctrls *perf_ctrls)
return ret;
}
EXPORT_SYMBOL_GPL(cppc_set_perf);

/**
* cppc_get_transition_latency - returns frequency transition latency in ns
*
* ACPI CPPC does not explicitly specifiy how a platform can specify the
* transition latency for perfromance change requests. The closest we have
* is the timing information from the PCCT tables which provides the info
* on the number and frequency of PCC commands the platform can handle.
*/
unsigned int cppc_get_transition_latency(int cpu_num)
{
/*
* Expected transition latency is based on the PCCT timing values
* Below are definition from ACPI spec:
* pcc_nominal- Expected latency to process a command, in microseconds
* pcc_mpar - The maximum number of periodic requests that the subspace
* channel can support, reported in commands per minute. 0
* indicates no limitation.
* pcc_mrtt - The minimum amount of time that OSPM must wait after the
* completion of a command before issuing the next command,
* in microseconds.
*/
unsigned int latency_ns = 0;
struct cpc_desc *cpc_desc;
struct cpc_register_resource *desired_reg;

cpc_desc = per_cpu(cpc_desc_ptr, cpu_num);
if (!cpc_desc)
return CPUFREQ_ETERNAL;

desired_reg = &cpc_desc->cpc_regs[DESIRED_PERF];
if (!CPC_IN_PCC(desired_reg))
return CPUFREQ_ETERNAL;

if (pcc_mpar)
latency_ns = 60 * (1000 * 1000 * 1000 / pcc_mpar);

latency_ns = max(latency_ns, (pcc_nominal + pcc_mrtt) * 1000);

return latency_ns;
}
EXPORT_SYMBOL_GPL(cppc_get_transition_latency);
1 change: 1 addition & 0 deletions drivers/cpufreq/cppc_cpufreq.c
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,7 @@ static int cppc_cpufreq_cpu_init(struct cpufreq_policy *policy)
policy->max = cpu->perf_caps.highest_perf;
policy->cpuinfo.min_freq = policy->min;
policy->cpuinfo.max_freq = policy->max;
policy->cpuinfo.transition_latency = cppc_get_transition_latency(cpu_num);
policy->shared_type = cpu->shared_type;

if (policy->shared_type == CPUFREQ_SHARED_TYPE_ANY)
Expand Down
1 change: 1 addition & 0 deletions include/acpi/cppc_acpi.h
Original file line number Diff line number Diff line change
Expand Up @@ -131,5 +131,6 @@ extern int cppc_get_perf_ctrs(int cpu, struct cppc_perf_fb_ctrs *perf_fb_ctrs);
extern int cppc_set_perf(int cpu, struct cppc_perf_ctrls *perf_ctrls);
extern int cppc_get_perf_caps(int cpu, struct cppc_perf_caps *caps);
extern int acpi_get_psd_map(struct cpudata **);
extern unsigned int cppc_get_transition_latency(int cpu);

#endif /* _CPPC_ACPI_H*/

0 comments on commit be8b88d

Please sign in to comment.