On Mon, 12 Feb 2024 17:26:42 -0600 David Lechner <dlechner@xxxxxxxxxxxx> wrote: > Splitting transfers is an expensive operation so we can potentially > optimize it by doing it only once per optimization of the message > instead of repeating each time the message is transferred. > > The transfer splitting functions are currently the only user of > spi_res_alloc() so spi_res_release() can be safely moved at this time > from spi_finalize_current_message() to spi_unoptimize_message(). > > The doc comments of the public functions for splitting transfers are > also updated so that callers will know when it is safe to call them > to ensure proper resource management. > > Signed-off-by: David Lechner <dlechner@xxxxxxxxxxxx> > --- Trivial thing (which applies equally to the original code). Otherwise LGTM. FWIW Reviewed-by: Jonathan Cameron <Jonathan.Cameron@xxxxxxxxxx> > +/** > + * spi_split_transfers - generic handling of transfer splitting > + * @msg: the message to split > + * > + * Under certain conditions, a SPI controller may not support arbitrary > + * transfer sizes or other features required by a peripheral. This function > + * will split the transfers in the message into smaller transfers that are > + * supported by the controller. > + * > + * Controllers with special requirements not covered here can also split > + * transfers in the optimize_message() callback. > + * > + * Context: can sleep > + * Return: zero on success, else a negative error code > + */ > +static int spi_split_transfers(struct spi_message *msg) > +{ > + struct spi_controller *ctlr = msg->spi->controller; > + struct spi_transfer *xfer; > + int ret; > + > + /* > + * If an SPI controller does not support toggling the CS line on each > + * transfer (indicated by the SPI_CS_WORD flag) or we are using a GPIO > + * for the CS line, we can emulate the CS-per-word hardware function by > + * splitting transfers into one-word transfers and ensuring that > + * cs_change is set for each transfer. > + */ > + if ((msg->spi->mode & SPI_CS_WORD) && (!(ctlr->mode_bits & SPI_CS_WORD) || > + spi_is_csgpiod(msg->spi))) { if ((msg->spi->mode & SPI_CS_WORD) && (!(ctlr->mode_bits & SPI_CS_WORD) || spi_is_csgpiod(msg->spi))) { Seems easier to read to me. I appreciate you are just moving it though so don't mind that much if you leave it in the original form. > + ret = spi_split_transfers_maxwords(ctlr, msg, 1); > + if (ret) > + return ret; > + > + list_for_each_entry(xfer, &msg->transfers, transfer_list) { > + /* Don't change cs_change on the last entry in the list */ > + if (list_is_last(&xfer->transfer_list, &msg->transfers)) > + break; > + > + xfer->cs_change = 1; > + } > + } else { > + ret = spi_split_transfers_maxsize(ctlr, msg, > + spi_max_transfer_size(msg->spi)); > + if (ret) > + return ret; > + } > + > + return 0; > +}