From patchwork Fri Oct 13 14:57:05 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Krzysztof Kozlowski X-Patchwork-Id: 733789 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 vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id D2C3DCDB482 for ; Fri, 13 Oct 2023 14:57:19 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S232206AbjJMO5T (ORCPT ); Fri, 13 Oct 2023 10:57:19 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:47296 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229879AbjJMO5S (ORCPT ); Fri, 13 Oct 2023 10:57:18 -0400 Received: from mail-ed1-x535.google.com (mail-ed1-x535.google.com [IPv6:2a00:1450:4864:20::535]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 68590C2 for ; Fri, 13 Oct 2023 07:57:10 -0700 (PDT) Received: by mail-ed1-x535.google.com with SMTP id 4fb4d7f45d1cf-53da80ada57so3963909a12.0 for ; Fri, 13 Oct 2023 07:57:10 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1697209029; x=1697813829; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:message-id:date:subject:cc :to:from:from:to:cc:subject:date:message-id:reply-to; bh=IWrbhvrzGMyL27X1/Ej2zzR/AW0jaYdGYz91JygNlqw=; b=He91YvxMijLyN6HY9/xNjBVW0GRMlbwIAm3/RS4yLQyNkTmaXDz8DIJ6SM0sltypLS ie/DNaZwEvBoaLMFXXORAnkdbElNTrku4Tld/PqFIZAA5vG4+lyY9gBl2HWRLEZIK6UB 5oFY7/9XB25YM7bAEfcBa1KtBy4VRPlJfF5h5gwxik7gZbaSt9XIg/pa1Awx9v1N52de vOU15hjpoHnvSGf1AIvR2ufRUn9bq+uDvI5K74KoFobb2XJNUIvEEC5nYyXjt+4vuTbm mkY1JFLlTEcOxV7YeJ0ENO52zgMwbdpzu7jyoa90VVsLn0Bjgll/nAPZazgpNmQkaYSA alkA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1697209029; x=1697813829; 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=IWrbhvrzGMyL27X1/Ej2zzR/AW0jaYdGYz91JygNlqw=; b=VvmHcBVyMM8gEScOT0HmeTdv21IRByOY/7F0zMy3GfOIt+vIJcNH/Z41sLVQoZDjHd 7hBn+iDZo/oSJC4UB7byP6uVNdcfB+6vg/MxqxnYtBQcvZdgYCEx5D3OBE0+dH1vz+jp z+1YvLq/rdcyjOorLEYKFpIIoWxhd5GkGZY9u5Im4eaxlan8hA8QcOCv9LUAhNOhBtve xcdT3BMO/Qbj+tlewLPirBaCxTd4Rdp9B1HD6iNEIiLzsxBR8F4dcbidVFAYr45kaAbS ukNjsGgipsNSpuT5zBag6p85bLRuHKuYyuoObPrGDZM4icrDpWj9wqiX4kp1b3Ryvn09 YyiQ== X-Gm-Message-State: AOJu0YxB4u+RKpnpkr8zLeNkpZvktEyWrS7OIJykozlDX+bsdn/UhBDU yacRFit7/uaUgddlawGzR2+Lgg== X-Google-Smtp-Source: AGHT+IGv76RjP4DNO5ukc0w7ZjoJSmsowv6+NlO4hl7Ade5sANtemSY4/pqSmSBjbNk2ivaq4buDTg== X-Received: by 2002:a17:907:7850:b0:9b9:ae5e:79ae with SMTP id lb16-20020a170907785000b009b9ae5e79aemr20288654ejc.60.1697209028794; Fri, 13 Oct 2023 07:57:08 -0700 (PDT) Received: from krzk-bin.. ([178.197.219.100]) by smtp.gmail.com with ESMTPSA id lu22-20020a170906fad600b009944e955e19sm12548341ejb.30.2023.10.13.07.57.07 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 13 Oct 2023 07:57:08 -0700 (PDT) From: Krzysztof Kozlowski To: Andy Gross , Bjorn Andersson , Konrad Dybcio , Linus Walleij , Srinivas Kandagatla , linux-arm-msm@vger.kernel.org, linux-gpio@vger.kernel.org, linux-kernel@vger.kernel.org Cc: Krzysztof Kozlowski , stable@vger.kernel.org Subject: [RESEND PATCH] pinctrl: qcom: lpass-lpi: fix concurrent register updates Date: Fri, 13 Oct 2023 16:57:05 +0200 Message-Id: <20231013145705.219954-1-krzysztof.kozlowski@linaro.org> X-Mailer: git-send-email 2.34.1 MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-gpio@vger.kernel.org The Qualcomm LPASS LPI pin controller driver uses one lock for guarding Read-Modify-Write code for slew rate registers. However the pin configuration and muxing registers have exactly the same RMW code but are not protected. Pin controller framework does not provide locking here, thus it is possible to trigger simultaneous change of pin configuration registers resulting in non-atomic changes. Protect from concurrent access by re-using the same lock used to cover the slew rate register. Using the same lock instead of adding second one will make more sense, once we add support for newer Qualcomm SoC, where slew rate is configured in the same register as pin configuration/muxing. Fixes: 6e261d1090d6 ("pinctrl: qcom: Add sm8250 lpass lpi pinctrl driver") Cc: stable@vger.kernel.org Reviewed-by: Linus Walleij Signed-off-by: Krzysztof Kozlowski --- Added Linus' review. Resending because no one picked up this patch. --- drivers/pinctrl/qcom/pinctrl-lpass-lpi.c | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/drivers/pinctrl/qcom/pinctrl-lpass-lpi.c b/drivers/pinctrl/qcom/pinctrl-lpass-lpi.c index abb6f1de230b..9651aed048cf 100644 --- a/drivers/pinctrl/qcom/pinctrl-lpass-lpi.c +++ b/drivers/pinctrl/qcom/pinctrl-lpass-lpi.c @@ -32,7 +32,8 @@ struct lpi_pinctrl { char __iomem *tlmm_base; char __iomem *slew_base; struct clk_bulk_data clks[MAX_LPI_NUM_CLKS]; - struct mutex slew_access_lock; + /* Protects from concurrent register updates */ + struct mutex lock; DECLARE_BITMAP(ever_gpio, MAX_NR_GPIO); const struct lpi_pinctrl_variant_data *data; }; @@ -103,6 +104,7 @@ static int lpi_gpio_set_mux(struct pinctrl_dev *pctldev, unsigned int function, if (WARN_ON(i == g->nfuncs)) return -EINVAL; + mutex_lock(&pctrl->lock); val = lpi_gpio_read(pctrl, pin, LPI_GPIO_CFG_REG); /* @@ -128,6 +130,7 @@ static int lpi_gpio_set_mux(struct pinctrl_dev *pctldev, unsigned int function, u32p_replace_bits(&val, i, LPI_GPIO_FUNCTION_MASK); lpi_gpio_write(pctrl, pin, LPI_GPIO_CFG_REG, val); + mutex_unlock(&pctrl->lock); return 0; } @@ -233,14 +236,14 @@ static int lpi_config_set(struct pinctrl_dev *pctldev, unsigned int group, if (slew_offset == LPI_NO_SLEW) break; - mutex_lock(&pctrl->slew_access_lock); + mutex_lock(&pctrl->lock); sval = ioread32(pctrl->slew_base + LPI_SLEW_RATE_CTL_REG); sval &= ~(LPI_SLEW_RATE_MASK << slew_offset); sval |= arg << slew_offset; iowrite32(sval, pctrl->slew_base + LPI_SLEW_RATE_CTL_REG); - mutex_unlock(&pctrl->slew_access_lock); + mutex_unlock(&pctrl->lock); break; default: return -EINVAL; @@ -256,6 +259,7 @@ static int lpi_config_set(struct pinctrl_dev *pctldev, unsigned int group, lpi_gpio_write(pctrl, group, LPI_GPIO_VALUE_REG, val); } + mutex_lock(&pctrl->lock); val = lpi_gpio_read(pctrl, group, LPI_GPIO_CFG_REG); u32p_replace_bits(&val, pullup, LPI_GPIO_PULL_MASK); @@ -264,6 +268,7 @@ static int lpi_config_set(struct pinctrl_dev *pctldev, unsigned int group, u32p_replace_bits(&val, output_enabled, LPI_GPIO_OE_MASK); lpi_gpio_write(pctrl, group, LPI_GPIO_CFG_REG, val); + mutex_unlock(&pctrl->lock); return 0; } @@ -461,7 +466,7 @@ int lpi_pinctrl_probe(struct platform_device *pdev) pctrl->chip.label = dev_name(dev); pctrl->chip.can_sleep = false; - mutex_init(&pctrl->slew_access_lock); + mutex_init(&pctrl->lock); pctrl->ctrl = devm_pinctrl_register(dev, &pctrl->desc, pctrl); if (IS_ERR(pctrl->ctrl)) { @@ -483,7 +488,7 @@ int lpi_pinctrl_probe(struct platform_device *pdev) return 0; err_pinctrl: - mutex_destroy(&pctrl->slew_access_lock); + mutex_destroy(&pctrl->lock); clk_bulk_disable_unprepare(MAX_LPI_NUM_CLKS, pctrl->clks); return ret; @@ -495,7 +500,7 @@ void lpi_pinctrl_remove(struct platform_device *pdev) struct lpi_pinctrl *pctrl = platform_get_drvdata(pdev); int i; - mutex_destroy(&pctrl->slew_access_lock); + mutex_destroy(&pctrl->lock); clk_bulk_disable_unprepare(MAX_LPI_NUM_CLKS, pctrl->clks); for (i = 0; i < pctrl->data->npins; i++)