From patchwork Wed Dec 6 23:17:24 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Stephen Boyd X-Patchwork-Id: 174767 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:a59:bcd1:0:b0:403:3b70:6f57 with SMTP id r17csp4438148vqy; Wed, 6 Dec 2023 15:17:48 -0800 (PST) X-Google-Smtp-Source: AGHT+IGfWUr5pkoFaN8JP5KCv/hWxku8dW6Aecb1LOibiVujQhW02IUFiH6JqcCZhuPmFCsV2gYU X-Received: by 2002:a17:903:2441:b0:1cf:cb80:3fa5 with SMTP id l1-20020a170903244100b001cfcb803fa5mr2854693pls.23.1701904667720; Wed, 06 Dec 2023 15:17:47 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1701904667; cv=none; d=google.com; s=arc-20160816; b=g0Dp2u3W550im5//gPd7ayfyoe9D7/xQTKGUAwwL4d2oWxOabjTAb+r7a47EtH0pH+ IzAu6sq2ywn5c+aT1Q9hjzpeXnJexyX20apzE7U26dj/pK4pNBSO/8mZH4mEOUHYghIS w2q6MuHUNj2aUXUI0ELSB7Hdwcn3tPCFXp1bgpX8evJWrTIkn5gK280D4yFdwapZvGg8 r5Nrrzj4RhNOwguKgoG0yYXSMtfM2poQK11PmeLIjifVIujUGFZ4EIcrziHu4XZDEwhg 5p4BUQGjcz/8AecaCDOV6e28pXITCXFjQIxsyh+FWoRhnqmGBRyjExIJ+Bgv5PgCJP8j 3QXA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:content-transfer-encoding:mime-version :references:in-reply-to:message-id:date:subject:cc:to:from :dkim-signature; bh=M8rtEHygI9RG6sBRnubA7bTpojnZgHlW5a8etwqssgk=; fh=ylw7XFiXYr9BYF9M+Kpjdbiymg7bIn6MnHhSkmiqHOA=; b=ycKkl+f8L/NWkli6MuINFlrxeVV/34ztWy9yV+Fo6s7SM/lToqO2LXMpQcFbF8vuFC AtDC7mwnjQ3l5Qh4RSb9ccuv4J+EpB58PkbY9p06ln8TCYt031zoz+sMD4O2Mio8Eycl efrT6kObASlUYRwRsbrrZ0fp+KkrWtg5l9jlD0W8ne/Q4fNKKut904xE4q8FFSVvA50Z Sow1YLnGTHgLuOfAbX7DmQ+Eimgl2A9LkdWVH0EXMpz4410olfbkBEZicQyb87KD6j7W G5MRzcsAdBDmr7JW5F/8nqpFNAQvwdxT+LDn5Kos1teNRyLdHlBCvMhKk57YB35JAfc7 I4Ug== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@kernel.org header.s=k20201202 header.b=gofp9myH; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::3:6 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=kernel.org Received: from pete.vger.email (pete.vger.email. [2620:137:e000::3:6]) by mx.google.com with ESMTPS id c1-20020a170902d48100b001cfe100a99fsi529592plg.487.2023.12.06.15.17.47 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 06 Dec 2023 15:17:47 -0800 (PST) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::3:6 as permitted sender) client-ip=2620:137:e000::3:6; Authentication-Results: mx.google.com; dkim=pass header.i=@kernel.org header.s=k20201202 header.b=gofp9myH; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::3:6 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=kernel.org Received: from out1.vger.email (depot.vger.email [IPv6:2620:137:e000::3:0]) by pete.vger.email (Postfix) with ESMTP id 45F0280DAC76; Wed, 6 Dec 2023 15:17:43 -0800 (PST) X-Virus-Status: Clean X-Virus-Scanned: clamav-milter 0.103.11 at pete.vger.email Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1379626AbjLFXRb (ORCPT + 99 others); Wed, 6 Dec 2023 18:17:31 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:37276 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229669AbjLFXR3 (ORCPT ); Wed, 6 Dec 2023 18:17:29 -0500 Received: from smtp.kernel.org (relay.kernel.org [52.25.139.140]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 24D97D62 for ; Wed, 6 Dec 2023 15:17:35 -0800 (PST) Received: by smtp.kernel.org (Postfix) with ESMTPSA id 805A9C433C8; Wed, 6 Dec 2023 23:17:34 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1701904654; bh=btlg8hyFkyWuS3pIp7blky6KCbKG8CQSpsyNdN07Qds=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=gofp9myHsPQijWocq0HLQpbngoOklggPnv8Q5vi10Iwc1kARRtnQoaNQ68lyw0pJn de1UgZyfPBHMBhHDk1l7shQravN1aiqVEcZ+Nd6rIk2cMw+Qo1j98x7j9v+MyEzVFo Z/n30t8tIP8xGLx+ZSfj7zhHIzKomLqCYhhxdDfxMzsm/GjEbiCp5ZmsSPQpwdsp+i VNlIFeLA0ncGe4/wwbBvcjp443jdYBwSBTbHmMksUrOwlfmeP4PztkKSMiAZH0cP8y DdYC3EjQCubqGKT0P3E7WNqkQrkGg+dTV+YmwCwbVWqL4nNzX3mDlML7gmX5PMLYYR ZxQaO5ivqAnDA== From: Stephen Boyd To: Greg Kroah-Hartman Cc: =?utf-8?b?TsOtY29sYXMgRi4gUi4gQS4gUHJhZG8=?= , linux-kernel@vger.kernel.org, patches@lists.linux.dev, AngeloGioacchino Del Regno , Alexandre Mergnat Subject: [PATCH 1/8] spmi: mtk-pmif: Serialize PMIF status check and command submission Date: Wed, 6 Dec 2023 15:17:24 -0800 Message-ID: <20231206231733.4031901-2-sboyd@kernel.org> X-Mailer: git-send-email 2.43.0.rc2.451.g8631bc7472-goog In-Reply-To: <20231206231733.4031901-1-sboyd@kernel.org> References: <20231206231733.4031901-1-sboyd@kernel.org> MIME-Version: 1.0 X-Spam-Status: No, score=-1.2 required=5.0 tests=DKIMWL_WL_HIGH,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,MAILING_LIST_MULTI, SPF_HELO_NONE,SPF_PASS,T_SCC_BODY_TEXT_LINE autolearn=unavailable autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on pete.vger.email Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org X-Greylist: Sender passed SPF test, not delayed by milter-greylist-4.6.4 (pete.vger.email [0.0.0.0]); Wed, 06 Dec 2023 15:17:43 -0800 (PST) X-getmail-retrieved-from-mailbox: INBOX X-GMAIL-THRID: 1784576389018289711 X-GMAIL-MSGID: 1784576389018289711 From: NĂ­colas F. R. A. Prado Before writing the read or write command to the SPMI arbiter through the PMIF interface, the current status of the channel is checked to ensure it is idle. However, since the status only changes from idle when the command is written, it is possible for two concurrent calls to determine that the channel is idle and simultaneously send their commands. At this point the PMIF interface hangs, with the status register no longer being updated, and thus causing all subsequent operations to time out. This was observed on the mt8195-cherry-tomato-r2 machine, particularly after commit 46600ab142f8 ("regulator: Set PROBE_PREFER_ASYNCHRONOUS for drivers between 5.10 and 5.15") was applied, since then the two MT6315 devices present on the SPMI bus would probe assynchronously and sometimes (during probe or at a later point) read the bus simultaneously, breaking the PMIF interface and consequently slowing down the whole system. To fix the issue at its root cause, introduce locking around the channel status check and the command write, so that both become an atomic operation, preventing race conditions between two (or more) SPMI bus read/write operations. A spinlock is used since this is a fast bus, as indicated by the usage of the atomic variant of readl_poll, and '.fast_io = true' being used in the mt6315 driver, so spinlocks are already used for the regmap access. Fixes: b45b3ccef8c0 ("spmi: mediatek: Add support for MT6873/8192") Signed-off-by: NĂ­colas F. R. A. Prado Link: https://lore.kernel.org/r/20230724154739.493724-1-nfraprado@collabora.com Reviewed-by: AngeloGioacchino Del Regno Reviewed-by: Alexandre Mergnat Signed-off-by: Stephen Boyd --- drivers/spmi/spmi-mtk-pmif.c | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/drivers/spmi/spmi-mtk-pmif.c b/drivers/spmi/spmi-mtk-pmif.c index b3c991e1ea40..54c35f5535cb 100644 --- a/drivers/spmi/spmi-mtk-pmif.c +++ b/drivers/spmi/spmi-mtk-pmif.c @@ -50,6 +50,7 @@ struct pmif { struct clk_bulk_data clks[PMIF_MAX_CLKS]; size_t nclks; const struct pmif_data *data; + raw_spinlock_t lock; }; static const char * const pmif_clock_names[] = { @@ -314,6 +315,7 @@ static int pmif_spmi_read_cmd(struct spmi_controller *ctrl, u8 opc, u8 sid, struct ch_reg *inf_reg; int ret; u32 data, cmd; + unsigned long flags; /* Check for argument validation. */ if (sid & ~0xf) { @@ -334,6 +336,7 @@ static int pmif_spmi_read_cmd(struct spmi_controller *ctrl, u8 opc, u8 sid, else return -EINVAL; + raw_spin_lock_irqsave(&arb->lock, flags); /* Wait for Software Interface FSM state to be IDLE. */ inf_reg = &arb->chan; ret = readl_poll_timeout_atomic(arb->base + arb->data->regs[inf_reg->ch_sta], @@ -343,6 +346,7 @@ static int pmif_spmi_read_cmd(struct spmi_controller *ctrl, u8 opc, u8 sid, /* set channel ready if the data has transferred */ if (pmif_is_fsm_vldclr(arb)) pmif_writel(arb, 1, inf_reg->ch_rdy); + raw_spin_unlock_irqrestore(&arb->lock, flags); dev_err(&ctrl->dev, "failed to wait for SWINF_IDLE\n"); return ret; } @@ -350,6 +354,7 @@ static int pmif_spmi_read_cmd(struct spmi_controller *ctrl, u8 opc, u8 sid, /* Send the command. */ cmd = (opc << 30) | (sid << 24) | ((len - 1) << 16) | addr; pmif_writel(arb, cmd, inf_reg->ch_send); + raw_spin_unlock_irqrestore(&arb->lock, flags); /* * Wait for Software Interface FSM state to be WFVLDCLR, @@ -376,7 +381,8 @@ static int pmif_spmi_write_cmd(struct spmi_controller *ctrl, u8 opc, u8 sid, struct pmif *arb = spmi_controller_get_drvdata(ctrl); struct ch_reg *inf_reg; int ret; - u32 data, cmd; + u32 data, wdata, cmd; + unsigned long flags; if (len > 4) { dev_err(&ctrl->dev, "pmif supports 1..4 bytes per trans, but:%zu requested", len); @@ -394,6 +400,10 @@ static int pmif_spmi_write_cmd(struct spmi_controller *ctrl, u8 opc, u8 sid, else return -EINVAL; + /* Set the write data. */ + memcpy(&wdata, buf, len); + + raw_spin_lock_irqsave(&arb->lock, flags); /* Wait for Software Interface FSM state to be IDLE. */ inf_reg = &arb->chan; ret = readl_poll_timeout_atomic(arb->base + arb->data->regs[inf_reg->ch_sta], @@ -403,17 +413,17 @@ static int pmif_spmi_write_cmd(struct spmi_controller *ctrl, u8 opc, u8 sid, /* set channel ready if the data has transferred */ if (pmif_is_fsm_vldclr(arb)) pmif_writel(arb, 1, inf_reg->ch_rdy); + raw_spin_unlock_irqrestore(&arb->lock, flags); dev_err(&ctrl->dev, "failed to wait for SWINF_IDLE\n"); return ret; } - /* Set the write data. */ - memcpy(&data, buf, len); - pmif_writel(arb, data, inf_reg->wdata); + pmif_writel(arb, wdata, inf_reg->wdata); /* Send the command. */ cmd = (opc << 30) | BIT(29) | (sid << 24) | ((len - 1) << 16) | addr; pmif_writel(arb, cmd, inf_reg->ch_send); + raw_spin_unlock_irqrestore(&arb->lock, flags); return 0; } @@ -488,6 +498,8 @@ static int mtk_spmi_probe(struct platform_device *pdev) arb->chan.ch_send = PMIF_SWINF_0_ACC + chan_offset; arb->chan.ch_rdy = PMIF_SWINF_0_VLD_CLR + chan_offset; + raw_spin_lock_init(&arb->lock); + platform_set_drvdata(pdev, ctrl); err = spmi_controller_add(ctrl);