From: David Laight <david.laight.linux@gmail.com>
To: Peter Collingbourne <peter@pcc.me.uk>
Cc: "Mark Brown" <broonie@kernel.org>,
"Jani Nikula" <jani.nikula@intel.com>,
"Ville Syrjälä" <ville.syrjala@linux.intel.com>,
"Christophe Kerello" <christophe.kerello@foss.st.com>,
"Patrice Chotard" <patrice.chotard@foss.st.com>,
"Boris Brezillon" <boris.brezillon@collabora.com>,
linux-spi@vger.kernel.org, linux-kernel@vger.kernel.org,
"Simona Vetter" <simona.vetter@ffwll.ch>,
"Randy Dunlap" <rdunlap@infradead.org>
Subject: Re: [PATCH v2] iopoll: use udelay() for initial polling
Date: Fri, 29 May 2026 12:20:16 +0100 [thread overview]
Message-ID: <20260529122016.0059f55d@pumpkin> (raw)
In-Reply-To: <CAPQLkRi1aP3N2d7GzrRfXF0xDyamt_n9AKzFvV1WdpNk0ZymJg@mail.gmail.com>
On Thu, 28 May 2026 22:59:25 -0700
Peter Collingbourne <peter@pcc.me.uk> wrote:
> On Fri, May 22, 2026 at 7:51 AM Mark Brown <broonie@kernel.org> wrote:
> >
> > On Thu, May 21, 2026 at 10:03:28AM +0300, Jani Nikula wrote:
> > > On Wed, 20 May 2026, Peter Collingbourne <peter@pcc.me.uk> wrote:
> >
> > > > That's what I had in v1; we decided this approach would better handle
> > > > misbehaving devices.
> > > > https://lore.kernel.org/all/20260517150253.031dec09@pumpkin/
> >
> > > I think the problem with trying to adapt to everything within
> > > read_poll_timeout() is that every step like this adapts to a *specific*
> > > use case, and once it gets specific enough, it's no longer usable to
> > > other scenarios.
> >
> > > Having to reimplement the whole thing in drivers is much worse than
> > > having to do two calls.
> >
> > > Could a staggered approach work?
> >
> > > ret = read_poll_timeout_atomic("short delay/timeout")
> > > if (ret)
> > > ret = read_poll_timeout("longer delay/timeout")
> >
> > > Then you have better control of the behaviour in the driver, instead of
> > > adapting a generic function to a specific use case.
> >
> > If we're doing that it still seems like it'd be better to have a helper
> > than just takes the two timeouts and does the right thing with them. My
> > original feedback here was that we should have helpers which encourage
> > good patterns, and TBH I expect there's probably a bunch of scenarios
> > where some fixed cutoff would be a worthwile improvement for very little
> > effort on the part of users.
>
> Thinking about it some more:
>
> Do we really want to udelay() for the initial busy wait? Assuming that
> we've decided to spend some time burning cycles, I think we may as
> well use those cycles to check the condition so that we have a chance
> of an early exit.
>
> As an experiment, I open coded it in the SPI NAND driver:
>
> diff --git a/drivers/spi/spi-mem.c b/drivers/spi/spi-mem.c
> index a09371a075d2..cce34ada7611 100644
> --- a/drivers/spi/spi-mem.c
> +++ b/drivers/spi/spi-mem.c
> @@ -1005,6 +1005,20 @@ int spi_mem_poll_status(struct spi_mem *mem,
> usleep_range((initial_delay_us >> 2) + 1,
> initial_delay_us);
>
> + {
> + ktime_t __start_time = ktime_get();
> + u64 __delay_timeout_us = 10;
> + ktime_t __delay_timeout =
> + ktime_add_us(__start_time, __delay_timeout_us);
> + while (ktime_compare(ktime_get(), __delay_timeout) <
> + 0) {
> + ret = spi_mem_read_status(mem, op, &status);
> + if (ret < 0)
> + return ret;
> + if ((status & mask) == match)
> + return 0;
> + }
> + }
> ret = read_poll_timeout(spi_mem_read_status, read_status_ret,
> (read_status_ret || ((status)
> & mask) == match),
> polling_delay_us, timeout_ms *
> 1000, false, mem,
>
> And it did in fact improve performance on my target compared to status
> quo and even v2.
>
> With hrtimers enabled, timing the UBI scan, 3 runs of each:
> - With no changes: 0.784s, 0.779s, 0.777s
> - With my v2: 0.687s, 0.686s, 0.687s
> - With the above patch: 0.665s, 0.665s, 0.665s
>
> So 3 options:
> 1. Take my v2 and change read_poll_timeout() to do the check during
> the busy wait.
> 2. Adjust read_poll_timeout_atomic() to busy wait using the check
> instead of udelay(), then change the SPI NAND driver to do the 2
> calls.
> 3. Introduce a new macro that does the 2 calls, and have the SPI NAND
> driver use it.
There is also the (difficult to measure) impact on overall system performance.
The versions that sleep let the cpu run other processes (or go to a low
power state).
Looping reading the status will load whatever bus handles the requests
between the cpu and spi interface logic (might be PCIe for example), that
could slow down accesses to other devices from other cpu.
I think I remember someone saying that the spi hardware interface normally
generates an interrupt when the request completes?
So for spi this is only fall-back code for a few systems.
Although I just looked at some code I have for doing bulk writes to an SPI
memory device (to write an fpga image).
That does about 35000 back to back writes.
The whole lot is in userspace - the driver just lets it mmap() the PCIe
registers. And the PCIe slave just converts 32bit accesses into 8 4-bit ones.
(I really should have supported read/write of AVX registers to reduce the
latency of reads - but reads are only really used for verify and I got the
CRC64 logic working in the end.)
The code has this comment:
/* Wait for the write - typically 0.6ms (max 5ms).
* In spite of the datasheet values, I'm seeing 200us writes. */
It waits 200us and then polls every 50us for 2 seconds.
-- David
>
> I don't have a strong opinion, but my preference would be either 1 or
> 3. I agree with Mark that it would make the preferred usage code
> easier to write (and to read), as there would be no need to duplicate
> the argument list or compute the timeouts correctly in every caller.
>
> Peter
next prev parent reply other threads:[~2026-05-29 11:20 UTC|newest]
Thread overview: 11+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-05-19 10:24 [PATCH v2] iopoll: use udelay() for initial polling Peter Collingbourne
2026-05-19 18:35 ` David Laight
2026-05-20 7:38 ` Peter Collingbourne
2026-05-20 13:29 ` Ville Syrjälä
2026-05-21 5:59 ` Peter Collingbourne
2026-05-21 7:03 ` Jani Nikula
2026-05-22 14:50 ` Mark Brown
2026-05-29 5:59 ` Peter Collingbourne
2026-05-29 11:20 ` David Laight [this message]
2026-05-29 21:56 ` Mark Brown
2026-05-30 10:20 ` David Laight
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260529122016.0059f55d@pumpkin \
--to=david.laight.linux@gmail.com \
--cc=boris.brezillon@collabora.com \
--cc=broonie@kernel.org \
--cc=christophe.kerello@foss.st.com \
--cc=jani.nikula@intel.com \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-spi@vger.kernel.org \
--cc=patrice.chotard@foss.st.com \
--cc=peter@pcc.me.uk \
--cc=rdunlap@infradead.org \
--cc=simona.vetter@ffwll.ch \
--cc=ville.syrjala@linux.intel.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox