From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mx0a-0031df01.pphosted.com (mx0a-0031df01.pphosted.com [205.220.168.131]) (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 E7693264A9D for ; Thu, 2 Apr 2026 06:52:16 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=205.220.168.131 ARC-Seal:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1775112738; cv=none; b=eBETNIXOjiDaFG9dVkIAAxX+7DFpYBKy8Sxl+uXDNsa7Z3D5TmELOndnK85krWz4b4XDqBVHfttgWti6FhEDEvD2xmzQ0C4hEP9ROttLK6wBFHRycbOLQYsZhHZYQb5ThIwgJLtqfuvh1x8bcMLZLvsCVdkurtotYOEPLPFuiNI= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1775112738; c=relaxed/simple; bh=xRrX7+ChFARFJjvSnOyf/XVz+ekF01zG2RHavVcSjLI=; h=Message-ID:Date:MIME-Version:Subject:To:Cc:References:From: In-Reply-To:Content-Type; b=STBAgprHhpE/+bh6LlLErVaWZTU+U4JjyepAteOaKxGth5vdRRUWPoo7QKZ3Xlld8ZSBz2Nxs+S94NJ91BXTg9XN+ALt8Fprdh0jRTQZLHAqkQtC+ZnKtMs4MDv82MulMKVw5zzGpMoaZX7ZEX3IH5PiHRjiHNuNd3jx06A7wcQ= ARC-Authentication-Results:i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=oss.qualcomm.com; spf=pass smtp.mailfrom=oss.qualcomm.com; dkim=pass (2048-bit key) header.d=qualcomm.com header.i=@qualcomm.com header.b=BRPEIKaR; dkim=pass (2048-bit key) header.d=oss.qualcomm.com header.i=@oss.qualcomm.com header.b=bjVZ+DJt; arc=none smtp.client-ip=205.220.168.131 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=oss.qualcomm.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=oss.qualcomm.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=qualcomm.com header.i=@qualcomm.com header.b="BRPEIKaR"; dkim=pass (2048-bit key) header.d=oss.qualcomm.com header.i=@oss.qualcomm.com header.b="bjVZ+DJt" Received: from pps.filterd (m0279862.ppops.net [127.0.0.1]) by mx0a-0031df01.pphosted.com (8.18.1.11/8.18.1.11) with ESMTP id 6324QxTL1551728 for ; Thu, 2 Apr 2026 06:52:16 GMT DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=qualcomm.com; h= cc:content-transfer-encoding:content-type:date:from:in-reply-to :message-id:mime-version:references:subject:to; s=qcppdkim1; bh= jTYcWIhFz0PjRYqf7rrSJdqYU6hbKED5h78gJAgGLmg=; b=BRPEIKaRTCfFaUaC OSajXchS1lk7vuYD7ZNHbkhCC5Qt+2bGMYDL3udopUGNXJOsTN2t8df8g3pFgLkP JVTIiqugaIiY74yOjlav/LH2su0hNn8v8PQto29aifYvS/OJUkPA/4orQvTwYpGR AXlr06HPcX2udTCTYJVw5pL/rgUAvpfG9kXCC+h9u3dUJy0/w6P1+DasYEVWUBl+ 0R2vMc8NomO+KhtS1VZVMCzbM4OPwxV9a+0pM9HPgiIwgat84XrvcFwu3KzwRy11 Kp1MkffG/6HnSU85nXK88KWYFusvVZ3EnEKtchZYx2jHeMhO0PxPV0Fy7PQaY/wA W69BYQ== Received: from mail-pg1-f199.google.com (mail-pg1-f199.google.com [209.85.215.199]) by mx0a-0031df01.pphosted.com (PPS) with ESMTPS id 4d9heergnc-1 (version=TLSv1.3 cipher=TLS_AES_128_GCM_SHA256 bits=128 verify=NOT) for ; Thu, 02 Apr 2026 06:52:16 +0000 (GMT) Received: by mail-pg1-f199.google.com with SMTP id 41be03b00d2f7-c741f038f7cso289875a12.2 for ; Wed, 01 Apr 2026 23:52:16 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=oss.qualcomm.com; s=google; t=1775112735; x=1775717535; darn=vger.kernel.org; h=content-transfer-encoding:in-reply-to:from:content-language :references:cc:to:subject:user-agent:mime-version:date:message-id :from:to:cc:subject:date:message-id:reply-to; bh=jTYcWIhFz0PjRYqf7rrSJdqYU6hbKED5h78gJAgGLmg=; b=bjVZ+DJtwMlxz0/eyt3lVcXzmEoSaulWBsTpRCQ9JBrubx0AIztQEp/wm8aKsFfLLE XPjF1lYmC2hZguHkyNgAQxfczTlm5LCzLq/JV1g7biNqDosx570s2g/z6z+17hPQ5jBo E36LW5W0+cTevtVav0Ym73IXi+13uMgvItiMd+gZTG8N5nqEPXvyakPEgztQb5cTfRMT EsRDlsGzNlaTOh5br1ZGywHruzgPa75a53P+zvF1K5fzFQ7jLeJfVwXOepXsv1SyhjCY 34JQv74jCkV11F5N71Y+QU7Rc0qyFzMLY5a/sBvUdhU3YqxIDI+dpsCijTgHtsTHAsKy GbZQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1775112735; x=1775717535; h=content-transfer-encoding:in-reply-to:from:content-language :references:cc:to:subject:user-agent:mime-version:date:message-id :x-gm-gg:x-gm-message-state:from:to:cc:subject:date:message-id :reply-to; bh=jTYcWIhFz0PjRYqf7rrSJdqYU6hbKED5h78gJAgGLmg=; b=jE+5wYinB12rASDdOmeQtmuSPtkTJ3qGI5M3uMXiJbaFNu41JPyo1deABfqZV1DErC lc3mrL7bp4iMCg0xppJzxl4gJQeCDFbHo4qy79JENhabFD+jMgSNe3oEEVVhI2ABE0BJ 2JIi3FEQwNeuvYdtswiu0Jk+bmGsc5AhJ/QaYVpMukL25NATDy6nSvgAvHGsKtO+RQhM OKLHOEfV9Spw8v3+0h25iRmlgHtVFqoYNZv27JneTa2bMfoOS+fh720u9gE5gc34s+K8 PkxJ/zZRhwEuZjqICna1H0EJtNRl437yV7qZtkP4IBQK0skjmIV5zfYAAaVvF9G1bl/Y ut0w== X-Forwarded-Encrypted: i=1; AJvYcCVA653bkVq3nmy8J5KpwJfvtB4e3wFEHXP/yCHZleirr3ZXW35NQMRTAP2e9JoK/qTbcdnuD8IkwS315yc=@vger.kernel.org X-Gm-Message-State: AOJu0YwJxVKcV4O3yosNY37XvJP0oplZnqZVMQoF8rsA7Hc+LC71BYOV EcgIVhNJDTtqkdEqa319u4cZuU36q0XgZZmH5ZPMGcwy0PPB47CP7KSXVZOH3dv3Tbc1TU7+hch Votfull/oQ52gpFlI4I/wVsafNF4mfcjlNqDWB9+LKHEQYysBKVBr4vfw7Dv+R32w4QaPb3j5cS RS0g== X-Gm-Gg: ATEYQzwDptOI/YF3DDU/puvYjoYFuTauiaWRtvvbB1sFcOCOUBTyhnRKDuY2mr8BGO5 xOQE1bVtJCjFryE5Jhg069koecdL5y314aRQAN2mnZqSkxkP6EWndzjkfBnBlbCRsGE8smJTZb3 FnzqV6ZuPWMHw4oTVVlkqORO//XmY1QVKUxv2patRZV9TXQRX2PeX9Wm/AMwR9RZzInw53B5Hhz uUtj4K2kpKtsrOoZqddN6O9VOMOkDrd8BSS72h33mPrUxi3WdtIxSJn8e3UggMvTabyw35byxak Dgc0xzWww0MDjohc3c90LnjaLIDHgvBPoBh8bfqAcT62IjpVXoqk0ym0mKCSfM5w9MyNevkuJ9U u5q1fHy/qz3AUIHRjgFxvHVe/ZAQsJLR3A1pKvpsiJ1MWcu25XMgobSPiZnjorXdGnJkzVMz1du KR4zHu48QT2/74gEDoHQ== X-Received: by 2002:a05:6a20:e293:b0:39b:e1e5:a101 with SMTP id adf61e73a8af0-39ef76f86a9mr6904823637.43.1775112735179; Wed, 01 Apr 2026 23:52:15 -0700 (PDT) X-Received: by 2002:a05:6a20:e293:b0:39b:e1e5:a101 with SMTP id adf61e73a8af0-39ef76f86a9mr6904789637.43.1775112734604; Wed, 01 Apr 2026 23:52:14 -0700 (PDT) Received: from [10.133.33.151] (tpe-colo-wan-fw-bordernet.qualcomm.com. [103.229.16.4]) by smtp.gmail.com with ESMTPSA id d2e1a72fcca58-82cf9b3ccc8sm2469676b3a.19.2026.04.01.23.52.06 (version=TLS1_3 cipher=TLS_AES_128_GCM_SHA256 bits=128/128); Wed, 01 Apr 2026 23:52:13 -0700 (PDT) Message-ID: <543e5567-2c8b-479a-8edf-a827d0637b93@oss.qualcomm.com> Date: Thu, 2 Apr 2026 14:52:04 +0800 Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 User-Agent: Mozilla Thunderbird Subject: Re: [PATCH v4 2/2] cpufreq: Pass the policy to cpufreq_driver->adjust_perf() To: K Prateek Nayak , "Rafael J. Wysocki" , Viresh Kumar , Huang Rui , "Gautham R. Shenoy" , Mario Limonciello , Sebastian Andrzej Siewior , Clark Williams , Steven Rostedt , Srinivas Pandruvada , Len Brown , Ingo Molnar , Peter Zijlstra , Juri Lelli , Vincent Guittot , Miguel Ojeda Cc: Perry Yuan , linux-pm@vger.kernel.org, linux-kernel@vger.kernel.org, rust-for-linux@vger.kernel.org, linux-rt-devel@lists.linux.dev, Dietmar Eggemann , Ben Segall , Mel Gorman , Valentin Schneider , Boqun Feng , Gary Guo , =?UTF-8?Q?Bj=C3=B6rn_Roy_Baron?= , Benno Lossin , Andreas Hindborg , Alice Ryhl , Trevor Gross , Danilo Krummrich , Bert Karwatzki , zhongqiu.han@oss.qualcomm.com References: <20260316081849.19368-1-kprateek.nayak@amd.com> <20260316081849.19368-3-kprateek.nayak@amd.com> Content-Language: en-US From: Zhongqiu Han In-Reply-To: <20260316081849.19368-3-kprateek.nayak@amd.com> Content-Type: text/plain; charset=UTF-8; format=flowed Content-Transfer-Encoding: 7bit X-Proofpoint-ORIG-GUID: EUTnRC-Z8XsMGdMIunOivoPDDs2HxzvB X-Authority-Analysis: v=2.4 cv=VY36/Vp9 c=1 sm=1 tr=0 ts=69ce1220 cx=c_pps a=Oh5Dbbf/trHjhBongsHeRQ==:117 a=nuhDOHQX5FNHPW3J6Bj6AA==:17 a=IkcTkHD0fZMA:10 a=A5OVakUREuEA:10 a=s4-Qcg_JpJYA:10 a=VkNPw1HP01LnGYTKEx00:22 a=u7WPNUs3qKkmUXheDGA7:22 a=_K5XuSEh1TEqbUxoQ0s3:22 a=VwQbUJbxAAAA:8 a=KKAkSRfTAAAA:8 a=zd2uoN0lAAAA:8 a=EUspDBNiAAAA:8 a=50MYKZWsfa7X8wndP2cA:9 a=QEXdDO2ut3YA:10 a=_Vgx9l1VpLgwpw_dHYaR:22 a=cvBusfyB2V15izCimMoJ:22 X-Proofpoint-GUID: EUTnRC-Z8XsMGdMIunOivoPDDs2HxzvB X-Proofpoint-Spam-Details-Enc: AW1haW4tMjYwNDAyMDA1OSBTYWx0ZWRfX2aqS7BrAKQw/ FkuDi0ysWQnQCD078I2EzRe9In5spO7gqr1/47M4dXcGCacUQR6fL4U9p08od5pbf8RYIAdx7OX j1WA08oghhu9PoBPPIvdatdQl64sCNb5wlGv7HWf6dP9/LAnYMbmhU/vmylODNjCpM5s+6M093o gYLM9IxkSDGaq7DC0vsywUkrap7yAH1OpIKLveIpxsbdNqR5tAmvqrLrT2l3479h08xhHSfm+YT FVhpGqR6dciUWU7VohrhGyanAlIK3ugmYZgxzoOGZY+LvQjGxYtkIjR9A3LkLkG+RQz+3+wSiKG w6pOHH1N7qToGorxW0+YSv2cxktbLyv/xwT+5/u3nVq4OWCTiWZ6oLSuKjOQp6Va8OUb4XvmAEP rDBjKI5Ps2eyyS8xzNTUF3N8kr5uWjNB8t3IUkkcMAUcr96Weof+nzWyhvbKeaQv8qOZpGnM0KA dZQp3C6LXdyLDS+mDww== X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.293,Aquarius:18.0.1143,Hydra:6.1.51,FMLib:17.12.100.49 definitions=2026-04-02_01,2026-04-01_02,2025-10-01_01 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 phishscore=0 bulkscore=0 lowpriorityscore=0 clxscore=1015 priorityscore=1501 malwarescore=0 spamscore=0 adultscore=0 impostorscore=0 suspectscore=0 classifier=typeunknown authscore=0 authtc= authcc= route=outbound adjust=0 reason=mlx scancount=1 engine=8.22.0-2603050001 definitions=main-2604020059 On 3/16/2026 4:18 PM, K Prateek Nayak wrote: > cpufreq_cpu_get() can sleep on PREEMPT_RT in presence of concurrent > writer(s), however amd-pstate depends on fetching the cpudata via the > policy's driver data which necessitates grabbing the reference. > > Since schedutil governor can call "cpufreq_driver->update_perf()" > during sched_tick/enqueue/dequeue with rq_lock held and IRQs disabled, > fetching the policy object using the cpufreq_cpu_get() helper in the > scheduler fast-path leads to "BUG: scheduling while atomic" on > PREEMPT_RT [1]. > > Pass the cached cpufreq policy object in sg_policy to the update_perf() > instead of just the CPU. The CPU can be inferred using "policy->cpu". > > The lifetime of cpufreq_policy object outlasts that of the governor and > the cpufreq driver (allocated when the CPU is onlined and only reclaimed > when the CPU is offlined / the CPU device is removed) which makes it > safe to be referenced throughout the governor's lifetime. > > Fixes: 1d215f0319c2 ("cpufreq: amd-pstate: Add fast switch function for AMD P-State") > Reported-by: Bert Karwatzki > Closes:https://lore.kernel.org/all/20250731092316.3191-1-spasswolf@web.de/ [1] > Acked-by: Viresh Kumar > Signed-off-by: K Prateek Nayak > --- > changelog v3..v4: > > o Added the Fixes tag. (Gautham, Chris Mason's review-prompts) > --- > drivers/cpufreq/amd-pstate.c | 3 +-- > drivers/cpufreq/cpufreq.c | 6 +++--- > drivers/cpufreq/intel_pstate.c | 4 ++-- > include/linux/cpufreq.h | 4 ++-- > kernel/sched/cpufreq_schedutil.c | 5 +++-- > rust/kernel/cpufreq.rs | 13 ++++++------- > 6 files changed, 17 insertions(+), 18 deletions(-) > > diff --git a/drivers/cpufreq/amd-pstate.c b/drivers/cpufreq/amd-pstate.c > index 5faccb3d6b14..ad4b5f84773a 100644 > --- a/drivers/cpufreq/amd-pstate.c > +++ b/drivers/cpufreq/amd-pstate.c > @@ -710,13 +710,12 @@ static unsigned int amd_pstate_fast_switch(struct cpufreq_policy *policy, > return policy->cur; > } > > -static void amd_pstate_adjust_perf(unsigned int cpu, > +static void amd_pstate_adjust_perf(struct cpufreq_policy *policy, > unsigned long _min_perf, > unsigned long target_perf, > unsigned long capacity) > { > u8 max_perf, min_perf, des_perf, cap_perf; > - struct cpufreq_policy *policy __free(put_cpufreq_policy) = cpufreq_cpu_get(cpu); > struct amd_cpudata *cpudata; > union perf_cached perf; Original code before the patch: static void amd_pstate_adjust_perf(unsigned int cpu, unsigned long _min_perf, unsigned long target_perf, unsigned long capacity) { u8 max_perf, min_perf, des_perf, cap_perf; struct cpufreq_policy *policy __free(put_cpufreq_policy) = cpufreq_cpu_get(cpu); struct amd_cpudata *cpudata; union perf_cached perf; if (!policy) return; Nit: Post-patch, the policy NULL check should no longer be necessary. Reviewed-by: Zhongqiu Han > > diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c > index 2082a9e4384f..17a5b8e0ea1e 100644 > --- a/drivers/cpufreq/cpufreq.c > +++ b/drivers/cpufreq/cpufreq.c > @@ -2231,7 +2231,7 @@ EXPORT_SYMBOL_GPL(cpufreq_driver_fast_switch); > > /** > * cpufreq_driver_adjust_perf - Adjust CPU performance level in one go. > - * @cpu: Target CPU. > + * @policy: cpufreq policy object of the target CPU. > * @min_perf: Minimum (required) performance level (units of @capacity). > * @target_perf: Target (desired) performance level (units of @capacity). > * @capacity: Capacity of the target CPU. > @@ -2250,12 +2250,12 @@ EXPORT_SYMBOL_GPL(cpufreq_driver_fast_switch); > * parallel with either ->target() or ->target_index() or ->fast_switch() for > * the same CPU. > */ > -void cpufreq_driver_adjust_perf(unsigned int cpu, > +void cpufreq_driver_adjust_perf(struct cpufreq_policy *policy, > unsigned long min_perf, > unsigned long target_perf, > unsigned long capacity) > { > - cpufreq_driver->adjust_perf(cpu, min_perf, target_perf, capacity); > + cpufreq_driver->adjust_perf(policy, min_perf, target_perf, capacity); > } > > /** > diff --git a/drivers/cpufreq/intel_pstate.c b/drivers/cpufreq/intel_pstate.c > index 51938c5a47ca..1552b2d32a34 100644 > --- a/drivers/cpufreq/intel_pstate.c > +++ b/drivers/cpufreq/intel_pstate.c > @@ -3239,12 +3239,12 @@ static unsigned int intel_cpufreq_fast_switch(struct cpufreq_policy *policy, > return target_pstate * cpu->pstate.scaling; > } > > -static void intel_cpufreq_adjust_perf(unsigned int cpunum, > +static void intel_cpufreq_adjust_perf(struct cpufreq_policy *policy, > unsigned long min_perf, > unsigned long target_perf, > unsigned long capacity) > { > - struct cpudata *cpu = all_cpu_data[cpunum]; > + struct cpudata *cpu = all_cpu_data[policy->cpu]; > u64 hwp_cap = READ_ONCE(cpu->hwp_cap_cached); > int old_pstate = cpu->pstate.current_pstate; > int cap_pstate, min_pstate, max_pstate, target_pstate; > diff --git a/include/linux/cpufreq.h b/include/linux/cpufreq.h > index cc894fc38971..4317c5a312bd 100644 > --- a/include/linux/cpufreq.h > +++ b/include/linux/cpufreq.h > @@ -372,7 +372,7 @@ struct cpufreq_driver { > * conditions) scale invariance can be disabled, which causes the > * schedutil governor to fall back to the latter. > */ > - void (*adjust_perf)(unsigned int cpu, > + void (*adjust_perf)(struct cpufreq_policy *policy, > unsigned long min_perf, > unsigned long target_perf, > unsigned long capacity); > @@ -617,7 +617,7 @@ struct cpufreq_governor { > /* Pass a target to the cpufreq driver */ > unsigned int cpufreq_driver_fast_switch(struct cpufreq_policy *policy, > unsigned int target_freq); > -void cpufreq_driver_adjust_perf(unsigned int cpu, > +void cpufreq_driver_adjust_perf(struct cpufreq_policy *policy, > unsigned long min_perf, > unsigned long target_perf, > unsigned long capacity); > diff --git a/kernel/sched/cpufreq_schedutil.c b/kernel/sched/cpufreq_schedutil.c > index 153232dd8276..ae9fd211cec1 100644 > --- a/kernel/sched/cpufreq_schedutil.c > +++ b/kernel/sched/cpufreq_schedutil.c > @@ -461,6 +461,7 @@ static void sugov_update_single_perf(struct update_util_data *hook, u64 time, > unsigned int flags) > { > struct sugov_cpu *sg_cpu = container_of(hook, struct sugov_cpu, update_util); > + struct sugov_policy *sg_policy = sg_cpu->sg_policy; > unsigned long prev_util = sg_cpu->util; > unsigned long max_cap; > > @@ -482,10 +483,10 @@ static void sugov_update_single_perf(struct update_util_data *hook, u64 time, > if (sugov_hold_freq(sg_cpu) && sg_cpu->util < prev_util) > sg_cpu->util = prev_util; > > - cpufreq_driver_adjust_perf(sg_cpu->cpu, sg_cpu->bw_min, > + cpufreq_driver_adjust_perf(sg_policy->policy, sg_cpu->bw_min, > sg_cpu->util, max_cap); > > - sg_cpu->sg_policy->last_freq_update_time = time; > + sg_policy->last_freq_update_time = time; > } > > static unsigned int sugov_next_freq_shared(struct sugov_cpu *sg_cpu, u64 time) > diff --git a/rust/kernel/cpufreq.rs b/rust/kernel/cpufreq.rs > index 76faa1ac8501..a83aec198336 100644 > --- a/rust/kernel/cpufreq.rs > +++ b/rust/kernel/cpufreq.rs > @@ -1256,18 +1256,17 @@ impl Registration { > /// # Safety > /// > /// - This function may only be called from the cpufreq C infrastructure. > + /// - The pointer arguments must be valid pointers. > unsafe extern "C" fn adjust_perf_callback( > - cpu: c_uint, > + ptr: *mut bindings::cpufreq_policy, > min_perf: c_ulong, > target_perf: c_ulong, > capacity: c_ulong, > ) { > - // SAFETY: The C API guarantees that `cpu` refers to a valid CPU number. > - let cpu_id = unsafe { CpuId::from_u32_unchecked(cpu) }; > - > - if let Ok(mut policy) = PolicyCpu::from_cpu(cpu_id) { > - T::adjust_perf(&mut policy, min_perf, target_perf, capacity); > - } > + // SAFETY: The `ptr` is guaranteed to be valid by the contract with the C code for the > + // lifetime of `policy`. > + let policy = unsafe { Policy::from_raw_mut(ptr) }; > + T::adjust_perf(policy, min_perf, target_perf, capacity); > } > > /// Driver's `get_intermediate` callback. -- Thx and BRs, Zhongqiu Han