All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH] serial: 8250_dw: preserve BUSY-safe fractional divisor programming
@ 2026-10-24  5:50 James Hilliard
  2026-10-24  5:57 ` sashiko-bot
  2026-10-24 14:14 ` Andy Shevchenko
  0 siblings, 2 replies; 3+ messages in thread
From: James Hilliard @ 2026-10-24  5:50 UTC (permalink / raw)
  To: Greg Kroah-Hartman, Jiri Slaby, Ilpo Järvinen
  Cc: Andy Shevchenko, Raul E Rangel, Heikki Krogerus, linux-serial,
	linux-kernel, stable, James Hilliard

dw8250_probe() installs a divisor setter that makes the UART idle and
checks DLAB before writing DLL and DLH. When dw8250_setup_port() detects
fractional-divisor support, it replaces that setter with the library's
callback. The replacement writes DLF and uses serial8250_do_set_divisor(),
bypassing the divisor setter's idle sequence and DLAB readback.

If the LCR update fails to set DLAB, the subsequent divisor writes can
reach TX and IER instead of DLL and DLH.

Install the BUSY-safe setter after hardware discovery and extend it to
write DLF when fractional divisors are supported. Program both divisor
fields only after DLAB has been confirmed, retaining the fractional
divisor calculation selected by dw8250_setup_port().

Fixes: a7b9ce39fbe4 ("serial: 8250_dw: Ensure BUSY is deasserted")
Cc: stable@vger.kernel.org
Signed-off-by: James Hilliard <james.hilliard1@gmail.com>
---
Previously included in the DMA cancellation series v4:
https://lore.kernel.org/r/20261023-submit-serial-8250-dma-cancel-v1-v4-0-e759de1839de@gmail.com

Changes in DMA cancellation v4:
- Keep DesignWare's BUSY-safe divisor setter after fractional-divisor
  discovery, writing DLF and DLL/DLH only after confirming DLAB.
- Link to v3: https://patch.msgid.link/20261023-submit-serial-8250-dma-cancel-v1-v3-0-d78f9e4c4932@gmail.com
---
 drivers/tty/serial/8250/8250_dw.c | 7 ++++++-
 1 file changed, 6 insertions(+), 1 deletion(-)

diff --git a/drivers/tty/serial/8250/8250_dw.c b/drivers/tty/serial/8250/8250_dw.c
index eca02e8bd6d1..7b7dfad583fe 100644
--- a/drivers/tty/serial/8250/8250_dw.c
+++ b/drivers/tty/serial/8250/8250_dw.c
@@ -190,6 +190,7 @@ static int dw8250_idle_enter(struct uart_port *p)
 static void dw8250_set_divisor(struct uart_port *p, unsigned int baud,
 			       unsigned int quot, unsigned int quot_frac)
 {
+	struct dw8250_port_data *pd = p->private_data;
 	struct uart_8250_port *up = up_to_u8250p(p);
 	int ret;
 
@@ -201,6 +202,8 @@ static void dw8250_set_divisor(struct uart_port *p, unsigned int baud,
 	if (!(serial_port_in(p, UART_LCR) & UART_LCR_DLAB))
 		goto idle_failed;
 
+	if (pd->dlf_size)
+		dw8250_writel_ext(p, DW_UART_DLF, quot_frac);
 	serial_dl_write(up, quot);
 	serial_port_out(p, UART_LCR, up->lcr);
 
@@ -651,7 +654,6 @@ static int dw8250_probe(struct platform_device *pdev)
 
 	p->set_ldisc	= dw8250_set_ldisc;
 	p->set_termios	= dw8250_set_termios;
-	p->set_divisor	= dw8250_set_divisor;
 
 	data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL);
 	if (!data)
@@ -768,6 +770,9 @@ static int dw8250_probe(struct platform_device *pdev)
 	if (!data->skip_autocfg)
 		dw8250_setup_port(p);
 
+	/* Use the BUSY-safe sequence for both integer and fractional divisors. */
+	p->set_divisor = dw8250_set_divisor;
+
 	/* If we have a valid fifosize, try hooking up DMA */
 	if (p->fifosize) {
 		data->data.dma.rxconf.src_maxburst = p->fifosize / 4;

---
base-commit: 1184f87e2790e8af9be3116f608d2e86b4792d7d
change-id: 20261023-submit-serial-8250-dw-divisor-v1-5f1689ed05a8

Best regards,
--  
James Hilliard <james.hilliard1@gmail.com>


^ permalink raw reply related	[flat|nested] 3+ messages in thread

* Re: [PATCH] serial: 8250_dw: preserve BUSY-safe fractional divisor programming
  2026-10-24  5:50 [PATCH] serial: 8250_dw: preserve BUSY-safe fractional divisor programming James Hilliard
@ 2026-10-24  5:57 ` sashiko-bot
  2026-10-24 14:14 ` Andy Shevchenko
  1 sibling, 0 replies; 3+ messages in thread
From: sashiko-bot @ 2026-10-24  5:57 UTC (permalink / raw)
  To: James Hilliard; +Cc: linux-serial

> dw8250_probe() installs a divisor setter that makes the UART idle and
> checks DLAB before writing DLL and DLH. When dw8250_setup_port() detects
> fractional-divisor support, it replaces that setter with the library's
> callback. The replacement writes DLF and uses serial8250_do_set_divisor(),
> bypassing the divisor setter's idle sequence and DLAB readback.
> 
> If the LCR update fails to set DLAB, the subsequent divisor writes can
> reach TX and IER instead of DLL and DLH.
> 
> Install the BUSY-safe setter after hardware discovery and extend it to
> write DLF when fractional divisors are supported. Program both divisor
> fields only after DLAB has been confirmed, retaining the fractional
> divisor calculation selected by dw8250_setup_port().
> 
> Fixes: a7b9ce39fbe4 ("serial: 8250_dw: Ensure BUSY is deasserted")
> Cc: stable@vger.kernel.org
> Signed-off-by: James Hilliard <james.hilliard1@gmail.com>

Sashiko has reviewed this patch and found no issues.

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20261023-submit-serial-8250-dw-divisor-v1-v1-1-f452d4bb1b1f@gmail.com?part=1


^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: [PATCH] serial: 8250_dw: preserve BUSY-safe fractional divisor programming
  2026-10-24  5:50 [PATCH] serial: 8250_dw: preserve BUSY-safe fractional divisor programming James Hilliard
  2026-10-24  5:57 ` sashiko-bot
@ 2026-10-24 14:14 ` Andy Shevchenko
  1 sibling, 0 replies; 3+ messages in thread
From: Andy Shevchenko @ 2026-10-24 14:14 UTC (permalink / raw)
  To: James Hilliard
  Cc: Greg Kroah-Hartman, Jiri Slaby, Ilpo Järvinen, Raul E Rangel,
	Heikki Krogerus, linux-serial, linux-kernel, stable

On Fri, Oct 23, 2026 at 11:50:17PM -0600, James Hilliard wrote:
> dw8250_probe() installs a divisor setter that makes the UART idle and
> checks DLAB before writing DLL and DLH. When dw8250_setup_port() detects
> fractional-divisor support, it replaces that setter with the library's
> callback. The replacement writes DLF and uses serial8250_do_set_divisor(),
> bypassing the divisor setter's idle sequence and DLAB readback.
> 
> If the LCR update fails to set DLAB, the subsequent divisor writes can
> reach TX and IER instead of DLL and DLH.
> 
> Install the BUSY-safe setter after hardware discovery and extend it to
> write DLF when fractional divisors are supported. Program both divisor
> fields only after DLAB has been confirmed, retaining the fractional
> divisor calculation selected by dw8250_setup_port().

...

> static void dw8250_set_divisor(struct uart_port *p, unsigned int baud,

>  	if (!(serial_port_in(p, UART_LCR) & UART_LCR_DLAB))
>  		goto idle_failed;
>  
> +	if (pd->dlf_size)
> +		dw8250_writel_ext(p, DW_UART_DLF, quot_frac);

I still think it's better to export dw8250_?et_divisor_dfl() from dwlib and use
both here.

In dwlib:

unsigned int dw8250_get_divisor_dfl(struct uart_port *p, unsigned int baud,
                                    unsigned int *frac)
{
        unsigned int quot, rem, base_baud = baud * 16;
        struct dw8250_port_data *d = p->private_data;

        quot = p->uartclk / base_baud;
        rem = p->uartclk % base_baud;
        *frac = DIV_ROUND_CLOSEST(rem << d->dlf_size, base_baud);

        return quot;
}

void dw8250_set_divisor_dfl(struct uart_port *p, unsigned int baud,
                            unsigned int quot, unsigned int quot_frac)
{
        dw8250_writel_ext(p, DW_UART_DLF, quot_frac);
}


static unsigned int dw8250_get_divisor(struct uart_port *p, unsigned int baud,
                                       unsigned int *frac)
{
        return dw8250_get_divisor_dfl(p, baud, frac);
}

static void dw8250_set_divisor(struct uart_port *p, unsigned int baud,
                               unsigned int quot, unsigned int quot_frac)
{
	dw8250_set_divisor_dfl(p, baud, quot, quot_frac);

        serial8250_do_set_divisor(p, baud, quot);
}

In dw:

static unsigned int dw8250_get_divisor(struct uart_port *p, unsigned int baud,
                                       unsigned int *frac)
{
        return dw8250_get_divisor_dfl(p, baud, frac);
}

static void dw8250_set_divisor(struct uart_port *p, unsigned int baud,
                               unsigned int quot, unsigned int quot_frac)
{
	...
	if (pd->dfl_size)
		dw8250_set_divisor_dfl(p, baud, quot, quot_frac);
	...
}

...

> +	/* Use the BUSY-safe sequence for both integer and fractional divisors. */

...and here

	p->get_divisor = dw8250_get_divisor;

> +	p->set_divisor = dw8250_set_divisor;


-- 
With Best Regards,
Andy Shevchenko



^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2026-10-24 14:14 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-10-24  5:50 [PATCH] serial: 8250_dw: preserve BUSY-safe fractional divisor programming James Hilliard
2026-10-24  5:57 ` sashiko-bot
2026-10-24 14:14 ` Andy Shevchenko

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.