On Tue, Nov 15, 2022 at 07:30:09PM +0200, Ilpo Järvinen wrote: > On Tue, 15 Nov 2022, Gabriel L. Somlo wrote: > > > On Tue, Nov 15, 2022 at 06:14:50PM +0200, Ilpo Järvinen wrote: > > > On Sat, 12 Nov 2022, Gabriel Somlo wrote: > > > > > > > Modify the TX path to operate in an IRQ-compatible way, while > > > > maintaining support for polling mode via the poll timer. > > > > > > > > Signed-off-by: Gabriel Somlo <gsomlo@xxxxxxxxx> > > > > --- > > > > drivers/tty/serial/liteuart.c | 67 ++++++++++++++++++++++++----------- > > > > 1 file changed, 47 insertions(+), 20 deletions(-) > > > > > > > > diff --git a/drivers/tty/serial/liteuart.c b/drivers/tty/serial/liteuart.c > > > > index e30adb30277f..307c27398e30 100644 > > > > --- a/drivers/tty/serial/liteuart.c > > > > +++ b/drivers/tty/serial/liteuart.c > > > > > + if (port->irq) { > > > > + u8 irq_mask = litex_read8(port->membase + OFF_EV_ENABLE); > > > > + litex_write8(port->membase + OFF_EV_ENABLE, irq_mask & ~EV_TX); > > > > > > If you put irq_mask into liteuart_port you wouldn't need to read it > > > back here? > > > > So, instead of `bool poll_tx_started` I should just keep a copy of the > > irq_mask there, and take `&port->lock` whenever I need to *both* update > > the mask *and* write it out to the actual device register? > > I was mostly thinking of storing EV_RX there but then it could be derived > from port->irq that is checked by all paths already. I'm a bit confused here -- the reason I was reading in irq_mask from the mmio port and then flipping the EV_TX bit before writing it back out was to preserve the current value of the EV_RX bit in that register, whatever it may happen to be at the time. If I shadowed the entire register value (with both EV_RX and EV_TX bits reflecting their current value), I could get away with only ever *writing* the MMIO register each time the shadow register value is modified (one or both of the bits are flipped), and only when port->irq is non-zero (i.e., the shadow register would work for polling-mode also). I think that's how altera_uart.c is doing it (I've been using that as a source of inspiration). I thought that's what you were suggesting earlie, but based on your response above I'm no longer sure I follow. > > > > + if (unlikely(port->x_char)) { > > > > + litex_write8(port->membase + OFF_RXTX, port->x_char); > > > > + port->x_char = 0; > > > > + port->icount.tx++; > > > > + return; > > > > + } > > > > + > > > > + while (!litex_read8(port->membase + OFF_TXFULL)) { > > > > + if (xmit->head == xmit->tail) > > > > > > There exists a helper for this condition. > > > > Is that in the released linus tree, or still only in tty-next? > > uart_circ_empty() has been around for ages. Oh, I misunderstood what you meant here originally -- just use `uart_circ_empty()` like I'm already doing elsewhere in the code, got it! > > > > + if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) > > > > + uart_write_wakeup(port); > > > > + > > > > + if (uart_circ_empty(xmit)) > > > > + liteuart_stop_tx(port); > > > > +} > > > > > > You might want to check if you can generate this whole function with > > > Jiri's tx helpers (IIRC, they're only in tty-next tree currently). > > > > Looks like I should switch to tty-next for this whole series, which > > makes sense, since it's a tty I'm working on :) > > > > I'll rebase on top of that before I send out v4, hopefully later this > > afternoon. > > Ok. > > As I now looked it up, Jiri's tx helpers is > 8275b48b278096edc1e3ea5aa9cf946a10022f79 and you'll find some example > conversions in the changes following it. I'll check that out and follow the examples. Thanks again, --G