On Mon, 12 Feb 2024 17:26:41 -0600 David Lechner <dlechner@xxxxxxxxxxxx> wrote: > This adds a new spi_optimize_message() function that can be used to > optimize SPI messages that are used more than once. Peripheral drivers > that use the same message multiple times can use this API to perform SPI > message validation and controller-specific optimizations once and then > reuse the message while avoiding the overhead of revalidating the > message on each spi_(a)sync() call. > > Internally, the SPI core will also call this function for each message > if the peripheral driver did not explicitly call it. This is done to so > that controller drivers don't have to have multiple code paths for > optimized and non-optimized messages. > > A hook is provided for controller drivers to perform controller-specific > optimizations. > > Suggested-by: Martin Sperl <kernel@xxxxxxxxxxxxxxxx> > Link: https://lore.kernel.org/linux-spi/39DEC004-10A1-47EF-9D77-276188D2580C@xxxxxxxxxxxxxxxx/ > Signed-off-by: David Lechner <dlechner@xxxxxxxxxxxx> A few trivial things inline but looks good to me in general. I thought about suggesting splitting this into an initial patch that just does the bits without the controller callbacks. Maybe it would work better that way with that introduced after the validate and splitting of transfers (so most of patches 1 and 2) as a patch 3 prior to the stm32 additions? > --- > drivers/spi/spi.c | 145 ++++++++++++++++++++++++++++++++++++++++++++++-- > include/linux/spi/spi.h | 19 +++++++ > 2 files changed, 160 insertions(+), 4 deletions(-) > > diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c > index c2b10e2c75f0..5bac215d7009 100644 > --- a/drivers/spi/spi.c > +++ b/drivers/spi/spi.c > @@ -2106,6 +2106,41 @@ struct spi_message *spi_get_next_queued_message(struct spi_controller *ctlr) > } > EXPORT_SYMBOL_GPL(spi_get_next_queued_message); > > +/** > + * __spi_unoptimize_message - shared implementation of spi_unoptimize_message() > + * and spi_maybe_unoptimize_message() > + * @msg: the message to unoptimize > + * > + * Periperhal drivers should use spi_unoptimize_message() and callers inside > + * core should use spi_maybe_unoptimize_message() rather than calling this > + * function directly. > + * > + * It is not valid to call this on a message that is not currently optimized. > + */ > +static void __spi_unoptimize_message(struct spi_message *msg) > +{ > + struct spi_controller *ctlr = msg->spi->controller; > + > + if (ctlr->unoptimize_message) > + ctlr->unoptimize_message(msg); > + > + msg->optimized = false; > + msg->opt_state = NULL; > +} Seems misbalanced that this doesn't take a pre_optimized flag in but __spi_optimize does. I'd move handling that to outside the call in both cases. > spin_lock_irqsave(&ctlr->bus_lock_spinlock, flags); > @@ -4271,6 +4401,8 @@ int spi_async(struct spi_device *spi, struct spi_message *message) > > spin_unlock_irqrestore(&ctlr->bus_lock_spinlock, flags); > > + spi_maybe_unoptimize_message(message); > + > return ret; > } > EXPORT_SYMBOL_GPL(spi_async); > @@ -4331,10 +4463,15 @@ static int __spi_sync(struct spi_device *spi, struct spi_message *message) > return -ESHUTDOWN; > } > > - status = __spi_validate(spi, message); > - if (status != 0) > + status = spi_maybe_optimize_message(spi, message); > + if (status) > return status; > > + /* > + * NB: all return paths after this point must ensure that > + * spi_finalize_current_message() is called to avoid leaking resources. I'm not sure a catch all like that makes sense. Not sufficient to call the finer grained spi_maybe_unoptimize_message() ? > + */ > + > SPI_STATISTICS_INCREMENT_FIELD(ctlr->pcpu_statistics, spi_sync); > SPI_STATISTICS_INCREMENT_FIELD(spi->pcpu_statistics, spi_sync);