Skip to content

Commit

Permalink
Merge tag 'tty-6.14-rc3' of git://git.kernel.org/pub/scm/linux/kernel…
Browse files Browse the repository at this point in the history
…/git/gregkh/tty

Pull serial driver fixes from Greg KH:
 "Here are some small serial driver fixes for some reported problems.
  Nothing major, just:

   - sc16is7xx irq check fix

   - 8250 fifo underflow fix

   - serial_port and 8250 iotype fixes

  Most of these have been in linux-next already, and all have passed
  0-day testing"

* tag 'tty-6.14-rc3' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty:
  serial: 8250: Fix fifo underflow on flush
  serial: 8250_pnp: Remove unneeded ->iotype assignment
  serial: 8250_platform: Remove unneeded ->iotype assignment
  serial: 8250_of: Remove unneeded ->iotype assignment
  serial: port: Make ->iotype validation global in __uart_read_properties()
  serial: port: Always update ->iotype in __uart_read_properties()
  serial: port: Assign ->iotype correctly when ->iobase is set
  serial: sc16is7xx: Fix IRQ number check behavior
  • Loading branch information
torvalds committed Feb 16, 2025
2 parents 6bfcc5f + 9e512ea commit 5640039
Show file tree
Hide file tree
Showing 8 changed files with 35 additions and 26 deletions.
2 changes: 2 additions & 0 deletions drivers/tty/serial/8250/8250.h
Original file line number Diff line number Diff line change
Expand Up @@ -374,6 +374,7 @@ static inline int is_omap1510_8250(struct uart_8250_port *pt)

#ifdef CONFIG_SERIAL_8250_DMA
extern int serial8250_tx_dma(struct uart_8250_port *);
extern void serial8250_tx_dma_flush(struct uart_8250_port *);
extern int serial8250_rx_dma(struct uart_8250_port *);
extern void serial8250_rx_dma_flush(struct uart_8250_port *);
extern int serial8250_request_dma(struct uart_8250_port *);
Expand Down Expand Up @@ -406,6 +407,7 @@ static inline int serial8250_tx_dma(struct uart_8250_port *p)
{
return -1;
}
static inline void serial8250_tx_dma_flush(struct uart_8250_port *p) { }
static inline int serial8250_rx_dma(struct uart_8250_port *p)
{
return -1;
Expand Down
16 changes: 16 additions & 0 deletions drivers/tty/serial/8250/8250_dma.c
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,22 @@ int serial8250_tx_dma(struct uart_8250_port *p)
return ret;
}

void serial8250_tx_dma_flush(struct uart_8250_port *p)
{
struct uart_8250_dma *dma = p->dma;

if (!dma->tx_running)
return;

/*
* kfifo_reset() has been called by the serial core, avoid
* advancing and underflowing in __dma_tx_complete().
*/
dma->tx_size = 0;

dmaengine_terminate_async(dma->rxchan);
}

int serial8250_rx_dma(struct uart_8250_port *p)
{
struct uart_8250_dma *dma = p->dma;
Expand Down
1 change: 0 additions & 1 deletion drivers/tty/serial/8250/8250_of.c
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,6 @@ static int of_platform_serial_setup(struct platform_device *ofdev,
spin_lock_init(&port->lock);

if (resource_type(&resource) == IORESOURCE_IO) {
port->iotype = UPIO_PORT;
port->iobase = resource.start;
} else {
port->mapbase = resource.start;
Expand Down
9 changes: 0 additions & 9 deletions drivers/tty/serial/8250/8250_platform.c
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,6 @@ static int serial8250_probe_acpi(struct platform_device *pdev)
struct device *dev = &pdev->dev;
struct uart_8250_port uart = { };
struct resource *regs;
unsigned char iotype;
int ret, line;

regs = platform_get_mem_or_io(pdev, 0);
Expand All @@ -122,13 +121,11 @@ static int serial8250_probe_acpi(struct platform_device *pdev)
switch (resource_type(regs)) {
case IORESOURCE_IO:
uart.port.iobase = regs->start;
iotype = UPIO_PORT;
break;
case IORESOURCE_MEM:
uart.port.mapbase = regs->start;
uart.port.mapsize = resource_size(regs);
uart.port.flags = UPF_IOREMAP;
iotype = UPIO_MEM;
break;
default:
return -EINVAL;
Expand All @@ -147,12 +144,6 @@ static int serial8250_probe_acpi(struct platform_device *pdev)
if (ret)
return ret;

/*
* The previous call may not set iotype correctly when reg-io-width
* property is absent and it doesn't support IO port resource.
*/
uart.port.iotype = iotype;

line = serial8250_register_8250_port(&uart);
if (line < 0)
return line;
Expand Down
10 changes: 0 additions & 10 deletions drivers/tty/serial/8250/8250_pnp.c
Original file line number Diff line number Diff line change
Expand Up @@ -436,7 +436,6 @@ serial_pnp_probe(struct pnp_dev *dev, const struct pnp_device_id *dev_id)
{
struct uart_8250_port uart, *port;
int ret, flags = dev_id->driver_data;
unsigned char iotype;
long line;

if (flags & UNKNOWN_DEV) {
Expand All @@ -448,14 +447,11 @@ serial_pnp_probe(struct pnp_dev *dev, const struct pnp_device_id *dev_id)
memset(&uart, 0, sizeof(uart));
if ((flags & CIR_PORT) && pnp_port_valid(dev, 2)) {
uart.port.iobase = pnp_port_start(dev, 2);
iotype = UPIO_PORT;
} else if (pnp_port_valid(dev, 0)) {
uart.port.iobase = pnp_port_start(dev, 0);
iotype = UPIO_PORT;
} else if (pnp_mem_valid(dev, 0)) {
uart.port.mapbase = pnp_mem_start(dev, 0);
uart.port.mapsize = pnp_mem_len(dev, 0);
iotype = UPIO_MEM;
uart.port.flags = UPF_IOREMAP;
} else
return -ENODEV;
Expand All @@ -471,12 +467,6 @@ serial_pnp_probe(struct pnp_dev *dev, const struct pnp_device_id *dev_id)
if (ret)
return ret;

/*
* The previous call may not set iotype correctly when reg-io-width
* property is absent and it doesn't support IO port resource.
*/
uart.port.iotype = iotype;

if (flags & CIR_PORT) {
uart.port.flags |= UPF_FIXED_PORT | UPF_FIXED_TYPE;
uart.port.type = PORT_8250_CIR;
Expand Down
9 changes: 9 additions & 0 deletions drivers/tty/serial/8250/8250_port.c
Original file line number Diff line number Diff line change
Expand Up @@ -2555,6 +2555,14 @@ static void serial8250_shutdown(struct uart_port *port)
serial8250_do_shutdown(port);
}

static void serial8250_flush_buffer(struct uart_port *port)
{
struct uart_8250_port *up = up_to_u8250p(port);

if (up->dma)
serial8250_tx_dma_flush(up);
}

static unsigned int serial8250_do_get_divisor(struct uart_port *port,
unsigned int baud,
unsigned int *frac)
Expand Down Expand Up @@ -3244,6 +3252,7 @@ static const struct uart_ops serial8250_pops = {
.break_ctl = serial8250_break_ctl,
.startup = serial8250_startup,
.shutdown = serial8250_shutdown,
.flush_buffer = serial8250_flush_buffer,
.set_termios = serial8250_set_termios,
.set_ldisc = serial8250_set_ldisc,
.pm = serial8250_pm,
Expand Down
2 changes: 1 addition & 1 deletion drivers/tty/serial/sc16is7xx.c
Original file line number Diff line number Diff line change
Expand Up @@ -1561,7 +1561,7 @@ int sc16is7xx_probe(struct device *dev, const struct sc16is7xx_devtype *devtype,
/* Always ask for fixed clock rate from a property. */
device_property_read_u32(dev, "clock-frequency", &uartclk);

s->polling = !!irq;
s->polling = (irq <= 0);
if (s->polling)
dev_dbg(dev,
"No interrupt pin definition, falling back to polling mode\n");
Expand Down
12 changes: 7 additions & 5 deletions drivers/tty/serial/serial_port.c
Original file line number Diff line number Diff line change
Expand Up @@ -173,6 +173,7 @@ EXPORT_SYMBOL(uart_remove_one_port);
* The caller is responsible to initialize the following fields of the @port
* ->dev (must be valid)
* ->flags
* ->iobase
* ->mapbase
* ->mapsize
* ->regshift (if @use_defaults is false)
Expand Down Expand Up @@ -214,7 +215,7 @@ static int __uart_read_properties(struct uart_port *port, bool use_defaults)
/* Read the registers I/O access type (default: MMIO 8-bit) */
ret = device_property_read_u32(dev, "reg-io-width", &value);
if (ret) {
port->iotype = UPIO_MEM;
port->iotype = port->iobase ? UPIO_PORT : UPIO_MEM;
} else {
switch (value) {
case 1:
Expand All @@ -227,15 +228,16 @@ static int __uart_read_properties(struct uart_port *port, bool use_defaults)
port->iotype = device_is_big_endian(dev) ? UPIO_MEM32BE : UPIO_MEM32;
break;
default:
if (!use_defaults) {
dev_err(dev, "Unsupported reg-io-width (%u)\n", value);
return -EINVAL;
}
port->iotype = UPIO_UNKNOWN;
break;
}
}

if (!use_defaults && port->iotype == UPIO_UNKNOWN) {
dev_err(dev, "Unsupported reg-io-width (%u)\n", value);
return -EINVAL;
}

/* Read the address mapping base offset (default: no offset) */
ret = device_property_read_u32(dev, "reg-offset", &value);
if (ret)
Expand Down

0 comments on commit 5640039

Please sign in to comment.