On Sat 12 Sep 13:17 CDT 2020, Douglas Anderson wrote: > If we're sending bytes over SPI, we know the FIFO is empty at the > start of the transfer. There's no reason to wait for the interrupt > telling us to start--we can just start right away. Then if we > transmit everything in one swell foop we don't even need to bother > listening for TX interrupts. > > In a test of "flashrom -p ec -r /tmp/foo.bin" interrupts were reduced > from ~30560 to ~29730, about a 3% savings. > > This patch looks bigger than it is because I moved a few functions > rather than adding a forward declaration. The only actual change to > geni_spi_handle_tx() was to make it return a bool indicating if there > is more to tx. > Reviewed-by: Bjorn Andersson <bjorn.andersson@xxxxxxxxxx> Regards, Bjorn > Signed-off-by: Douglas Anderson <dianders@xxxxxxxxxxxx> > --- > > drivers/spi/spi-geni-qcom.c | 167 +++++++++++++++++++----------------- > 1 file changed, 86 insertions(+), 81 deletions(-) > > diff --git a/drivers/spi/spi-geni-qcom.c b/drivers/spi/spi-geni-qcom.c > index 0dc3f4c55b0b..49c9eb870755 100644 > --- a/drivers/spi/spi-geni-qcom.c > +++ b/drivers/spi/spi-geni-qcom.c > @@ -326,6 +326,88 @@ static int spi_geni_init(struct spi_geni_master *mas) > return 0; > } > > +static unsigned int geni_byte_per_fifo_word(struct spi_geni_master *mas) > +{ > + /* > + * Calculate how many bytes we'll put in each FIFO word. If the > + * transfer words don't pack cleanly into a FIFO word we'll just put > + * one transfer word in each FIFO word. If they do pack we'll pack 'em. > + */ > + if (mas->fifo_width_bits % mas->cur_bits_per_word) > + return roundup_pow_of_two(DIV_ROUND_UP(mas->cur_bits_per_word, > + BITS_PER_BYTE)); > + > + return mas->fifo_width_bits / BITS_PER_BYTE; > +} > + > +static bool geni_spi_handle_tx(struct spi_geni_master *mas) > +{ > + struct geni_se *se = &mas->se; > + unsigned int max_bytes; > + const u8 *tx_buf; > + unsigned int bytes_per_fifo_word = geni_byte_per_fifo_word(mas); > + unsigned int i = 0; > + > + max_bytes = (mas->tx_fifo_depth - mas->tx_wm) * bytes_per_fifo_word; > + if (mas->tx_rem_bytes < max_bytes) > + max_bytes = mas->tx_rem_bytes; > + > + tx_buf = mas->cur_xfer->tx_buf + mas->cur_xfer->len - mas->tx_rem_bytes; > + while (i < max_bytes) { > + unsigned int j; > + unsigned int bytes_to_write; > + u32 fifo_word = 0; > + u8 *fifo_byte = (u8 *)&fifo_word; > + > + bytes_to_write = min(bytes_per_fifo_word, max_bytes - i); > + for (j = 0; j < bytes_to_write; j++) > + fifo_byte[j] = tx_buf[i++]; > + iowrite32_rep(se->base + SE_GENI_TX_FIFOn, &fifo_word, 1); > + } > + mas->tx_rem_bytes -= max_bytes; > + if (!mas->tx_rem_bytes) { > + writel(0, se->base + SE_GENI_TX_WATERMARK_REG); > + return false; > + } > + return true; > +} > + > +static void geni_spi_handle_rx(struct spi_geni_master *mas) > +{ > + struct geni_se *se = &mas->se; > + u32 rx_fifo_status; > + unsigned int rx_bytes; > + unsigned int rx_last_byte_valid; > + u8 *rx_buf; > + unsigned int bytes_per_fifo_word = geni_byte_per_fifo_word(mas); > + unsigned int i = 0; > + > + rx_fifo_status = readl(se->base + SE_GENI_RX_FIFO_STATUS); > + rx_bytes = (rx_fifo_status & RX_FIFO_WC_MSK) * bytes_per_fifo_word; > + if (rx_fifo_status & RX_LAST) { > + rx_last_byte_valid = rx_fifo_status & RX_LAST_BYTE_VALID_MSK; > + rx_last_byte_valid >>= RX_LAST_BYTE_VALID_SHFT; > + if (rx_last_byte_valid && rx_last_byte_valid < 4) > + rx_bytes -= bytes_per_fifo_word - rx_last_byte_valid; > + } > + if (mas->rx_rem_bytes < rx_bytes) > + rx_bytes = mas->rx_rem_bytes; > + > + rx_buf = mas->cur_xfer->rx_buf + mas->cur_xfer->len - mas->rx_rem_bytes; > + while (i < rx_bytes) { > + u32 fifo_word = 0; > + u8 *fifo_byte = (u8 *)&fifo_word; > + unsigned int bytes_to_read; > + unsigned int j; > + > + bytes_to_read = min(bytes_per_fifo_word, rx_bytes - i); > + ioread32_rep(se->base + SE_GENI_RX_FIFOn, &fifo_word, 1); > + for (j = 0; j < bytes_to_read; j++) > + rx_buf[i++] = fifo_byte[j]; > + } > + mas->rx_rem_bytes -= rx_bytes; > +} > + > static void setup_fifo_xfer(struct spi_transfer *xfer, > struct spi_geni_master *mas, > u16 mode, struct spi_master *spi) > @@ -398,8 +480,10 @@ static void setup_fifo_xfer(struct spi_transfer *xfer, > * setting up GENI SE engine, as driver starts data transfer > * for the watermark interrupt. > */ > - if (m_cmd & SPI_TX_ONLY) > - writel(mas->tx_wm, se->base + SE_GENI_TX_WATERMARK_REG); > + if (m_cmd & SPI_TX_ONLY) { > + if (geni_spi_handle_tx(mas)) > + writel(mas->tx_wm, se->base + SE_GENI_TX_WATERMARK_REG); > + } > spin_unlock_irq(&mas->lock); > } > > @@ -417,85 +501,6 @@ static int spi_geni_transfer_one(struct spi_master *spi, > return 1; > } > > -static unsigned int geni_byte_per_fifo_word(struct spi_geni_master *mas) > -{ > - /* > - * Calculate how many bytes we'll put in each FIFO word. If the > - * transfer words don't pack cleanly into a FIFO word we'll just put > - * one transfer word in each FIFO word. If they do pack we'll pack 'em. > - */ > - if (mas->fifo_width_bits % mas->cur_bits_per_word) > - return roundup_pow_of_two(DIV_ROUND_UP(mas->cur_bits_per_word, > - BITS_PER_BYTE)); > - > - return mas->fifo_width_bits / BITS_PER_BYTE; > -} > - > -static void geni_spi_handle_tx(struct spi_geni_master *mas) > -{ > - struct geni_se *se = &mas->se; > - unsigned int max_bytes; > - const u8 *tx_buf; > - unsigned int bytes_per_fifo_word = geni_byte_per_fifo_word(mas); > - unsigned int i = 0; > - > - max_bytes = (mas->tx_fifo_depth - mas->tx_wm) * bytes_per_fifo_word; > - if (mas->tx_rem_bytes < max_bytes) > - max_bytes = mas->tx_rem_bytes; > - > - tx_buf = mas->cur_xfer->tx_buf + mas->cur_xfer->len - mas->tx_rem_bytes; > - while (i < max_bytes) { > - unsigned int j; > - unsigned int bytes_to_write; > - u32 fifo_word = 0; > - u8 *fifo_byte = (u8 *)&fifo_word; > - > - bytes_to_write = min(bytes_per_fifo_word, max_bytes - i); > - for (j = 0; j < bytes_to_write; j++) > - fifo_byte[j] = tx_buf[i++]; > - iowrite32_rep(se->base + SE_GENI_TX_FIFOn, &fifo_word, 1); > - } > - mas->tx_rem_bytes -= max_bytes; > - if (!mas->tx_rem_bytes) > - writel(0, se->base + SE_GENI_TX_WATERMARK_REG); > -} > - > -static void geni_spi_handle_rx(struct spi_geni_master *mas) > -{ > - struct geni_se *se = &mas->se; > - u32 rx_fifo_status; > - unsigned int rx_bytes; > - unsigned int rx_last_byte_valid; > - u8 *rx_buf; > - unsigned int bytes_per_fifo_word = geni_byte_per_fifo_word(mas); > - unsigned int i = 0; > - > - rx_fifo_status = readl(se->base + SE_GENI_RX_FIFO_STATUS); > - rx_bytes = (rx_fifo_status & RX_FIFO_WC_MSK) * bytes_per_fifo_word; > - if (rx_fifo_status & RX_LAST) { > - rx_last_byte_valid = rx_fifo_status & RX_LAST_BYTE_VALID_MSK; > - rx_last_byte_valid >>= RX_LAST_BYTE_VALID_SHFT; > - if (rx_last_byte_valid && rx_last_byte_valid < 4) > - rx_bytes -= bytes_per_fifo_word - rx_last_byte_valid; > - } > - if (mas->rx_rem_bytes < rx_bytes) > - rx_bytes = mas->rx_rem_bytes; > - > - rx_buf = mas->cur_xfer->rx_buf + mas->cur_xfer->len - mas->rx_rem_bytes; > - while (i < rx_bytes) { > - u32 fifo_word = 0; > - u8 *fifo_byte = (u8 *)&fifo_word; > - unsigned int bytes_to_read; > - unsigned int j; > - > - bytes_to_read = min(bytes_per_fifo_word, rx_bytes - i); > - ioread32_rep(se->base + SE_GENI_RX_FIFOn, &fifo_word, 1); > - for (j = 0; j < bytes_to_read; j++) > - rx_buf[i++] = fifo_byte[j]; > - } > - mas->rx_rem_bytes -= rx_bytes; > -} > - > static irqreturn_t geni_spi_isr(int irq, void *data) > { > struct spi_master *spi = data; > -- > 2.28.0.618.gf4bc123cb7-goog >