From nobody Tue Jun 16 11:42:59 2026 Received: from mail-pg1-f177.google.com (mail-pg1-f177.google.com [209.85.215.177]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 31DCF175A6C for ; Sun, 19 Apr 2026 08:08:49 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.215.177 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1776586133; cv=none; b=jg8OTaGJY7HOTUrR9GLQXOOEP772cP8inHPqo3Jxo+K/TIete8KnFo2gbyeEK0BtoU2Y1UHOEKqN8nck2gVOGuEa+0XdbkEueEzaayX6RSdJkc3tLuzDa+Cpb6tADPEj1JTDCJwyeLge9h9lvfSqta67wNdjMitn7vGkqR31n2Y= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1776586133; c=relaxed/simple; bh=OCi9nDDPRNt+0Tt22m27NOerlt18eeVeDVdbhOVkDFA=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version:Content-Type; b=LbFoUVuOosWtsqWqOKO24xNcFGrvp0rnMGoccwEd1oNN41gDbW/p7B6AWFo6OhOdzygLpgDGBiDwhs97MTX8jyoxf42Pv6mEQblySI5EuMcDdtqXoQMu2hKh+bfaB6r29IuUpQcDxr/YLoQ5kUAjfFlbqhPq19XQGQf8xiAMizA= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=snu.ac.kr; spf=pass smtp.mailfrom=snu.ac.kr; dkim=pass (1024-bit key) header.d=snu.ac.kr header.i=@snu.ac.kr header.b=jNa41cP5; arc=none smtp.client-ip=209.85.215.177 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=snu.ac.kr Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=snu.ac.kr Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=snu.ac.kr header.i=@snu.ac.kr header.b="jNa41cP5" Received: by mail-pg1-f177.google.com with SMTP id 41be03b00d2f7-c76d797b180so1480386a12.2 for ; Sun, 19 Apr 2026 01:08:49 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=snu.ac.kr; s=google; t=1776586128; x=1777190928; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=xkh8bldvZTdSRdXrrl3UK2Fj0kWohJXGFNjSq2Nw4w4=; b=jNa41cP57MoEmdvofah+K481ZlzR6vLBJz0my5/u3LDfngebYioiBeCprDCpq1YC9n rT+bV2dUTMnJQzJJYLRVKOcEr00H8hJeMSpEDUTWvYJ2OUg5VXtDU5eJpj8JLVWsF4KW 0WLLj9bqOf39JvfKngcPL4DhjPwvVBHlKes30= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1776586128; x=1777190928; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=xkh8bldvZTdSRdXrrl3UK2Fj0kWohJXGFNjSq2Nw4w4=; b=j3gV0MGN+cXiaZQF7addY5hlvZ/MZy2no0IZwUPSD4GuKWBYEMdkaI9M5DcuxN+hVV /keLMK30Z8XFY+mSVaK89bp6p+Y8UP+X4UeSCbUXelXMFoL4s+VqA9JWqXqVggGoDOU4 sxSSQLJxrdQ7FglEvRA+NILh2X2PAK2ZIqco5KHSgH3zmsKPv4j7EQvZrWq/GB8SqCaq TCqKbHubxaJbJ3jjuw8YbhGOVVPnAkQVKVRmA5VciZAjAgVt78Z1PuIqtt8JBT+h0QZI 67SpgehNJethm3stZ8frQgoGjgCJ6D9lrqPF+xvGxDfMPCFdUeWTwzOSeT//fe9nTZRh ZH9Q== X-Forwarded-Encrypted: i=1; AFNElJ/WjzwDUVGlpge5BBPtmXXutcP+qYrHF0Stm8Nib0KV9UZgl9Zoaq+FG6Jhh9GEFOf3gDrSVlako/6t4Iw=@vger.kernel.org X-Gm-Message-State: AOJu0YxkDft70a8K5+ZZZFSavKaS0YZJY1C0P/Hqj2/Pk4nRCkc/Wy4F hnnK/G8qZoT9hqqh2dF14cZbch7olcRUXfs4kUMJz0pCVRaa+tJ6QEr/atCeqf9Qucs= X-Gm-Gg: AeBDieundjL/kudY7f2K85y381tCAlCyixaXbxFu7fEZSzTZd0JT+GZi/QBdwkRQG9U 0r4rsca5CvgS1N61ztcZcscHxQUMHtocJAPPMOZzfL3iyMIcUQrHEd9Rus01bohSE6ONVXbiaVi CcMfLJH+5sScGOar1aIpH7k2advYTEEO5q+KG9/NRJj0y+akmBJ6kyDGwtZ4LSQHAfsq9j84y5T PclBFFKvgAhPJYjmIJnXn6KBtdkrISCrlUfIlGz4liDl6dPd+jDeqCVXvEnxwpA+IyT3i1q3qCo hY3Sgi5swOb4GkmaMEBMgO9Ajvv8oaHfcM4UwySPshm9oASE/cah+rpXGiVkxtHlbHMfUEeHYdO f66rcFJw0wlSdH/a0qiMqwKiXVY5tcaFrkEgQSNzzStcvPJn8ZTo6num1jYTcUjWhcmfjLdd5Lg aAcCIGQc/ECOrOgT1DlpAuo27SaK5HRraldzihiX8hq4kPBQd3EY6U/21/5KRBchXC1/Ekeg== X-Received: by 2002:a05:6a20:6a20:b0:39f:24ad:ad00 with SMTP id adf61e73a8af0-3a08d68d780mr10535341637.7.1776586128576; Sun, 19 Apr 2026 01:08:48 -0700 (PDT) Received: from nunu.. (nunu.snu.ac.kr. [147.46.112.82]) by smtp.gmail.com with ESMTPSA id d2e1a72fcca58-82f8ebb3f31sm8583735b3a.37.2026.04.19.01.08.46 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 19 Apr 2026 01:08:48 -0700 (PDT) From: Sangyun Kim To: ukleinek@kernel.org Cc: nicolas.ferre@microchip.com, alexandre.belloni@bootlin.com, claudiu.beznea@tuxon.dev, linux-pwm@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org Subject: [PATCH v2] pwm: atmel-tcb: Cache clock rates and mark chip as atomic Date: Sun, 19 Apr 2026 17:08:38 +0900 Message-Id: <20260419080838.3192357-1-sangyun.kim@snu.ac.kr> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20260415093433.2359955-1-sangyun.kim@snu.ac.kr> References: <20260415093433.2359955-1-sangyun.kim@snu.ac.kr> 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" atmel_tcb_pwm_apply() holds tcbpwmc->lock as a spinlock via guard(spinlock)() and then calls atmel_tcb_pwm_config(), which calls clk_get_rate() twice. clk_get_rate() acquires clk_prepare_lock (a mutex), so this is a sleep-in-atomic-context violation. On CONFIG_DEBUG_ATOMIC_SLEEP kernels every pwm_apply_state() that enables or reconfigures the PWM triggers a "BUG: sleeping function called from invalid context" warning. Acquire exclusive control over the clock rates with clk_rate_exclusive_get() at probe time and cache the rates in struct atmel_tcb_pwm_chip, then read the cached rates from atmel_tcb_pwm_config(). This keeps the spinlock-based mutual exclusion introduced in commit 37f7707077f5 ("pwm: atmel-tcb: Fix race condition and convert to guards") and removes the sleeping calls from the atomic section. With no sleeping calls left in .apply() and the regmap-mmio bus already running with fast_io=3Dtrue, also mark the chip as atomic so consumers can use pwm_apply_atomic() from atomic context. Fixes: 37f7707077f5 ("pwm: atmel-tcb: Fix race condition and convert to gua= rds") Signed-off-by: Sangyun Kim --- Hi Uwe, Thanks for the review! "Sangyun" is the right form to address me, no worries. Changes in v2: - Keep the spinlock instead of converting tcbpwmc->lock to a mutex. - Cache clk and slow_clk rates at probe via clk_rate_exclusive_get() so the .apply() path no longer calls clk_get_rate() under the spinlock. - Mark the chip as atomic now that .apply() has no sleeping calls. Thanks, Sangyun drivers/pwm/pwm-atmel-tcb.c | 28 +++++++++++++++++++++++++--- 1 file changed, 25 insertions(+), 3 deletions(-) diff --git a/drivers/pwm/pwm-atmel-tcb.c b/drivers/pwm/pwm-atmel-tcb.c index f9a9c12cbcdd..8d46ce28f736 100644 --- a/drivers/pwm/pwm-atmel-tcb.c +++ b/drivers/pwm/pwm-atmel-tcb.c @@ -50,6 +50,8 @@ struct atmel_tcb_pwm_chip { spinlock_t lock; u8 channel; u8 width; + unsigned long rate; + unsigned long slow_rate; struct regmap *regmap; struct clk *clk; struct clk *gclk; @@ -266,7 +268,7 @@ static int atmel_tcb_pwm_config(struct pwm_chip *chip, = struct pwm_device *pwm, int slowclk =3D 0; unsigned period; unsigned duty; - unsigned rate =3D clk_get_rate(tcbpwmc->clk); + unsigned long rate =3D tcbpwmc->rate; unsigned long long min; unsigned long long max; =20 @@ -294,7 +296,7 @@ static int atmel_tcb_pwm_config(struct pwm_chip *chip, = struct pwm_device *pwm, */ if (i =3D=3D ARRAY_SIZE(atmel_tcb_divisors)) { i =3D slowclk; - rate =3D clk_get_rate(tcbpwmc->slow_clk); + rate =3D tcbpwmc->slow_rate; min =3D div_u64(NSEC_PER_SEC, rate); max =3D min << tcbpwmc->width; =20 @@ -431,6 +433,7 @@ static int atmel_tcb_pwm_probe(struct platform_device *= pdev) } =20 chip->ops =3D &atmel_tcb_pwm_ops; + chip->atomic =3D true; tcbpwmc->channel =3D channel; tcbpwmc->width =3D config->counter_width; =20 @@ -438,16 +441,33 @@ static int atmel_tcb_pwm_probe(struct platform_device= *pdev) if (err) goto err_gclk; =20 + err =3D clk_rate_exclusive_get(tcbpwmc->clk); + if (err) + goto err_disable_clk; + + err =3D clk_rate_exclusive_get(tcbpwmc->slow_clk); + if (err) + goto err_clk_unlock; + + tcbpwmc->rate =3D clk_get_rate(tcbpwmc->clk); + tcbpwmc->slow_rate =3D clk_get_rate(tcbpwmc->slow_clk); + spin_lock_init(&tcbpwmc->lock); =20 err =3D pwmchip_add(chip); if (err < 0) - goto err_disable_clk; + goto err_slow_clk_unlock; =20 platform_set_drvdata(pdev, chip); =20 return 0; =20 +err_slow_clk_unlock: + clk_rate_exclusive_put(tcbpwmc->slow_clk); + +err_clk_unlock: + clk_rate_exclusive_put(tcbpwmc->clk); + err_disable_clk: clk_disable_unprepare(tcbpwmc->slow_clk); =20 @@ -470,6 +490,8 @@ static void atmel_tcb_pwm_remove(struct platform_device= *pdev) =20 pwmchip_remove(chip); =20 + clk_rate_exclusive_put(tcbpwmc->slow_clk); + clk_rate_exclusive_put(tcbpwmc->clk); clk_disable_unprepare(tcbpwmc->slow_clk); clk_put(tcbpwmc->gclk); clk_put(tcbpwmc->clk); --=20 2.34.1