From nobody Sun Oct 5 01:49:55 2025 Received: from mailgw.kylinos.cn (mailgw.kylinos.cn [124.126.103.232]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 5357F14286; Mon, 11 Aug 2025 07:27:21 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=124.126.103.232 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1754897246; cv=none; b=TCeUXj/VL4sUtF9G6IKpHrE4+nsGhBiuBsh5bQ9Zvndk2BkKOocYqLQT2zdJSHRHuLoa9ScQpesKRxeI+n+5GZ5caKsBUxMwtVchJf0Kk7NZy2EvC1ztiqsZ727FD+k4p7ViDVHtUgLcdHG/0yHVCdlDU+xhGzkF48uS1WQNvI0= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1754897246; c=relaxed/simple; bh=Ek71y/Vysl6TXj+/+lo0qw6uZeFpzglWXMM5szs8uNY=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=pgMeUovWbsnKj1Lsu+P0yhTLxozHFwiiisCQa6w2ipaOlfNGRHkoTERqkyj/1d0zG1VK780ysnp7/jyXQA1Uh501YJcXLYmGSBnaoO8f/aksXcGhn+7p6Z8REk35Yxo1MrGg66C+yCran50C8nPoVOx1371SWEfy/y/AeU+T0t4= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=kylinos.cn; spf=pass smtp.mailfrom=kylinos.cn; arc=none smtp.client-ip=124.126.103.232 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=kylinos.cn Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=kylinos.cn X-UUID: 9b02d770768411f0b29709d653e92f7d-20250811 X-CTIC-Tags: HR_CC_COUNT, HR_CC_DOMAIN_COUNT, HR_CC_NAME, HR_CC_NO_NAME, HR_CTE_8B HR_CTT_MISS, HR_DATE_H, HR_DATE_WKD, HR_DATE_ZONE, HR_FROM_NAME HR_SJ_DIGIT_LEN, HR_SJ_LANG, HR_SJ_LEN, HR_SJ_LETTER, HR_SJ_NOR_SYM HR_SJ_PHRASE, HR_SJ_PHRASE_LEN, HR_SJ_WS, HR_TO_COUNT, HR_TO_DOMAIN_COUNT HR_TO_NO_NAME, IP_UNTRUSTED, SRC_UNTRUSTED, IP_UNFAMILIAR, SRC_UNFAMILIAR DN_TRUSTED, SRC_TRUSTED, SA_EXISTED, SN_TRUSTED, SN_EXISTED SPF_NOPASS, DKIM_NOPASS, DMARC_NOPASS, CIE_BAD, CIE_GOOD_SPF CIE_UNKNOWN, GTI_FG_BS, GTI_RG_INFO, GTI_C_BU, AMN_T1 AMN_GOOD, AMN_C_TI, AMN_C_BU, ABX_MISS_RDNS X-CID-P-RULE: Release_Ham X-CID-O-INFO: VERSION:1.1.45,REQID:1c842df1-d979-4189-af2a-00d2b81df130,IP:10, URL:0,TC:0,Content:-5,EDM:0,RT:0,SF:5,FILE:0,BULK:0,RULE:Release_Ham,ACTIO N:release,TS:10 X-CID-INFO: VERSION:1.1.45,REQID:1c842df1-d979-4189-af2a-00d2b81df130,IP:10,UR L:0,TC:0,Content:-5,EDM:0,RT:0,SF:5,FILE:0,BULK:0,RULE:Release_Ham,ACTION: release,TS:10 X-CID-META: VersionHash:6493067,CLOUDID:5cfb0a6c5684ba53816d6312a4afd43e,BulkI D:250811134842PQLSK940,BulkQuantity:1,Recheck:0,SF:19|23|38|43|66|72|74|78 |81|82|102,TC:nil,Content:0|50,EDM:-3,IP:-2,URL:0,File:nil,RT:nil,Bulk:40, QS:nil,BEC:nil,COL:0,OSI:0,OSA:0,AV:0,LES:1,SPR:NO,DKR:0,DKP:0,BRR:0,BRE:0 ,ARC:0 X-CID-BVR: 0 X-CID-BAS: 0,_,0,_ X-CID-FACTOR: TF_CID_SPAM_FSD,TF_CID_SPAM_SNR X-UUID: 9b02d770768411f0b29709d653e92f7d-20250811 X-User: tianyaxiong@kylinos.cn Received: from localhost.localdomain [(106.16.203.49)] by mailgw.kylinos.cn (envelope-from ) (Generic MTA) with ESMTP id 91083289; Mon, 11 Aug 2025 15:27:15 +0800 From: Yaxiong Tian To: rafael@kernel.org, daniel.lezcano@linaro.org, lenb@kernel.org, robert.moore@intel.com Cc: linux-pm@vger.kernel.org, linux-kernel@vger.kernel.org, linux-acpi@vger.kernel.org, acpica-devel@lists.linux.dev, Yaxiong Tian , Shaobo Huang , Yinfeng Wang , Xu Wang Subject: [PATCH 1/2] cpuidle: Add interface to get cpuidle_driver by CPU ID Date: Mon, 11 Aug 2025 15:27:09 +0800 Message-Id: <20250811072709.761961-1-tianyaxiong@kylinos.cn> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20250811072349.753478-1-tianyaxiong@kylinos.cn> References: <20250811072349.753478-1-tianyaxiong@kylinos.cn> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Some drivers need to obtain the cpuidle_driver via CPU ID before the cpuidle_device is registered. Therefore, this interface is added. Tested-by: Shaobo Huang Signed-off-by: Yaxiong Tian Signed-off-by: Shaobo Huang Signed-off-by: Yinfeng Wang Signed-off-by: Xu Wang --- drivers/cpuidle/driver.c | 16 ++++++++++++++++ include/linux/cpuidle.h | 4 ++++ 2 files changed, 20 insertions(+) diff --git a/drivers/cpuidle/driver.c b/drivers/cpuidle/driver.c index 9bbfa594c442..8647f8165863 100644 --- a/drivers/cpuidle/driver.c +++ b/drivers/cpuidle/driver.c @@ -353,6 +353,22 @@ struct cpuidle_driver *cpuidle_get_cpu_driver(struct c= puidle_device *dev) } EXPORT_SYMBOL_GPL(cpuidle_get_cpu_driver); =20 +/** + * cpuidle_get_cpu_driver_by_cpu - return the driver registered for a CPU. + * @cpu_num: a valid cpu num + * + * Returns a struct cpuidle_driver pointer, or NULL if no driver is regist= ered + * for the CPU associated with @cpu. + */ +struct cpuidle_driver *cpuidle_get_cpu_driver_by_cpu(int cpu_num) +{ + if (cpu_num < 0 || cpu_num >=3D nr_cpu_ids) + return NULL; + + return __cpuidle_get_cpu_driver(cpu_num); +} +EXPORT_SYMBOL_GPL(cpuidle_get_cpu_driver_by_cpu); + /** * cpuidle_driver_state_disabled - Disable or enable an idle state * @drv: cpuidle driver owning the state diff --git a/include/linux/cpuidle.h b/include/linux/cpuidle.h index a9ee4fe55dcf..aebbaae6a501 100644 --- a/include/linux/cpuidle.h +++ b/include/linux/cpuidle.h @@ -200,6 +200,7 @@ extern void cpuidle_disable_device(struct cpuidle_devic= e *dev); extern int cpuidle_play_dead(void); =20 extern struct cpuidle_driver *cpuidle_get_cpu_driver(struct cpuidle_device= *dev); +extern struct cpuidle_driver *cpuidle_get_cpu_driver_by_cpu(int cpu_num); static inline struct cpuidle_device *cpuidle_get_device(void) {return __this_cpu_read(cpuidle_devices); } #else @@ -240,6 +241,9 @@ static inline void cpuidle_disable_device(struct cpuidl= e_device *dev) { } static inline int cpuidle_play_dead(void) {return -ENODEV; } static inline struct cpuidle_driver *cpuidle_get_cpu_driver( struct cpuidle_device *dev) {return NULL; } + +static inline struct cpuidle_driver *cpuidle_get_cpu_driver_by_cpu( + int cpu_num) {return NULL; }; static inline struct cpuidle_device *cpuidle_get_device(void) {return NULL= ; } #endif =20 --=20 2.25.1 From nobody Sun Oct 5 01:49:55 2025 Received: from mailgw.kylinos.cn (mailgw.kylinos.cn [124.126.103.232]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id CB94A2D879D; Mon, 11 Aug 2025 07:27:34 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=124.126.103.232 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1754897257; cv=none; b=TW0AVdatX11Y0+xaxrj9cl7BSAu7hyC+sS/JFSFA/3viOZk4Lm27ED26xuJk1783dh4J0pdDCrt+F77q51jtORCq7sQNoy5n+DX5y12Sch49G9nN0taCnyWeAuO1O23Ckvr6495nHKzprD8B5SZGrsB/p5cM5s0GPFRyCw3ezac= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1754897257; c=relaxed/simple; bh=7In0APipBxYztvMciKOwywMsghjmq6Nbt71Lm7V7KOI=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=Sub2jO5SREOZ7Be5qtuEVlyfJZUfizPlq325da1jOa2uQEJyZL5dQsqrIaKCwidCSjPZAGsDjgKM2I7Md1h7rTFoPHI/QC2FGAj3k2d9p85I1mYEClTb3C60rPO4txxfS0yzRHRByFSdSu2VfMS+Zms/YaMKL4gxFOoEEQQ1N4I= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=kylinos.cn; spf=pass smtp.mailfrom=kylinos.cn; arc=none smtp.client-ip=124.126.103.232 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=kylinos.cn Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=kylinos.cn X-UUID: a281b462768411f0b29709d653e92f7d-20250811 X-CTIC-Tags: HR_CC_COUNT, HR_CC_DOMAIN_COUNT, HR_CC_NAME, HR_CC_NO_NAME, HR_CTE_8B HR_CTT_MISS, HR_DATE_H, HR_DATE_WKD, HR_DATE_ZONE, HR_FROM_NAME HR_SJ_DIGIT_LEN, HR_SJ_LANG, HR_SJ_LEN, HR_SJ_LETTER, HR_SJ_NOR_SYM HR_SJ_PHRASE, HR_SJ_PHRASE_LEN, HR_SJ_WS, HR_TO_COUNT, HR_TO_DOMAIN_COUNT HR_TO_NO_NAME, IP_UNTRUSTED, SRC_UNTRUSTED, IP_UNFAMILIAR, SRC_UNFAMILIAR DN_TRUSTED, SRC_TRUSTED, SA_EXISTED, SN_TRUSTED, SN_EXISTED SPF_NOPASS, DKIM_NOPASS, DMARC_NOPASS, CIE_BAD, CIE_GOOD_SPF CIE_UNKNOWN, GTI_FG_BS, GTI_RG_INFO, GTI_C_BU, AMN_T1 AMN_GOOD, AMN_C_TI, AMN_C_BU, ABX_MISS_RDNS X-CID-P-RULE: Release_Ham X-CID-O-INFO: VERSION:1.1.45,REQID:0d026300-57ae-43b8-b99b-ffdbed3ba909,IP:10, URL:0,TC:0,Content:-25,EDM:0,RT:0,SF:5,FILE:0,BULK:0,RULE:Release_Ham,ACTI ON:release,TS:-10 X-CID-INFO: VERSION:1.1.45,REQID:0d026300-57ae-43b8-b99b-ffdbed3ba909,IP:10,UR L:0,TC:0,Content:-25,EDM:0,RT:0,SF:5,FILE:0,BULK:0,RULE:Release_Ham,ACTION :release,TS:-10 X-CID-META: VersionHash:6493067,CLOUDID:7e0d3e1ee74fae7613c1de3ccc5d5296,BulkI D:250811152729XBBZWQNU,BulkQuantity:0,Recheck:0,SF:19|23|38|43|66|72|74|78 |81|82|102,TC:nil,Content:0|50,EDM:-3,IP:-2,URL:0,File:nil,RT:nil,Bulk:nil ,QS:nil,BEC:nil,COL:0,OSI:0,OSA:0,AV:0,LES:1,SPR:NO,DKR:0,DKP:0,BRR:0,BRE: 0,ARC:0 X-CID-BVR: 0 X-CID-BAS: 0,_,0,_ X-CID-FACTOR: TF_CID_SPAM_SNR,TF_CID_SPAM_FSD X-UUID: a281b462768411f0b29709d653e92f7d-20250811 X-User: tianyaxiong@kylinos.cn Received: from localhost.localdomain [(106.16.203.49)] by mailgw.kylinos.cn (envelope-from ) (Generic MTA) with ESMTP id 660309298; Mon, 11 Aug 2025 15:27:28 +0800 From: Yaxiong Tian To: rafael@kernel.org, daniel.lezcano@linaro.org, lenb@kernel.org, robert.moore@intel.com Cc: linux-pm@vger.kernel.org, linux-kernel@vger.kernel.org, linux-acpi@vger.kernel.org, acpica-devel@lists.linux.dev, Yaxiong Tian , Shaobo Huang , Yinfeng Wang , Xu Wang Subject: [PATCH 2/2] ACPI: processor: idle: Replace single idle driver with per-CPU model for better hybrid CPU support Date: Mon, 11 Aug 2025 15:27:23 +0800 Message-Id: <20250811072723.762608-1-tianyaxiong@kylinos.cn> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20250811072349.753478-1-tianyaxiong@kylinos.cn> References: <20250811072349.753478-1-tianyaxiong@kylinos.cn> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Current implementations of hybrid architectures (e.g., ARM64 big.LITTLE and Intel Alder Lake) feature CPU cores with different exit latencies. Using a single driver to describe_LPI states for all core types is therefore suboptimal. This is further supported by ACPI specification 8.4.4.1 which states: "In a processor hierarchy, each node has its own _LPI low-power states specific to that node." To address these limitations, we replace the monolithic idle driver with a per-CPU model. This approach enables accurate idle state representat= ion for each core type Tested-by: Shaobo Huang Signed-off-by: Yaxiong Tian Signed-off-by: Shaobo Huang Signed-off-by: Yinfeng Wang Signed-off-by: Xu Wang --- drivers/acpi/Kconfig | 1 + drivers/acpi/processor_driver.c | 3 +- drivers/acpi/processor_idle.c | 60 ++++++++++++++++----------------- include/acpi/processor.h | 2 +- 4 files changed, 34 insertions(+), 32 deletions(-) diff --git a/drivers/acpi/Kconfig b/drivers/acpi/Kconfig index ca00a5dbcf75..d92c0faca978 100644 --- a/drivers/acpi/Kconfig +++ b/drivers/acpi/Kconfig @@ -276,6 +276,7 @@ config ACPI_PROCESSOR_CSTATE config ACPI_PROCESSOR_IDLE bool select CPU_IDLE + select CPU_IDLE_MULTIPLE_DRIVERS =20 config ACPI_MCFG bool diff --git a/drivers/acpi/processor_driver.c b/drivers/acpi/processor_drive= r.c index 65e779be64ff..22db9c904437 100644 --- a/drivers/acpi/processor_driver.c +++ b/drivers/acpi/processor_driver.c @@ -166,7 +166,8 @@ static int __acpi_processor_start(struct acpi_device *d= evice) if (result && !IS_ENABLED(CONFIG_ACPI_CPU_FREQ_PSS)) dev_dbg(&device->dev, "CPPC data invalid or not present\n"); =20 - if (!cpuidle_get_driver() || cpuidle_get_driver() =3D=3D &acpi_idle_drive= r) + if (!cpuidle_get_cpu_driver_by_cpu(pr->id) || cpuidle_get_cpu_driver_by_c= pu(pr->id) + =3D=3D per_cpu_ptr(&acpi_idle_driver, pr->id)) acpi_processor_power_init(pr); =20 acpi_pss_perf_init(pr); diff --git a/drivers/acpi/processor_idle.c b/drivers/acpi/processor_idle.c index 2c2dc559e0f8..4922110da0bf 100644 --- a/drivers/acpi/processor_idle.c +++ b/drivers/acpi/processor_idle.c @@ -51,15 +51,12 @@ module_param(latency_factor, uint, 0644); =20 static DEFINE_PER_CPU(struct cpuidle_device *, acpi_cpuidle_device); =20 -struct cpuidle_driver acpi_idle_driver =3D { - .name =3D "acpi_idle", - .owner =3D THIS_MODULE, -}; +DEFINE_PER_CPU(struct cpuidle_driver, acpi_idle_driver); =20 #ifdef CONFIG_ACPI_PROCESSOR_CSTATE void acpi_idle_rescan_dead_smt_siblings(void) { - if (cpuidle_get_driver() =3D=3D &acpi_idle_driver) + if (cpuidle_get_driver() =3D=3D this_cpu_ptr(&acpi_idle_driver)) arch_cpu_rescan_dead_smt_siblings(); } =20 @@ -738,12 +735,13 @@ static int acpi_processor_setup_cpuidle_cx(struct acp= i_processor *pr, int i, count =3D ACPI_IDLE_STATE_START; struct acpi_processor_cx *cx; struct cpuidle_state *state; + struct cpuidle_driver *drv =3D per_cpu_ptr(&acpi_idle_driver, pr->id); =20 if (max_cstate =3D=3D 0) max_cstate =3D 1; =20 for (i =3D 1; i < ACPI_PROCESSOR_MAX_POWER && i <=3D max_cstate; i++) { - state =3D &acpi_idle_driver.states[count]; + state =3D &drv->states[count]; cx =3D &pr->power.states[i]; =20 if (!cx->valid) @@ -776,7 +774,7 @@ static int acpi_processor_setup_cstates(struct acpi_pro= cessor *pr) int i, count; struct acpi_processor_cx *cx; struct cpuidle_state *state; - struct cpuidle_driver *drv =3D &acpi_idle_driver; + struct cpuidle_driver *drv =3D per_cpu_ptr(&acpi_idle_driver, pr->id); =20 if (max_cstate =3D=3D 0) max_cstate =3D 1; @@ -1198,7 +1196,7 @@ static int acpi_processor_setup_lpi_states(struct acp= i_processor *pr) int i; struct acpi_lpi_state *lpi; struct cpuidle_state *state; - struct cpuidle_driver *drv =3D &acpi_idle_driver; + struct cpuidle_driver *drv =3D per_cpu_ptr(&acpi_idle_driver, pr->id); =20 if (!pr->flags.has_lpi) return -EOPNOTSUPP; @@ -1232,7 +1230,7 @@ static int acpi_processor_setup_lpi_states(struct acp= i_processor *pr) static int acpi_processor_setup_cpuidle_states(struct acpi_processor *pr) { int i; - struct cpuidle_driver *drv =3D &acpi_idle_driver; + struct cpuidle_driver *drv =3D per_cpu_ptr(&acpi_idle_driver, pr->id); =20 if (!pr->flags.power_setup_done || !pr->flags.power) return -EINVAL; @@ -1316,13 +1314,7 @@ int acpi_processor_power_state_has_changed(struct ac= pi_processor *pr) if (!pr->flags.power_setup_done) return -ENODEV; =20 - /* - * FIXME: Design the ACPI notification to make it once per - * system instead of once per-cpu. This condition is a hack - * to make the code that updates C-States be called once. - */ - - if (pr->id =3D=3D 0 && cpuidle_get_driver() =3D=3D &acpi_idle_driver) { + if (cpuidle_get_cpu_driver_by_cpu(pr->id) =3D=3D per_cpu_ptr(&acpi_idle_d= river, pr->id)) { =20 /* Protect against cpu-hotplug */ cpus_read_lock(); @@ -1360,12 +1352,14 @@ int acpi_processor_power_state_has_changed(struct a= cpi_processor *pr) return 0; } =20 -static int acpi_processor_registered; =20 int acpi_processor_power_init(struct acpi_processor *pr) { int retval; + struct cpumask *cpumask; struct cpuidle_device *dev; + struct cpuidle_driver *drv =3D per_cpu_ptr(&acpi_idle_driver, pr->id); + =20 if (disabled_by_idle_boot_param()) return 0; @@ -1382,14 +1376,21 @@ int acpi_processor_power_init(struct acpi_processor= *pr) */ if (pr->flags.power) { /* Register acpi_idle_driver if not already registered */ - if (!acpi_processor_registered) { - acpi_processor_setup_cpuidle_states(pr); - retval =3D cpuidle_register_driver(&acpi_idle_driver); - if (retval) - return retval; - pr_debug("%s registered with cpuidle\n", - acpi_idle_driver.name); + acpi_processor_setup_cpuidle_states(pr); + + drv->name =3D "acpi_idle"; + drv->owner =3D THIS_MODULE; + cpumask =3D kzalloc(cpumask_size(), GFP_KERNEL); + cpumask_set_cpu(pr->id, cpumask); + drv->cpumask =3D cpumask; + + retval =3D cpuidle_register_driver(drv); + if (retval) { + kfree(cpumask); + return retval; } + pr_debug("cpu %d:%s registered with cpuidle\n", pr->id, + drv->name); =20 dev =3D kzalloc(sizeof(*dev), GFP_KERNEL); if (!dev) @@ -1403,11 +1404,10 @@ int acpi_processor_power_init(struct acpi_processor= *pr) */ retval =3D cpuidle_register_device(dev); if (retval) { - if (acpi_processor_registered =3D=3D 0) - cpuidle_unregister_driver(&acpi_idle_driver); + cpuidle_unregister_driver(drv); + kfree(cpumask); return retval; } - acpi_processor_registered++; } return 0; } @@ -1415,17 +1415,17 @@ int acpi_processor_power_init(struct acpi_processor= *pr) int acpi_processor_power_exit(struct acpi_processor *pr) { struct cpuidle_device *dev =3D per_cpu(acpi_cpuidle_device, pr->id); + struct cpuidle_driver *drv =3D per_cpu_ptr(&acpi_idle_driver, pr->id); =20 if (disabled_by_idle_boot_param()) return 0; =20 if (pr->flags.power) { cpuidle_unregister_device(dev); - acpi_processor_registered--; - if (acpi_processor_registered =3D=3D 0) - cpuidle_unregister_driver(&acpi_idle_driver); + cpuidle_unregister_driver(drv); =20 kfree(dev); + kfree(drv->cpumask); } =20 pr->flags.power_setup_done =3D 0; diff --git a/include/acpi/processor.h b/include/acpi/processor.h index d0eccbd920e5..36940c6b96cc 100644 --- a/include/acpi/processor.h +++ b/include/acpi/processor.h @@ -417,7 +417,7 @@ static inline void acpi_processor_throttling_init(void)= {} #endif /* CONFIG_ACPI_CPU_FREQ_PSS */ =20 /* in processor_idle.c */ -extern struct cpuidle_driver acpi_idle_driver; +DECLARE_PER_CPU(struct cpuidle_driver, acpi_idle_driver); #ifdef CONFIG_ACPI_PROCESSOR_IDLE int acpi_processor_power_init(struct acpi_processor *pr); int acpi_processor_power_exit(struct acpi_processor *pr); --=20 2.25.1