From patchwork Tue Jul 9 10:18:05 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Uwe_Kleine-K=C3=B6nig?= X-Patchwork-Id: 13727604 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 82165C2BD09 for ; Tue, 9 Jul 2024 10:18:59 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20210309; h=Sender:List-Subscribe:List-Help :List-Post:List-Archive:List-Unsubscribe:List-Id:Content-Transfer-Encoding: Content-Type:MIME-Version:Message-ID:Date:Subject:Cc:To:From:Reply-To: Content-ID:Content-Description:Resent-Date:Resent-From:Resent-Sender: Resent-To:Resent-Cc:Resent-Message-ID:In-Reply-To:References:List-Owner; bh=55skElxOMrOCjPUV7UX9C7ptFLmqKM5oP3GtZJKO37w=; b=ozXoqs5X/5N6yOidBJcOcZugZu xnCHjXQ5Chv1gKLc1dmPJEiE7GmhVlbRE66EokzXfs6X8NK5snjXIah8bOcCl+sUeS03qJ3kSi9ki AN2hwxq+lAmGJCb1uefOc3WZLyzh5bMB3zBmbUr97EhSuhWJBMvNPXkSMVwOD7tdsb+K2G/g59/Fp F56EAbaj0Jofl8yuss+VYHTbX//JsoOGSqoZ+s4sT0VIzdAL+A/pYS32lFvVONdRbEpic2845YvP6 vkInzIuXcNeD5Cm0eLpoTFVmxpNW76amtkVcNUcvKK6Hlh1NJfxgVrgREkq7dmPsYm7YyRrfYsL8E 1fYCWI2Q==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.97.1 #2 (Red Hat Linux)) id 1sR7vp-00000006msz-3dVt; Tue, 09 Jul 2024 10:18:46 +0000 Received: from mail-ed1-x529.google.com ([2a00:1450:4864:20::529]) by bombadil.infradead.org with esmtps (Exim 4.97.1 #2 (Red Hat Linux)) id 1sR7vZ-00000006mqR-1PY9 for linux-arm-kernel@lists.infradead.org; Tue, 09 Jul 2024 10:18:31 +0000 Received: by mail-ed1-x529.google.com with SMTP id 4fb4d7f45d1cf-59589a9be92so290440a12.2 for ; Tue, 09 Jul 2024 03:18:28 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=baylibre-com.20230601.gappssmtp.com; s=20230601; t=1720520307; x=1721125107; darn=lists.infradead.org; h=content-transfer-encoding:mime-version:message-id:date:subject:cc :to:from:from:to:cc:subject:date:message-id:reply-to; bh=55skElxOMrOCjPUV7UX9C7ptFLmqKM5oP3GtZJKO37w=; b=VTj4qi0Ru6bD5dGzH1KT/aEcavBvPabnTDG0vd2BddU/9YB28inD2padKOJ9PeQIhS iL8LNlHi/fnzKR34upF2pbwt8nqFHL/0Dxa4C13/SC7Q1Nkqp5rdTIgeyN2jQcw8t8mt N8vbWs/PgwDZfh8TJTPaPThJZwVH0TpRwRO7VNE4cVG9k4Xonuk11RoeMfnWOzmPHXU/ 7JORS4y2sPt/C/ZIihHx4ESVwNCT+qvc99YsL/0Ti38wW4E+MIzfRW1ByZOBiw4YznLP QpvVIH6JVSkggfpaZxyCC58vwEHgB5xbJCH6v+RehwB+XQrSlMYGIcgLvoNiz0RU31dJ rXCg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1720520307; x=1721125107; h=content-transfer-encoding:mime-version:message-id:date:subject:cc :to:from:x-gm-message-state:from:to:cc:subject:date:message-id :reply-to; bh=55skElxOMrOCjPUV7UX9C7ptFLmqKM5oP3GtZJKO37w=; b=pdy6QlHrAhkzHIMl+5nrWsbeXih7CwGHcIEozLanftiGgRotybXmo7Ge4jY0VFH+9W WwInaITP/la8nC/TA+RMstPH6OPeWo98v3OEayXjB0aW4fFUVevxGfy5VPegSmgJqgkq DyOCL3zSI9HPbeWwrEnz1ubAUTmu4xBe01ArJ+s7hyEBYyW6CqUN6IHyq9eRxtL5JPHy quoGGNiMv8JLW7hwudTpTsuniBIcn12flXGKjwq9RKZBb7C0Txg38V+3zywXegrLNd3h x/KLNTncoiZoYdZhCwoh+iWMYdZeK7jyKjtKXZQe8RRWJuYKiG6HQhcDihV+/w86D/kK YFrQ== X-Forwarded-Encrypted: i=1; AJvYcCX9vR2Wwfd3bPby0AKkAvcgP4+WiB/SBVBeoKOwOdL4l1Zm3Ne3mPDlWZaW5jjw2DatabANSpKb1A8NnuCG6VMJJMFusU6DYvlP3Q2ezjqoXgaOsFc= X-Gm-Message-State: AOJu0YyqByuGqVwv98z9D02HLaUOPRI5Qjb+UECDz255dbgY4QSxFKUs PInNqU5jLe50NijOqdsyTTFSBPLHQFifaQmHIyeVxFjYkHltj14E0OM4CXLir/g= X-Google-Smtp-Source: AGHT+IFKicBvL2WppGJx9Wp7stHGuv3aT4Zjx+F3UAzn59KIF3x/7SLjKWmnyoCEK+rfT5yAZNwixg== X-Received: by 2002:aa7:da8b:0:b0:57c:5fcf:b570 with SMTP id 4fb4d7f45d1cf-594bc7ca0fbmr1260673a12.32.1720520307223; Tue, 09 Jul 2024 03:18:27 -0700 (PDT) Received: from localhost (p50915e7b.dip0.t-ipconnect.de. [80.145.94.123]) by smtp.gmail.com with ESMTPSA id 4fb4d7f45d1cf-594bbe2d338sm901811a12.39.2024.07.09.03.18.26 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 09 Jul 2024 03:18:26 -0700 (PDT) From: =?utf-8?q?Uwe_Kleine-K=C3=B6nig?= To: Nicolas Ferre , Alexandre Belloni , Claudiu Beznea , Boris Brezillon Cc: linux-pwm@vger.kernel.org, linux-arm-kernel@lists.infradead.org Subject: [PATCH 1/2] pwm: atmel-tcb: Fix race condition and convert to guards Date: Tue, 9 Jul 2024 12:18:05 +0200 Message-ID: <20240709101806.52394-3-u.kleine-koenig@baylibre.com> X-Mailer: git-send-email 2.43.0 MIME-Version: 1.0 X-Developer-Signature: v=1; a=openpgp-sha256; l=3472; i=u.kleine-koenig@baylibre.com; h=from:subject; bh=mXyUzOkvkfb+kJ85JoB+gVRy5JglbPng3lB2rtsWqsQ=; b=owEBbQGS/pANAwAKAY+A+1h9Ev5OAcsmYgBmjQ5eGS57zLE42aid3aguQbgn0NuMDGAxKRy/n 3iaE1X9mMuJATMEAAEKAB0WIQQ/gaxpOnoeWYmt/tOPgPtYfRL+TgUCZo0OXgAKCRCPgPtYfRL+ TvG1CACmwn+592GoOBW/oopHdgC+X0LAPRPOFcx/zX94/es7aEaPFsG3x/6RvQ1hDMYU06Ol61S l64ePJvBLXBYg/IPONdjY+cNm1GVIRn2QprIOGVdEVRxBj52RG7xRAWBJSXz5mmyuHV9qsc6mUW 5ZgVB0ULWJ1vOBSNV3juB0xGqBUgE7+iBYQNlD2wihw1kOEve4KkZAzkHsrtGvzupWvbYf6DMZ5 iADh5ZZveyvNxdJqAdh8p6UafPaznR1NsOCcFtfZUocCQ/VvSip8fxg1zHnI25noA2haqgJD+8S K11Kzl5GrQcDEYmIVER1gNlAUCLlv6GwXvlYH19FxSTOCcuC X-Developer-Key: i=u.kleine-koenig@baylibre.com; a=openpgp; fpr=0D2511F322BFAB1C1580266BE2DCDD9132669BD6 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20240709_031829_496709_ADFB6407 X-CRM114-Status: GOOD ( 16.42 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org The hardware only supports a single period length for both PWM outputs. So atmel_tcb_pwm_config() checks the configuration of the other output if it's compatible with the currently requested setting. The register values are then actually updated in atmel_tcb_pwm_enable(). To make this race free the lock must be held during the whole process, so grab the lock in .apply() instead of individually in atmel_tcb_pwm_disable() and atmel_tcb_pwm_enable() which then also covers atmel_tcb_pwm_config(). To simplify handling, use the guard helper to let the compiler care for unlocking. Otherwise unlocking would be more difficult as there is more than one exit path in atmel_tcb_pwm_apply(). Fixes: 9421bade0765 ("pwm: atmel: add Timer Counter Block PWM driver") Signed-off-by: Uwe Kleine-König Acked-by: Nicolas Ferre --- drivers/pwm/pwm-atmel-tcb.c | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) base-commit: 120a528213b6693214e3cbc24a9c3052a4b1024b diff --git a/drivers/pwm/pwm-atmel-tcb.c b/drivers/pwm/pwm-atmel-tcb.c index 528e54c5999d..aca11493239a 100644 --- a/drivers/pwm/pwm-atmel-tcb.c +++ b/drivers/pwm/pwm-atmel-tcb.c @@ -81,7 +81,8 @@ static int atmel_tcb_pwm_request(struct pwm_chip *chip, tcbpwm->period = 0; tcbpwm->div = 0; - spin_lock(&tcbpwmc->lock); + guard(spinlock)(&tcbpwmc->lock); + regmap_read(tcbpwmc->regmap, ATMEL_TC_REG(tcbpwmc->channel, CMR), &cmr); /* * Get init config from Timer Counter registers if @@ -107,7 +108,6 @@ static int atmel_tcb_pwm_request(struct pwm_chip *chip, cmr |= ATMEL_TC_WAVE | ATMEL_TC_WAVESEL_UP_AUTO | ATMEL_TC_EEVT_XC0; regmap_write(tcbpwmc->regmap, ATMEL_TC_REG(tcbpwmc->channel, CMR), cmr); - spin_unlock(&tcbpwmc->lock); return 0; } @@ -137,7 +137,6 @@ static void atmel_tcb_pwm_disable(struct pwm_chip *chip, struct pwm_device *pwm, if (tcbpwm->duty == 0) polarity = !polarity; - spin_lock(&tcbpwmc->lock); regmap_read(tcbpwmc->regmap, ATMEL_TC_REG(tcbpwmc->channel, CMR), &cmr); /* flush old setting and set the new one */ @@ -172,8 +171,6 @@ static void atmel_tcb_pwm_disable(struct pwm_chip *chip, struct pwm_device *pwm, ATMEL_TC_SWTRG); tcbpwmc->bkup.enabled = 0; } - - spin_unlock(&tcbpwmc->lock); } static int atmel_tcb_pwm_enable(struct pwm_chip *chip, struct pwm_device *pwm, @@ -194,7 +191,6 @@ static int atmel_tcb_pwm_enable(struct pwm_chip *chip, struct pwm_device *pwm, if (tcbpwm->duty == 0) polarity = !polarity; - spin_lock(&tcbpwmc->lock); regmap_read(tcbpwmc->regmap, ATMEL_TC_REG(tcbpwmc->channel, CMR), &cmr); /* flush old setting and set the new one */ @@ -256,7 +252,6 @@ static int atmel_tcb_pwm_enable(struct pwm_chip *chip, struct pwm_device *pwm, regmap_write(tcbpwmc->regmap, ATMEL_TC_REG(tcbpwmc->channel, CCR), ATMEL_TC_SWTRG | ATMEL_TC_CLKEN); tcbpwmc->bkup.enabled = 1; - spin_unlock(&tcbpwmc->lock); return 0; } @@ -341,9 +336,12 @@ static int atmel_tcb_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm, static int atmel_tcb_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm, const struct pwm_state *state) { + struct atmel_tcb_pwm_chip *tcbpwmc = to_tcb_chip(chip); int duty_cycle, period; int ret; + guard(spinlock)(&tcbpwmc->lock); + if (!state->enabled) { atmel_tcb_pwm_disable(chip, pwm, state->polarity); return 0;