lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-Id: <20221114015749.28490-4-samuel@sholland.org>
Date:   Sun, 13 Nov 2022 19:57:49 -0600
From:   Samuel Holland <samuel@...lland.org>
To:     Chen-Yu Tsai <wens@...e.org>,
        Jernej Skrabec <jernej.skrabec@...il.com>
Cc:     Ivaylo Dimitrov <ivo.g.dimitrov.75@...il.com>,
        linux-arm-kernel@...ts.infradead.org, linux-kernel@...r.kernel.org,
        linux-sunxi@...ts.linux.dev,
        Andre Przywara <andre.przywara@....com>,
        Samuel Holland <samuel@...lland.org>
Subject: [PATCH v3 3/3] bus: sunxi-rsb: Clear interrupt status before each transfer

Currently, the driver clears the interrupt status bits after anything
could have set them. However, this requires duplicating the same logic
in several places.

Instead of clearing the status flags in the interrupt handler, disable
all further interrupts by clearing the RSB_CTRL_GLOBAL_INT_ENB bit.
Then we can delay the status register write until the start of the next
transfer, so it only has to be done in one place.

Signed-off-by: Samuel Holland <samuel@...lland.org>
---

Changes in v3:
 - Add a patch refactoring how the status bits are cleared

 drivers/bus/sunxi-rsb.c | 20 +++++---------------
 1 file changed, 5 insertions(+), 15 deletions(-)

diff --git a/drivers/bus/sunxi-rsb.c b/drivers/bus/sunxi-rsb.c
index 3aa91aed3bf7..cb622e60897b 100644
--- a/drivers/bus/sunxi-rsb.c
+++ b/drivers/bus/sunxi-rsb.c
@@ -279,6 +279,7 @@ static int _sunxi_rsb_run_xfer(struct sunxi_rsb *rsb)
 
 	int_mask = RSB_INTS_LOAD_BSY | RSB_INTS_TRANS_ERR | RSB_INTS_TRANS_OVER;
 	writel(int_mask, rsb->regs + RSB_INTE);
+	writel(int_mask, rsb->regs + RSB_INTS);
 	writel(RSB_CTRL_START_TRANS | RSB_CTRL_GLOBAL_INT_ENB,
 	       rsb->regs + RSB_CTRL);
 
@@ -286,7 +287,6 @@ static int _sunxi_rsb_run_xfer(struct sunxi_rsb *rsb)
 		timeout = readl_poll_timeout_atomic(rsb->regs + RSB_INTS,
 						    status, (status & int_mask),
 						    10, 100000);
-		writel(status, rsb->regs + RSB_INTS);
 	} else {
 		timeout = !wait_for_completion_io_timeout(&rsb->complete,
 							  msecs_to_jiffies(100));
@@ -296,12 +296,9 @@ static int _sunxi_rsb_run_xfer(struct sunxi_rsb *rsb)
 	if (timeout) {
 		dev_dbg(rsb->dev, "RSB timeout\n");
 
-		/* abort the transfer */
+		/* abort the transfer and disable interrupts */
 		writel(RSB_CTRL_ABORT_TRANS, rsb->regs + RSB_CTRL);
 
-		/* clear any interrupt flags */
-		writel(readl(rsb->regs + RSB_INTS), rsb->regs + RSB_INTS);
-
 		return -ETIMEDOUT;
 	}
 
@@ -503,15 +500,11 @@ EXPORT_SYMBOL_GPL(__devm_regmap_init_sunxi_rsb);
 static irqreturn_t sunxi_rsb_irq(int irq, void *dev_id)
 {
 	struct sunxi_rsb *rsb = dev_id;
-	u32 status;
 
-	status = readl(rsb->regs + RSB_INTS);
-	rsb->status = status;
+	/* disable interrupts */
+	writel(0, rsb->regs + RSB_CTRL);
 
-	/* Clear interrupts */
-	status &= (RSB_INTS_LOAD_BSY | RSB_INTS_TRANS_ERR |
-		   RSB_INTS_TRANS_OVER);
-	writel(status, rsb->regs + RSB_INTS);
+	rsb->status = readl(rsb->regs + RSB_INTS);
 
 	complete(&rsb->complete);
 
@@ -532,9 +525,6 @@ static int sunxi_rsb_init_device_mode(struct sunxi_rsb *rsb)
 	if (reg & RSB_DMCR_DEVICE_START)
 		ret = -ETIMEDOUT;
 
-	/* clear interrupt status bits */
-	writel(readl(rsb->regs + RSB_INTS), rsb->regs + RSB_INTS);
-
 	return ret;
 }
 
-- 
2.37.3

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ