Received: by 2002:a05:7412:2a8c:b0:e2:908c:2ebd with SMTP id u12csp2090615rdh; Tue, 26 Sep 2023 12:04:20 -0700 (PDT) X-Google-Smtp-Source: AGHT+IH+ZGT60bCNKF6K1nZb3kQBqExO9mzMv5Pn7iswICUQx/OlQzkkPxM4ddyuuP618K/fc/4R X-Received: by 2002:a17:90a:d489:b0:267:c0cb:e462 with SMTP id s9-20020a17090ad48900b00267c0cbe462mr7014696pju.48.1695755059691; Tue, 26 Sep 2023 12:04:19 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1695755059; cv=none; d=google.com; s=arc-20160816; b=abOVfIv7LH+cZaEmwMJGr6i2LGOXrmbFOxsqkR/vDm4FY8SpwYQC0xuwq5B+Q5ZNV8 td25UKktuo8QNOLB6UchSXEtTXbU723Xxs997hsIiIATazowwL3N4Fzrftp6hkbhuu9l YWDOxUBs9KXuoZkedzMYJx/hDrLt2kGTJFFfwEKzgNN0jWf/fJhrJ0j7IRNUpmx/lNl0 xsFkr2kwRfITIUOOVeYcQ9c40JGGsdtw/7o+U8EqTWVf5klSRUWYsc/tBImoyZQ/J8ts OpQdaJGi3nVlHwpAwxJyrA/D5uJkuQXwWOybgTsGdxFYCO14T+c7OUnGfoEMxtGRg+XV fSmA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:content-transfer-encoding:cc:to:subject :message-id:date:from:in-reply-to:references:mime-version; bh=Kp00Qep7LLPgt/nPgaXwnXy1m5DM6jNgTyx+/A+2Yy4=; fh=O6YYF95gEoTquszwa1x1Mp3NZS9Am1klEUxdtkLeXmY=; b=nwQ1HgGxZ4pcAd01Djooe7DWHABdaK7j9c9yavEA3Z8URox5U1kSol2TeH0RC1SeFD Al1G4f4mtHAcK9xtCHCKGas9/MmRio1cQzltVzeuqILDNdWjDtHZnveESCVO7UitFgoT XytbUkODw6Xd6s3gRcMF9ZAEXy/mqUOtqpt5Jb1nJzsfgFTA05IW2A8V+mvrXla/aFf4 HzjCMmyQfRgvu8QU4JMBC8B5uF0sP+QFPaEOROayBwF9PCowset5IgHA5729gJwMCqWI qLkVCVWIxd9zAWRtuhGNPsHIeSPYhcs622u3xjq/9EsyoX6r3G9KXOa6qok8O2qv6JQc rM/Q== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::3:1 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=kernel.org Return-Path: Received: from morse.vger.email (morse.vger.email. [2620:137:e000::3:1]) by mx.google.com with ESMTPS id c9-20020a17090ab28900b00274dcfcf309si15069342pjr.83.2023.09.26.12.04.19 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 26 Sep 2023 12:04:19 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::3:1 as permitted sender) client-ip=2620:137:e000::3:1; Authentication-Results: mx.google.com; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::3:1 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=kernel.org Received: from out1.vger.email (depot.vger.email [IPv6:2620:137:e000::3:0]) by morse.vger.email (Postfix) with ESMTP id 529D8826E3B5; Tue, 26 Sep 2023 11:52:27 -0700 (PDT) X-Virus-Status: Clean X-Virus-Scanned: clamav-milter 0.103.10 at morse.vger.email Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S235625AbjIZSwZ convert rfc822-to-8bit (ORCPT + 99 others); Tue, 26 Sep 2023 14:52:25 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:39182 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S235600AbjIZSwY (ORCPT ); Tue, 26 Sep 2023 14:52:24 -0400 Received: from mail-oo1-f52.google.com (mail-oo1-f52.google.com [209.85.161.52]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id B4545194; Tue, 26 Sep 2023 11:52:14 -0700 (PDT) Received: by mail-oo1-f52.google.com with SMTP id 006d021491bc7-57c0775d4fcso237003eaf.0; Tue, 26 Sep 2023 11:52:14 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1695754334; x=1696359134; h=content-transfer-encoding:cc:to:subject:message-id:date:from :in-reply-to:references:mime-version:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=T9EEcz88p/fMmIocGQC2OR/atoxLGQssRLX7uVCAPaw=; b=dxvB0OYlTRWk8m9GwiNlLSnUbZm0IgD0z69XrJYbi3+bzrb1HnAPU64ssEfGnjGIfl jV1ER00N0VchxtBzc70rsUck/sZ4wxAjlr+L1vEVCgXGtcwT52XyAfMx5ncNMi5UddWZ iClQypXMfPAHMsQKIVmgW1kzc6xNVWLbXpPhBz8xwqsEEF/UJjOhFuI4Wfd8w7MPm23v PNptk5OTnwafWQQIegi88ZlWzsEYT6WI7stG8mUr7qVTkKV8xBEg+XyVbS8f3W85C5JO tKkYa63gsh4SrSxGsuR1fTpFhloYihDWCufCX0yNx3mn/0QrlbxbjEcwPfbanjIMfHYN 6caA== X-Gm-Message-State: AOJu0YzPeN7hVE4QPPTDFBRjDdb76FLXLF4VPmfaY+zptPMcssqk5cf8 8ZBhbUm/0xe0MzF75qOdfHZyzklGQgktpQeEZ+u/cyhH X-Received: by 2002:a4a:d9da:0:b0:56e:94ed:c098 with SMTP id l26-20020a4ad9da000000b0056e94edc098mr9353747oou.0.1695754333687; Tue, 26 Sep 2023 11:52:13 -0700 (PDT) MIME-Version: 1.0 References: <20230925081139.1305766-1-lukasz.luba@arm.com> <20230925081139.1305766-8-lukasz.luba@arm.com> In-Reply-To: <20230925081139.1305766-8-lukasz.luba@arm.com> From: "Rafael J. Wysocki" Date: Tue, 26 Sep 2023 20:52:02 +0200 Message-ID: Subject: Re: [PATCH v4 07/18] PM: EM: Refactor struct em_perf_domain and add default_table To: Lukasz Luba Cc: linux-kernel@vger.kernel.org, linux-pm@vger.kernel.org, rafael@kernel.org, dietmar.eggemann@arm.com, rui.zhang@intel.com, amit.kucheria@verdurent.com, amit.kachhap@gmail.com, daniel.lezcano@linaro.org, viresh.kumar@linaro.org, len.brown@intel.com, pavel@ucw.cz, mhiramat@kernel.org, qyousef@layalina.io, wvw@google.com Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: 8BIT X-Spam-Status: No, score=-1.0 required=5.0 tests=MAILING_LIST_MULTI, SPF_HELO_NONE,SPF_PASS autolearn=unavailable autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on morse.vger.email Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org X-Greylist: Sender passed SPF test, not delayed by milter-greylist-4.6.4 (morse.vger.email [0.0.0.0]); Tue, 26 Sep 2023 11:52:27 -0700 (PDT) On Mon, Sep 25, 2023 at 10:11 AM Lukasz Luba wrote: > > The Energy Model is going to support runtime modifications. Refactor old > implementation which accessed struct em_perf_state and introduce > em_perf_domain::default_table to clean up the design. This new field > will help to better distinguish 2 performance state tables. > > Update all drivers or frameworks which used the old field: > em_perf_domain::table and now should use em_perf_domain::default_table. > > Signed-off-by: Lukasz Luba > --- > drivers/powercap/dtpm_cpu.c | 27 +++++++++++++++++++-------- > drivers/powercap/dtpm_devfreq.c | 23 ++++++++++++++++------- > drivers/thermal/cpufreq_cooling.c | 24 ++++++++++++++++-------- > drivers/thermal/devfreq_cooling.c | 23 +++++++++++++++++------ > include/linux/energy_model.h | 24 ++++++++++++++++++------ > kernel/power/energy_model.c | 26 ++++++++++++++++++++++---- > 6 files changed, 108 insertions(+), 39 deletions(-) > > diff --git a/drivers/powercap/dtpm_cpu.c b/drivers/powercap/dtpm_cpu.c > index 2ff7717530bf..743a0ac8ecdf 100644 > --- a/drivers/powercap/dtpm_cpu.c > +++ b/drivers/powercap/dtpm_cpu.c > @@ -43,6 +43,7 @@ static u64 set_pd_power_limit(struct dtpm *dtpm, u64 power_limit) > { > struct dtpm_cpu *dtpm_cpu = to_dtpm_cpu(dtpm); > struct em_perf_domain *pd = em_cpu_get(dtpm_cpu->cpu); > + struct em_perf_state *table; > struct cpumask cpus; > unsigned long freq; > u64 power; > @@ -51,19 +52,21 @@ static u64 set_pd_power_limit(struct dtpm *dtpm, u64 power_limit) > cpumask_and(&cpus, cpu_online_mask, to_cpumask(pd->cpus)); > nr_cpus = cpumask_weight(&cpus); > > + table = pd->default_table->state; > + > for (i = 0; i < pd->nr_perf_states; i++) { > > - power = pd->table[i].power * nr_cpus; > + power = table[i].power * nr_cpus; > > if (power > power_limit) > break; > } > > - freq = pd->table[i - 1].frequency; > + freq = table[i - 1].frequency; > > freq_qos_update_request(&dtpm_cpu->qos_req, freq); > > - power_limit = pd->table[i - 1].power * nr_cpus; > + power_limit = table[i - 1].power * nr_cpus; > > return power_limit; > } > @@ -88,12 +91,14 @@ static u64 scale_pd_power_uw(struct cpumask *pd_mask, u64 power) > static u64 get_pd_power_uw(struct dtpm *dtpm) > { > struct dtpm_cpu *dtpm_cpu = to_dtpm_cpu(dtpm); > + struct em_perf_state *table; > struct em_perf_domain *pd; > struct cpumask *pd_mask; > unsigned long freq; > int i; > > pd = em_cpu_get(dtpm_cpu->cpu); > + table = pd->default_table->state; > > pd_mask = em_span_cpus(pd); > > @@ -101,10 +106,10 @@ static u64 get_pd_power_uw(struct dtpm *dtpm) > > for (i = 0; i < pd->nr_perf_states; i++) { > > - if (pd->table[i].frequency < freq) > + if (table[i].frequency < freq) > continue; > > - return scale_pd_power_uw(pd_mask, pd->table[i].power * > + return scale_pd_power_uw(pd_mask, table[i].power * > MICROWATT_PER_MILLIWATT); > } > > @@ -115,17 +120,20 @@ static int update_pd_power_uw(struct dtpm *dtpm) > { > struct dtpm_cpu *dtpm_cpu = to_dtpm_cpu(dtpm); > struct em_perf_domain *em = em_cpu_get(dtpm_cpu->cpu); > + struct em_perf_state *table; > struct cpumask cpus; > int nr_cpus; > > cpumask_and(&cpus, cpu_online_mask, to_cpumask(em->cpus)); > nr_cpus = cpumask_weight(&cpus); > > - dtpm->power_min = em->table[0].power; > + table = em->default_table->state; > + > + dtpm->power_min = table[0].power; > dtpm->power_min *= MICROWATT_PER_MILLIWATT; > dtpm->power_min *= nr_cpus; > > - dtpm->power_max = em->table[em->nr_perf_states - 1].power; > + dtpm->power_max = table[em->nr_perf_states - 1].power; > dtpm->power_max *= MICROWATT_PER_MILLIWATT; > dtpm->power_max *= nr_cpus; > > @@ -182,6 +190,7 @@ static int __dtpm_cpu_setup(int cpu, struct dtpm *parent) > { > struct dtpm_cpu *dtpm_cpu; > struct cpufreq_policy *policy; > + struct em_perf_state *table; > struct em_perf_domain *pd; > char name[CPUFREQ_NAME_LEN]; > int ret = -ENOMEM; > @@ -198,6 +207,8 @@ static int __dtpm_cpu_setup(int cpu, struct dtpm *parent) > if (!pd || em_is_artificial(pd)) > return -EINVAL; > > + table = pd->default_table->state; > + > dtpm_cpu = kzalloc(sizeof(*dtpm_cpu), GFP_KERNEL); > if (!dtpm_cpu) > return -ENOMEM; > @@ -216,7 +227,7 @@ static int __dtpm_cpu_setup(int cpu, struct dtpm *parent) > > ret = freq_qos_add_request(&policy->constraints, > &dtpm_cpu->qos_req, FREQ_QOS_MAX, > - pd->table[pd->nr_perf_states - 1].frequency); > + table[pd->nr_perf_states - 1].frequency); > if (ret) > goto out_dtpm_unregister; > > diff --git a/drivers/powercap/dtpm_devfreq.c b/drivers/powercap/dtpm_devfreq.c > index 91276761a31d..6ef0f2b4a683 100644 > --- a/drivers/powercap/dtpm_devfreq.c > +++ b/drivers/powercap/dtpm_devfreq.c > @@ -37,11 +37,14 @@ static int update_pd_power_uw(struct dtpm *dtpm) > struct devfreq *devfreq = dtpm_devfreq->devfreq; > struct device *dev = devfreq->dev.parent; > struct em_perf_domain *pd = em_pd_get(dev); > + struct em_perf_state *table; > > - dtpm->power_min = pd->table[0].power; > + table = pd->default_table->state; > + > + dtpm->power_min = table[0].power; > dtpm->power_min *= MICROWATT_PER_MILLIWATT; > > - dtpm->power_max = pd->table[pd->nr_perf_states - 1].power; > + dtpm->power_max = table[pd->nr_perf_states - 1].power; > dtpm->power_max *= MICROWATT_PER_MILLIWATT; > > return 0; > @@ -53,22 +56,25 @@ static u64 set_pd_power_limit(struct dtpm *dtpm, u64 power_limit) > struct devfreq *devfreq = dtpm_devfreq->devfreq; > struct device *dev = devfreq->dev.parent; > struct em_perf_domain *pd = em_pd_get(dev); > + struct em_perf_state *table; > unsigned long freq; > u64 power; > int i; > > + table = pd->default_table->state; > + > for (i = 0; i < pd->nr_perf_states; i++) { > > - power = pd->table[i].power * MICROWATT_PER_MILLIWATT; > + power = table[i].power * MICROWATT_PER_MILLIWATT; > if (power > power_limit) > break; > } > > - freq = pd->table[i - 1].frequency; > + freq = table[i - 1].frequency; > > dev_pm_qos_update_request(&dtpm_devfreq->qos_req, freq); > > - power_limit = pd->table[i - 1].power * MICROWATT_PER_MILLIWATT; > + power_limit = table[i - 1].power * MICROWATT_PER_MILLIWATT; > > return power_limit; > } > @@ -94,6 +100,7 @@ static u64 get_pd_power_uw(struct dtpm *dtpm) > struct device *dev = devfreq->dev.parent; > struct em_perf_domain *pd = em_pd_get(dev); > struct devfreq_dev_status status; > + struct em_perf_state *table; > unsigned long freq; > u64 power; > int i; > @@ -102,15 +109,17 @@ static u64 get_pd_power_uw(struct dtpm *dtpm) > status = devfreq->last_status; > mutex_unlock(&devfreq->lock); > > + table = pd->default_table->state; > + > freq = DIV_ROUND_UP(status.current_frequency, HZ_PER_KHZ); > _normalize_load(&status); > > for (i = 0; i < pd->nr_perf_states; i++) { > > - if (pd->table[i].frequency < freq) > + if (table[i].frequency < freq) > continue; > > - power = pd->table[i].power * MICROWATT_PER_MILLIWATT; > + power = table[i].power * MICROWATT_PER_MILLIWATT; > power *= status.busy_time; > power >>= 10; > > diff --git a/drivers/thermal/cpufreq_cooling.c b/drivers/thermal/cpufreq_cooling.c > index e2cc7bd30862..d468aca241e2 100644 > --- a/drivers/thermal/cpufreq_cooling.c > +++ b/drivers/thermal/cpufreq_cooling.c > @@ -91,10 +91,11 @@ struct cpufreq_cooling_device { > static unsigned long get_level(struct cpufreq_cooling_device *cpufreq_cdev, > unsigned int freq) > { > + struct em_perf_state *table = cpufreq_cdev->em->default_table->state; > int i; > > for (i = cpufreq_cdev->max_level - 1; i >= 0; i--) { > - if (freq > cpufreq_cdev->em->table[i].frequency) > + if (freq > table[i].frequency) > break; > } > > @@ -104,15 +105,16 @@ static unsigned long get_level(struct cpufreq_cooling_device *cpufreq_cdev, > static u32 cpu_freq_to_power(struct cpufreq_cooling_device *cpufreq_cdev, > u32 freq) > { > + struct em_perf_state *table = cpufreq_cdev->em->default_table->state; > unsigned long power_mw; > int i; > > for (i = cpufreq_cdev->max_level - 1; i >= 0; i--) { > - if (freq > cpufreq_cdev->em->table[i].frequency) > + if (freq > table[i].frequency) > break; > } > > - power_mw = cpufreq_cdev->em->table[i + 1].power; > + power_mw = table[i + 1].power; > power_mw /= MICROWATT_PER_MILLIWATT; > > return power_mw; > @@ -121,18 +123,19 @@ static u32 cpu_freq_to_power(struct cpufreq_cooling_device *cpufreq_cdev, > static u32 cpu_power_to_freq(struct cpufreq_cooling_device *cpufreq_cdev, > u32 power) > { > + struct em_perf_state *table = cpufreq_cdev->em->default_table->state; > unsigned long em_power_mw; > int i; > > for (i = cpufreq_cdev->max_level; i > 0; i--) { > /* Convert EM power to milli-Watts to make safe comparison */ > - em_power_mw = cpufreq_cdev->em->table[i].power; > + em_power_mw = table[i].power; > em_power_mw /= MICROWATT_PER_MILLIWATT; > if (power >= em_power_mw) > break; > } > > - return cpufreq_cdev->em->table[i].frequency; > + return table[i].frequency; > } > > /** > @@ -262,8 +265,9 @@ static int cpufreq_get_requested_power(struct thermal_cooling_device *cdev, > static int cpufreq_state2power(struct thermal_cooling_device *cdev, > unsigned long state, u32 *power) > { > - unsigned int freq, num_cpus, idx; > struct cpufreq_cooling_device *cpufreq_cdev = cdev->devdata; > + unsigned int freq, num_cpus, idx; > + struct em_perf_state *table; > > /* Request state should be less than max_level */ > if (state > cpufreq_cdev->max_level) > @@ -271,8 +275,9 @@ static int cpufreq_state2power(struct thermal_cooling_device *cdev, > > num_cpus = cpumask_weight(cpufreq_cdev->policy->cpus); > > + table = cpufreq_cdev->em->default_table->state; > idx = cpufreq_cdev->max_level - state; > - freq = cpufreq_cdev->em->table[idx].frequency; > + freq = table[idx].frequency; > *power = cpu_freq_to_power(cpufreq_cdev, freq) * num_cpus; > > return 0; > @@ -378,8 +383,11 @@ static unsigned int get_state_freq(struct cpufreq_cooling_device *cpufreq_cdev, > #ifdef CONFIG_THERMAL_GOV_POWER_ALLOCATOR > /* Use the Energy Model table if available */ > if (cpufreq_cdev->em) { > + struct em_perf_state *table; > + > + table = cpufreq_cdev->em->default_table->state; > idx = cpufreq_cdev->max_level - state; > - return cpufreq_cdev->em->table[idx].frequency; > + return table[idx].frequency; > } > #endif > > diff --git a/drivers/thermal/devfreq_cooling.c b/drivers/thermal/devfreq_cooling.c > index 262e62ab6cf2..4207ef850582 100644 > --- a/drivers/thermal/devfreq_cooling.c > +++ b/drivers/thermal/devfreq_cooling.c > @@ -87,6 +87,7 @@ static int devfreq_cooling_set_cur_state(struct thermal_cooling_device *cdev, > struct devfreq_cooling_device *dfc = cdev->devdata; > struct devfreq *df = dfc->devfreq; > struct device *dev = df->dev.parent; > + struct em_perf_state *table; > unsigned long freq; > int perf_idx; > > @@ -99,8 +100,9 @@ static int devfreq_cooling_set_cur_state(struct thermal_cooling_device *cdev, > return -EINVAL; > > if (dfc->em_pd) { > + table = dfc->em_pd->default_table->state; > perf_idx = dfc->max_state - state; > - freq = dfc->em_pd->table[perf_idx].frequency * 1000; > + freq = table[perf_idx].frequency * 1000; > } else { > freq = dfc->freq_table[state]; > } > @@ -123,10 +125,11 @@ static int devfreq_cooling_set_cur_state(struct thermal_cooling_device *cdev, > */ > static int get_perf_idx(struct em_perf_domain *em_pd, unsigned long freq) > { > + struct em_perf_state *table = em_pd->default_table->state; > int i; > > for (i = 0; i < em_pd->nr_perf_states; i++) { > - if (em_pd->table[i].frequency == freq) > + if (table[i].frequency == freq) > return i; > } > > @@ -181,6 +184,7 @@ static int devfreq_cooling_get_requested_power(struct thermal_cooling_device *cd > struct devfreq_cooling_device *dfc = cdev->devdata; > struct devfreq *df = dfc->devfreq; > struct devfreq_dev_status status; > + struct em_perf_state *table; > unsigned long state; > unsigned long freq; > unsigned long voltage; > @@ -192,6 +196,8 @@ static int devfreq_cooling_get_requested_power(struct thermal_cooling_device *cd > > freq = status.current_frequency; > > + table = dfc->em_pd->default_table->state; > + > if (dfc->power_ops && dfc->power_ops->get_real_power) { > voltage = get_voltage(df, freq); > if (voltage == 0) { > @@ -204,7 +210,7 @@ static int devfreq_cooling_get_requested_power(struct thermal_cooling_device *cd > state = dfc->capped_state; > > /* Convert EM power into milli-Watts first */ > - dfc->res_util = dfc->em_pd->table[state].power; > + dfc->res_util = table[state].power; > dfc->res_util /= MICROWATT_PER_MILLIWATT; > > dfc->res_util *= SCALE_ERROR_MITIGATION; > @@ -225,7 +231,7 @@ static int devfreq_cooling_get_requested_power(struct thermal_cooling_device *cd > _normalize_load(&status); > > /* Convert EM power into milli-Watts first */ > - *power = dfc->em_pd->table[perf_idx].power; > + *power = table[perf_idx].power; > *power /= MICROWATT_PER_MILLIWATT; > /* Scale power for utilization */ > *power *= status.busy_time; > @@ -245,13 +251,15 @@ static int devfreq_cooling_state2power(struct thermal_cooling_device *cdev, > unsigned long state, u32 *power) > { > struct devfreq_cooling_device *dfc = cdev->devdata; > + struct em_perf_state *table; > int perf_idx; > > if (state > dfc->max_state) > return -EINVAL; > > + table = dfc->em_pd->default_table->state; > perf_idx = dfc->max_state - state; > - *power = dfc->em_pd->table[perf_idx].power; > + *power = table[perf_idx].power; > *power /= MICROWATT_PER_MILLIWATT; > > return 0; > @@ -264,6 +272,7 @@ static int devfreq_cooling_power2state(struct thermal_cooling_device *cdev, > struct devfreq *df = dfc->devfreq; > struct devfreq_dev_status status; > unsigned long freq, em_power_mw; > + struct em_perf_state *table; > s32 est_power; > int i; > > @@ -273,6 +282,8 @@ static int devfreq_cooling_power2state(struct thermal_cooling_device *cdev, > > freq = status.current_frequency; > > + table = dfc->em_pd->default_table->state; > + > if (dfc->power_ops && dfc->power_ops->get_real_power) { > /* Scale for resource utilization */ > est_power = power * dfc->res_util; > @@ -290,7 +301,7 @@ static int devfreq_cooling_power2state(struct thermal_cooling_device *cdev, > */ > for (i = dfc->max_state; i > 0; i--) { > /* Convert EM power to milli-Watts to make safe comparison */ > - em_power_mw = dfc->em_pd->table[i].power; > + em_power_mw = table[i].power; > em_power_mw /= MICROWATT_PER_MILLIWATT; > if (est_power >= em_power_mw) > break; > diff --git a/include/linux/energy_model.h b/include/linux/energy_model.h > index 8069f526c9d8..d236e08e80dc 100644 > --- a/include/linux/energy_model.h > +++ b/include/linux/energy_model.h > @@ -36,9 +36,19 @@ struct em_perf_state { > */ > #define EM_PERF_STATE_INEFFICIENT BIT(0) > > +/** > + * struct em_perf_table - Performance states table > + * @state: List of performance states, in ascending order > + * @rcu: RCU used for safe access and destruction > + */ > +struct em_perf_table { > + struct em_perf_state *state; > + struct rcu_head rcu; There is no explanation of the role of this rcu_head in the changelog or anywhere in this patch. It is also not used as of this patch AFAICS. It would be better to add it when it actually gets used IMV.