From patchwork Wed Nov 19 20:36:21 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ashwin Chaugule X-Patchwork-Id: 41212 Return-Path: X-Original-To: linaro@patches.linaro.org Delivered-To: linaro@patches.linaro.org Received: from mail-la0-f72.google.com (mail-la0-f72.google.com [209.85.215.72]) by ip-10-151-82-157.ec2.internal (Postfix) with ESMTPS id 8A44F20CBB for ; Wed, 19 Nov 2014 20:36:53 +0000 (UTC) Received: by mail-la0-f72.google.com with SMTP id mc6sf917698lab.7 for ; Wed, 19 Nov 2014 12:36:52 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:mime-version:delivered-to:from:to:cc:subject :date:message-id:in-reply-to:references:x-original-sender :x-original-authentication-results:precedence:mailing-list:list-id :list-post:list-help:list-archive:list-unsubscribe; bh=AOiKodvyqu82u6Tu4T62yumEROHq6kIGd84zwzuIiRo=; b=OpNKCsfyXyzeu5hRNSoBf100JcXS9TcDllnRUDF6urEzN/+YhJ2cEwH/vojen+PMDj ay9rbbYSQv2Qh2SeACuo4BrAIeYMHrkBH2yU+BAFwGAAiDostYfRR/XeYNr594LIHGyb tWDS2Ia9DDzsPlSCNVh0SoD9wFMZpZ/4sFGqKQePdzasQIdkztcAiAGAIDK7It4P1L0+ pzUQvkSx4kIlExdPLoMLPZRSOflAV5ECIjIGfctIqYGTLDhrstBxk1LC6xn+hDwvH1a8 rA6j/DHaB5PAuBWoFTw07hDmpcnUQG1s48/oJNZDtRxCw53tTYw/b1hL+5iEKwDOt5x/ ndjw== X-Gm-Message-State: ALoCoQk/BGkd91ziSLOtLSWVslWhovdmYDjfWUMN/Hj26v/CYQNKyyZ2palekO9Ojp5jHS0J1BQd X-Received: by 10.152.6.4 with SMTP id w4mr1039687law.7.1416429412502; Wed, 19 Nov 2014 12:36:52 -0800 (PST) MIME-Version: 1.0 X-BeenThere: patchwork-forward@linaro.org Received: by 10.152.6.169 with SMTP id c9ls1354885laa.104.gmail; Wed, 19 Nov 2014 12:36:52 -0800 (PST) X-Received: by 10.152.120.73 with SMTP id la9mr44240773lab.23.1416429412123; Wed, 19 Nov 2014 12:36:52 -0800 (PST) Received: from mail-lb0-f175.google.com (mail-lb0-f175.google.com. [209.85.217.175]) by mx.google.com with ESMTPS id k17si246716laa.67.2014.11.19.12.36.52 for (version=TLSv1 cipher=ECDHE-RSA-RC4-SHA bits=128/128); Wed, 19 Nov 2014 12:36:52 -0800 (PST) Received-SPF: pass (google.com: domain of patch+caf_=patchwork-forward=linaro.org@linaro.org designates 209.85.217.175 as permitted sender) client-ip=209.85.217.175; Received: by mail-lb0-f175.google.com with SMTP id n15so1182972lbi.6 for ; Wed, 19 Nov 2014 12:36:52 -0800 (PST) X-Received: by 10.112.62.166 with SMTP id z6mr7168304lbr.74.1416429411989; Wed, 19 Nov 2014 12:36:51 -0800 (PST) X-Forwarded-To: patchwork-forward@linaro.org X-Forwarded-For: patch@linaro.org patchwork-forward@linaro.org Delivered-To: patches@linaro.org Received: by 10.112.184.201 with SMTP id ew9csp158302lbc; Wed, 19 Nov 2014 12:36:50 -0800 (PST) X-Received: by 10.68.162.100 with SMTP id xz4mr24155648pbb.138.1416429410092; Wed, 19 Nov 2014 12:36:50 -0800 (PST) Received: from mail-pd0-f174.google.com (mail-pd0-f174.google.com. [209.85.192.174]) by mx.google.com with ESMTPS id fa3si436388pab.30.2014.11.19.12.36.49 for (version=TLSv1 cipher=ECDHE-RSA-RC4-SHA bits=128/128); Wed, 19 Nov 2014 12:36:50 -0800 (PST) Received-SPF: pass (google.com: domain of ashwin.chaugule@linaro.org designates 209.85.192.174 as permitted sender) client-ip=209.85.192.174; Received: by mail-pd0-f174.google.com with SMTP id w10so1552719pde.33 for ; Wed, 19 Nov 2014 12:36:49 -0800 (PST) X-Received: by 10.66.120.129 with SMTP id lc1mr24927751pab.86.1416429409348; Wed, 19 Nov 2014 12:36:49 -0800 (PST) Received: from esagroth.qualcomm.com (rrcs-67-52-130-30.west.biz.rr.com. [67.52.130.30]) by mx.google.com with ESMTPSA id nu3sm113326pbb.60.2014.11.19.12.36.44 for (version=TLSv1.2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Wed, 19 Nov 2014 12:36:48 -0800 (PST) From: Ashwin Chaugule To: viresh.kumar@linaro.org Cc: rwells@codeaurora.org, linda.knippers@hp.com, linux-pm@vger.kernel.org, Catalin.Marinas@arm.com, dirk.brandewie@gmail.com, patches@linaro.org, linaro-acpi@lists.linaro.org, rjw@rjwysocki.net, Ashwin Chaugule Subject: [PATCH v3 2/2] ACPI PID: Add frequency domain awareness. Date: Wed, 19 Nov 2014 15:36:21 -0500 Message-Id: <1416429381-3839-3-git-send-email-ashwin.chaugule@linaro.org> X-Mailer: git-send-email 1.9.1 In-Reply-To: <1416429381-3839-1-git-send-email-ashwin.chaugule@linaro.org> References: <1416429381-3839-1-git-send-email-ashwin.chaugule@linaro.org> X-Removed-Original-Auth: Dkim didn't pass. X-Original-Sender: ashwin.chaugule@linaro.org X-Original-Authentication-Results: mx.google.com; spf=pass (google.com: domain of patch+caf_=patchwork-forward=linaro.org@linaro.org designates 209.85.217.175 as permitted sender) smtp.mail=patch+caf_=patchwork-forward=linaro.org@linaro.org Precedence: list Mailing-list: list patchwork-forward@linaro.org; contact patchwork-forward+owners@linaro.org List-ID: X-Google-Group-Id: 836684582541 List-Post: , List-Help: , List-Archive: List-Unsubscribe: , Previously the driver assumed each CPU to be in its own frequency domain. But this may not be always true in practice. Search for the PSD ACPI package for each CPU and parse its domain information. Once this information is known, the first CPU to wake up from a timeout evaluates all other CPUs in its domain and makes a collective vote for all. Each sibling CPUs timeout is defferred as it is evaluated. There could be a pending IRQ for such a CPU, in which case a spinlock protects the sample data, and on spin_unlock, we let it proceed and re-evaluate. Signed-off-by: Ashwin Chaugule --- drivers/cpufreq/acpi_pid.c | 112 +++++++++++++++++++++++++++++++++++++-------- 1 file changed, 93 insertions(+), 19 deletions(-) diff --git a/drivers/cpufreq/acpi_pid.c b/drivers/cpufreq/acpi_pid.c index f8d8376..ccaace9 100644 --- a/drivers/cpufreq/acpi_pid.c +++ b/drivers/cpufreq/acpi_pid.c @@ -60,6 +60,7 @@ #include #include +#include #include #define FRAC_BITS 8 @@ -114,6 +115,14 @@ struct cpudata { u64 prev_reference; u64 prev_delivered; struct sample sample; + cpumask_var_t shared_cpus; + /* + * This lock protects a CPU sample + * from being overwritten while it + * is being evaluated by another CPU + * in the shared_cpu map. + */ + spinlock_t sample_lock; }; static struct cpudata **all_cpu_data; @@ -207,6 +216,7 @@ struct cpc_desc { }; static DEFINE_PER_CPU(struct cpc_desc *, cpc_desc_ptr); +static struct acpi_processor_performance __percpu *acpi_perf_info; static int cpc_read64(u64 *val, struct cpc_register_resource *reg) { @@ -535,6 +545,8 @@ static inline int acpi_pid_sample(struct cpudata *cpu) { int ret = 0; + spin_lock(&cpu->sample_lock); + cpu->last_sample_time = cpu->sample.time; cpu->sample.time = ktime_get(); @@ -545,6 +557,8 @@ static inline int acpi_pid_sample(struct cpudata *cpu) acpi_pid_calc_busy(cpu); + spin_unlock(&cpu->sample_lock); + return ret; } @@ -579,40 +593,51 @@ static inline int32_t acpi_pid_get_scaled_busy(struct cpudata *cpu) return core_busy; } -static inline int acpi_pid_adjust_busy_pstate(struct cpudata *cpu) +static void acpi_pid_timer_func(unsigned long __data) { - int32_t busy_scaled; + struct cpudata *cpu = (struct cpudata *) __data; + struct sample *sample; + struct cpudata *sibling_cpu; + struct cpudata *max_busy_cpu = NULL; struct _pid *pid; signed int ctl; + int32_t max_busy = 0, busy, i; - pid = &cpu->pid; - busy_scaled = acpi_pid_get_scaled_busy(cpu); + for_each_cpu(i, cpu->shared_cpus) { + /* Get sibling cpu ptr. */ + sibling_cpu = all_cpu_data[i]; - ctl = pid_calc(pid, busy_scaled); + /* Get its sample data. */ + acpi_pid_sample(sibling_cpu); - /* Negative values of ctl increase the pstate and vice versa */ - return acpi_pid_set_pstate(cpu, cpu->pstate.current_pstate - ctl); -} + /* Defer its timeout. */ + acpi_pid_set_sample_time(sibling_cpu); -static void acpi_pid_timer_func(unsigned long __data) -{ - struct cpudata *cpu = (struct cpudata *) __data; - struct sample *sample; + /* Calc how busy it was. */ + busy = acpi_pid_get_scaled_busy(sibling_cpu); - acpi_pid_sample(cpu); + /* Was this the most busiest? */ + if (busy >= max_busy) { + max_busy = busy; + max_busy_cpu = sibling_cpu; + } + } - sample = &cpu->sample; + sample = &max_busy_cpu->sample; - acpi_pid_adjust_busy_pstate(cpu); + pid = &max_busy_cpu->pid; + ctl = pid_calc(pid, max_busy); + + /* XXX: This needs to change depending on SW_ANY/SW_ALL */ + /* Negative values of ctl increase the pstate and vice versa */ + acpi_pid_set_pstate(max_busy_cpu, max_busy_cpu->pstate.current_pstate - ctl); trace_pstate_sample(fp_toint(sample->core_pct_busy), fp_toint(acpi_pid_get_scaled_busy(cpu)), cpu->pstate.current_pstate, - sample->delivered, sample->reference, + sample->delivered, sample->freq); - - acpi_pid_set_sample_time(cpu); } static int acpi_pid_init_cpu(unsigned int cpunum) @@ -627,6 +652,7 @@ static int acpi_pid_init_cpu(unsigned int cpunum) cpu = all_cpu_data[cpunum]; cpu->cpu = cpunum; + spin_lock_init(&cpu->sample_lock); ret = acpi_pid_get_cpu_pstates(cpu); if (ret < 0) @@ -712,6 +738,7 @@ static void acpi_pid_stop_cpu(struct cpufreq_policy *policy) static int acpi_pid_cpu_init(struct cpufreq_policy *policy) { struct cpudata *cpu; + struct acpi_processor_performance *perf; int rc; rc = acpi_pid_init_cpu(policy->cpu); @@ -732,7 +759,25 @@ static int acpi_pid_cpu_init(struct cpufreq_policy *policy) policy->cpuinfo.min_freq = cpu->pstate.min_pstate * 100000; policy->cpuinfo.max_freq = cpu->pstate.max_pstate * 100000; policy->cpuinfo.transition_latency = CPUFREQ_ETERNAL; + + if (!zalloc_cpumask_var_node(&cpu->shared_cpus, + GFP_KERNEL, cpu_to_node(policy->cpu))) { + pr_err("No mem for shared_cpus cpumask\n"); + return -ENOMEM; + } + + /* Parse the PSD info we acquired in acpi_cppc_init */ + perf = per_cpu_ptr(acpi_perf_info, policy->cpu); + policy->shared_type = perf->shared_type; + + if (policy->shared_type == CPUFREQ_SHARED_TYPE_ALL || + policy->shared_type == CPUFREQ_SHARED_TYPE_ANY) { + cpumask_copy(policy->cpus, perf->shared_cpu_map); + cpumask_copy(cpu->shared_cpus, perf->shared_cpu_map); + } + cpumask_set_cpu(policy->cpu, policy->cpus); + cpumask_set_cpu(policy->cpu, cpu->shared_cpus); return 0; } @@ -1103,8 +1148,20 @@ static struct cpu_defaults acpi_pid_cppc = { }, }; +static void free_acpi_perf_info(void) +{ + unsigned int i; + + for_each_possible_cpu(i) + free_cpumask_var(per_cpu_ptr(acpi_perf_info, i) + ->shared_cpu_map); + free_percpu(acpi_perf_info); +} + static int __init acpi_cppc_init(void) { + unsigned int i; + if (acpi_disabled || acpi_cppc_processor_probe()) { pr_err("Err initializing CPC structures or ACPI is disabled\n"); return -ENODEV; @@ -1113,7 +1170,24 @@ static int __init acpi_cppc_init(void) copy_pid_params(&acpi_pid_cppc.pid_policy); copy_cpu_funcs(&acpi_pid_cppc.funcs); - return 0; + acpi_perf_info = alloc_percpu(struct acpi_processor_performance); + if (!acpi_perf_info) { + pr_err("Out for mem for acpi_perf_info\n"); + return -ENOMEM; + } + + for_each_possible_cpu(i) { + if (!zalloc_cpumask_var_node( + &per_cpu_ptr(acpi_perf_info, i)->shared_cpu_map, + GFP_KERNEL, cpu_to_node(i))) { + + free_acpi_perf_info(); + return -ENOMEM; + } + } + + /* Get _PSD info about CPUs and the freq domain they belong to. */ + return acpi_processor_preregister_performance(acpi_perf_info); } static int __init acpi_pid_init(void)