diff options
Diffstat (limited to 'drivers/tty/serial/8250/8250_port.c')
| -rw-r--r-- | drivers/tty/serial/8250/8250_port.c | 1136 |
1 files changed, 543 insertions, 593 deletions
diff --git a/drivers/tty/serial/8250/8250_port.c b/drivers/tty/serial/8250/8250_port.c index 893bc493f662..719faf92aa8a 100644 --- a/drivers/tty/serial/8250/8250_port.c +++ b/drivers/tty/serial/8250/8250_port.c @@ -39,15 +39,6 @@ #include "8250.h" /* - * Debugging. - */ -#if 0 -#define DEBUG_AUTOCONF(fmt...) printk(fmt) -#else -#define DEBUG_AUTOCONF(fmt...) do { } while (0) -#endif - -/* * Here we define the default xmit fifo size used for each type of UART. */ static const struct serial8250_config uart_config[] = { @@ -338,79 +329,91 @@ static void default_serial_dl_write(struct uart_8250_port *up, u32 value) serial_out(up, UART_DLM, value >> 8 & 0xff); } -static unsigned int hub6_serial_in(struct uart_port *p, int offset) +#ifdef CONFIG_HAS_IOPORT +static u32 hub6_serial_in(struct uart_port *p, unsigned int offset) { offset = offset << p->regshift; outb(p->hub6 - 1 + offset, p->iobase); return inb(p->iobase + 1); } -static void hub6_serial_out(struct uart_port *p, int offset, int value) +static void hub6_serial_out(struct uart_port *p, unsigned int offset, u32 value) { offset = offset << p->regshift; outb(p->hub6 - 1 + offset, p->iobase); outb(value, p->iobase + 1); } +#endif /* CONFIG_HAS_IOPORT */ -static unsigned int mem_serial_in(struct uart_port *p, int offset) +static u32 mem_serial_in(struct uart_port *p, unsigned int offset) { offset = offset << p->regshift; return readb(p->membase + offset); } -static void mem_serial_out(struct uart_port *p, int offset, int value) +static void mem_serial_out(struct uart_port *p, unsigned int offset, u32 value) { offset = offset << p->regshift; writeb(value, p->membase + offset); } -static void mem16_serial_out(struct uart_port *p, int offset, int value) +static void mem16_serial_out(struct uart_port *p, unsigned int offset, u32 value) { offset = offset << p->regshift; writew(value, p->membase + offset); } -static unsigned int mem16_serial_in(struct uart_port *p, int offset) +static u32 mem16_serial_in(struct uart_port *p, unsigned int offset) { offset = offset << p->regshift; return readw(p->membase + offset); } -static void mem32_serial_out(struct uart_port *p, int offset, int value) +static void mem32_serial_out(struct uart_port *p, unsigned int offset, u32 value) { offset = offset << p->regshift; writel(value, p->membase + offset); } -static unsigned int mem32_serial_in(struct uart_port *p, int offset) +static u32 mem32_serial_in(struct uart_port *p, unsigned int offset) { offset = offset << p->regshift; return readl(p->membase + offset); } -static void mem32be_serial_out(struct uart_port *p, int offset, int value) +static void mem32be_serial_out(struct uart_port *p, unsigned int offset, u32 value) { offset = offset << p->regshift; iowrite32be(value, p->membase + offset); } -static unsigned int mem32be_serial_in(struct uart_port *p, int offset) +static u32 mem32be_serial_in(struct uart_port *p, unsigned int offset) { offset = offset << p->regshift; return ioread32be(p->membase + offset); } -static unsigned int io_serial_in(struct uart_port *p, int offset) +#ifdef CONFIG_HAS_IOPORT +static u32 io_serial_in(struct uart_port *p, unsigned int offset) { offset = offset << p->regshift; return inb(p->iobase + offset); } -static void io_serial_out(struct uart_port *p, int offset, int value) +static void io_serial_out(struct uart_port *p, unsigned int offset, u32 value) { offset = offset << p->regshift; outb(value, p->iobase + offset); } +#endif +static u32 no_serial_in(struct uart_port *p, unsigned int offset) +{ + return ~0U; +} + +static void no_serial_out(struct uart_port *p, unsigned int offset, u32 value) +{ +} static int serial8250_default_handle_irq(struct uart_port *port); @@ -422,10 +425,12 @@ static void set_io_from_upio(struct uart_port *p) up->dl_write = default_serial_dl_write; switch (p->iotype) { +#ifdef CONFIG_HAS_IOPORT case UPIO_HUB6: p->serial_in = hub6_serial_in; p->serial_out = hub6_serial_out; break; +#endif case UPIO_MEM: p->serial_in = mem_serial_in; @@ -446,11 +451,17 @@ static void set_io_from_upio(struct uart_port *p) p->serial_in = mem32be_serial_in; p->serial_out = mem32be_serial_out; break; - - default: +#ifdef CONFIG_HAS_IOPORT + case UPIO_PORT: p->serial_in = io_serial_in; p->serial_out = io_serial_out; break; +#endif + default: + WARN(p->iotype != UPIO_PORT || p->iobase, + "Unsupported UART type %x\n", p->iotype); + p->serial_in = no_serial_in; + p->serial_out = no_serial_out; } /* Remember loaded iotype */ up->cur_iotype = p->iotype; @@ -546,19 +557,17 @@ static int serial8250_em485_init(struct uart_8250_port *p) if (!p->em485) return -ENOMEM; - hrtimer_init(&p->em485->stop_tx_timer, CLOCK_MONOTONIC, - HRTIMER_MODE_REL); - hrtimer_init(&p->em485->start_tx_timer, CLOCK_MONOTONIC, - HRTIMER_MODE_REL); - p->em485->stop_tx_timer.function = &serial8250_em485_handle_stop_tx; - p->em485->start_tx_timer.function = &serial8250_em485_handle_start_tx; + hrtimer_setup(&p->em485->stop_tx_timer, &serial8250_em485_handle_stop_tx, CLOCK_MONOTONIC, + HRTIMER_MODE_REL); + hrtimer_setup(&p->em485->start_tx_timer, &serial8250_em485_handle_start_tx, CLOCK_MONOTONIC, + HRTIMER_MODE_REL); p->em485->port = p; p->em485->active_timer = NULL; p->em485->tx_stopped = true; deassert_rts: if (p->em485->tx_stopped) - p->rs485_stop_tx(p); + p->rs485_stop_tx(p, true); return 0; } @@ -629,7 +638,7 @@ EXPORT_SYMBOL_GPL(serial8250_em485_config); * once and disable_runtime_pm_tx() will still disable RPM because the fifo is * empty and the HW can idle again. */ -void serial8250_rpm_get_tx(struct uart_8250_port *p) +static void serial8250_rpm_get_tx(struct uart_8250_port *p) { unsigned char rpm_active; @@ -641,9 +650,8 @@ void serial8250_rpm_get_tx(struct uart_8250_port *p) return; pm_runtime_get_sync(p->port.dev); } -EXPORT_SYMBOL_GPL(serial8250_rpm_get_tx); -void serial8250_rpm_put_tx(struct uart_8250_port *p) +static void serial8250_rpm_put_tx(struct uart_8250_port *p) { unsigned char rpm_active; @@ -656,7 +664,6 @@ void serial8250_rpm_put_tx(struct uart_8250_port *p) pm_runtime_mark_last_busy(p->port.dev); pm_runtime_put_autosuspend(p->port.dev); } -EXPORT_SYMBOL_GPL(serial8250_rpm_put_tx); /* * IER sleep support. UARTs which have EFRs need the "extended @@ -667,106 +674,45 @@ static void serial8250_set_sleep(struct uart_8250_port *p, int sleep) { unsigned char lcr = 0, efr = 0; - serial8250_rpm_get(p); - - if (p->capabilities & UART_CAP_SLEEP) { - /* Synchronize UART_IER access against the console. */ - uart_port_lock_irq(&p->port); - if (p->capabilities & UART_CAP_EFR) { - lcr = serial_in(p, UART_LCR); - efr = serial_in(p, UART_EFR); - serial_out(p, UART_LCR, UART_LCR_CONF_MODE_B); - serial_out(p, UART_EFR, UART_EFR_ECB); - serial_out(p, UART_LCR, 0); - } - serial_out(p, UART_IER, sleep ? UART_IERX_SLEEP : 0); - if (p->capabilities & UART_CAP_EFR) { - serial_out(p, UART_LCR, UART_LCR_CONF_MODE_B); - serial_out(p, UART_EFR, efr); - serial_out(p, UART_LCR, lcr); - } - uart_port_unlock_irq(&p->port); - } - - serial8250_rpm_put(p); -} + guard(serial8250_rpm)(p); -static void serial8250_clear_IER(struct uart_8250_port *up) -{ - if (up->capabilities & UART_CAP_UUE) - serial_out(up, UART_IER, UART_IER_UUE); - else - serial_out(up, UART_IER, 0); -} - -#ifdef CONFIG_SERIAL_8250_RSA -/* - * Attempts to turn on the RSA FIFO. Returns zero on failure. - * We set the port uart clock rate if we succeed. - */ -static int __enable_rsa(struct uart_8250_port *up) -{ - unsigned char mode; - int result; + if (!(p->capabilities & UART_CAP_SLEEP)) + return; - mode = serial_in(up, UART_RSA_MSR); - result = mode & UART_RSA_MSR_FIFO; + /* Synchronize UART_IER access against the console. */ + guard(uart_port_lock_irq)(&p->port); - if (!result) { - serial_out(up, UART_RSA_MSR, mode | UART_RSA_MSR_FIFO); - mode = serial_in(up, UART_RSA_MSR); - result = mode & UART_RSA_MSR_FIFO; + if (p->capabilities & UART_CAP_EFR) { + lcr = serial_in(p, UART_LCR); + efr = serial_in(p, UART_EFR); + serial_out(p, UART_LCR, UART_LCR_CONF_MODE_B); + serial_out(p, UART_EFR, UART_EFR_ECB); + serial_out(p, UART_LCR, 0); + } + serial_out(p, UART_IER, sleep ? UART_IERX_SLEEP : 0); + if (p->capabilities & UART_CAP_EFR) { + serial_out(p, UART_LCR, UART_LCR_CONF_MODE_B); + serial_out(p, UART_EFR, efr); + serial_out(p, UART_LCR, lcr); } - - if (result) - up->port.uartclk = SERIAL_RSA_BAUD_BASE * 16; - - return result; } -static void enable_rsa(struct uart_8250_port *up) +/* Clear the interrupt registers. */ +static void serial8250_clear_interrupts(struct uart_port *port) { - if (up->port.type == PORT_RSA) { - if (up->port.uartclk != SERIAL_RSA_BAUD_BASE * 16) { - uart_port_lock_irq(&up->port); - __enable_rsa(up); - uart_port_unlock_irq(&up->port); - } - if (up->port.uartclk == SERIAL_RSA_BAUD_BASE * 16) - serial_out(up, UART_RSA_FRR, 0); - } + serial_port_in(port, UART_LSR); + serial_port_in(port, UART_RX); + serial_port_in(port, UART_IIR); + serial_port_in(port, UART_MSR); } -/* - * Attempts to turn off the RSA FIFO. Returns zero on failure. - * It is unknown why interrupts were disabled in here. However, - * the caller is expected to preserve this behaviour by grabbing - * the spinlock before calling this function. - */ -static void disable_rsa(struct uart_8250_port *up) +static void serial8250_clear_IER(struct uart_8250_port *up) { - unsigned char mode; - int result; - - if (up->port.type == PORT_RSA && - up->port.uartclk == SERIAL_RSA_BAUD_BASE * 16) { - uart_port_lock_irq(&up->port); - - mode = serial_in(up, UART_RSA_MSR); - result = !(mode & UART_RSA_MSR_FIFO); - - if (!result) { - serial_out(up, UART_RSA_MSR, mode & ~UART_RSA_MSR_FIFO); - mode = serial_in(up, UART_RSA_MSR); - result = !(mode & UART_RSA_MSR_FIFO); - } - - if (result) - up->port.uartclk = SERIAL_RSA_BAUD_BASE_LO * 16; - uart_port_unlock_irq(&up->port); - } + if (up->capabilities & UART_CAP_UUE) + serial_out(up, UART_IER, UART_IER_UUE); + else + serial_out(up, UART_IER, 0); } -#endif /* CONFIG_SERIAL_8250_RSA */ /* * This is a quickie test to see how big the FIFO is. @@ -871,8 +817,6 @@ static void autoconfig_has_efr(struct uart_8250_port *up) id3 = serial_icr_read(up, UART_ID3); rev = serial_icr_read(up, UART_REV); - DEBUG_AUTOCONF("950id=%02x:%02x:%02x:%02x ", id1, id2, id3, rev); - if (id1 == 0x16 && id2 == 0xC9 && (id3 == 0x50 || id3 == 0x52 || id3 == 0x54)) { up->port.type = PORT_16C950; @@ -896,7 +840,6 @@ static void autoconfig_has_efr(struct uart_8250_port *up) * 0x14 - XR16C854. */ id1 = autoconfig_read_divisor_id(up); - DEBUG_AUTOCONF("850id=%04x ", id1); id2 = id1 >> 8; if (id2 == 0x10 || id2 == 0x12 || id2 == 0x14) { @@ -983,7 +926,6 @@ static void autoconfig_16550a(struct uart_8250_port *up) if (serial_in(up, UART_EFR) == 0) { serial_out(up, UART_EFR, 0xA8); if (serial_in(up, UART_EFR) != 0) { - DEBUG_AUTOCONF("EFRv1 "); up->port.type = PORT_16650; up->capabilities |= UART_CAP_EFR | UART_CAP_SLEEP; } else { @@ -996,8 +938,6 @@ static void autoconfig_16550a(struct uart_8250_port *up) if (status1 == UART_IIR_FIFO_ENABLED_16750) up->port.type = PORT_16550A_FSL64; - else - DEBUG_AUTOCONF("Motorola 8xxx DUART "); } serial_out(up, UART_EFR, 0); return; @@ -1009,7 +949,6 @@ static void autoconfig_16550a(struct uart_8250_port *up) */ serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B); if (serial_in(up, UART_EFR) == 0 && !broken_efr(up)) { - DEBUG_AUTOCONF("EFRv2 "); autoconfig_has_efr(up); return; } @@ -1072,8 +1011,6 @@ static void autoconfig_16550a(struct uart_8250_port *up) serial_out(up, UART_LCR, 0); - DEBUG_AUTOCONF("iir1=%d iir2=%d ", status1, status2); - if (status1 == UART_IIR_FIFO_ENABLED_16550A && status2 == UART_IIR_FIFO_ENABLED_16750) { up->port.type = PORT_16750; @@ -1102,17 +1039,10 @@ static void autoconfig_16550a(struct uart_8250_port *up) * It's an Xscale. * We'll leave the UART_IER_UUE bit set to 1 (enabled). */ - DEBUG_AUTOCONF("Xscale "); up->port.type = PORT_XSCALE; up->capabilities |= UART_CAP_UUE | UART_CAP_RTOIE; return; } - } else { - /* - * If we got here we couldn't force the IER_UUE bit to 0. - * Log it and continue. - */ - DEBUG_AUTOCONF("Couldn't force IER_UUE to 0 "); } serial_out(up, UART_IER, iersave); @@ -1144,9 +1074,6 @@ static void autoconfig(struct uart_8250_port *up) if (!port->iobase && !port->mapbase && !port->membase) return; - DEBUG_AUTOCONF("%s: autoconf (0x%04lx, 0x%p): ", - port->name, port->iobase, port->membase); - /* * We really do need global IRQs disabled here - we're going to * be frobbing the chips IRQ enable register to see if it exists. @@ -1174,7 +1101,7 @@ static void autoconfig(struct uart_8250_port *up) */ scratch = serial_in(up, UART_IER); serial_out(up, UART_IER, 0); -#ifdef __i386__ +#if defined(__i386__) && defined(CONFIG_HAS_IOPORT) outb(0xff, 0x080); #endif /* @@ -1183,7 +1110,7 @@ static void autoconfig(struct uart_8250_port *up) */ scratch2 = serial_in(up, UART_IER) & UART_IER_ALL_INTR; serial_out(up, UART_IER, UART_IER_ALL_INTR); -#ifdef __i386__ +#if defined(__i386__) && defined(CONFIG_HAS_IOPORT) outb(0, 0x080); #endif scratch3 = serial_in(up, UART_IER) & UART_IER_ALL_INTR; @@ -1193,9 +1120,7 @@ static void autoconfig(struct uart_8250_port *up) * We failed; there's nothing here */ uart_port_unlock_irqrestore(port, flags); - DEBUG_AUTOCONF("IER test failed (%02x, %02x) ", - scratch2, scratch3); - goto out; + return; } } @@ -1217,9 +1142,7 @@ static void autoconfig(struct uart_8250_port *up) serial8250_out_MCR(up, save_mcr); if (status1 != (UART_MSR_DCD | UART_MSR_CTS)) { uart_port_unlock_irqrestore(port, flags); - DEBUG_AUTOCONF("LOOP test failed (%02x) ", - status1); - goto out; + return; } } @@ -1253,14 +1176,7 @@ static void autoconfig(struct uart_8250_port *up) break; } -#ifdef CONFIG_SERIAL_8250_RSA - /* - * Only probe for RSA ports if we got the region. - */ - if (port->type == PORT_16550A && up->probe & UART_PROBE_RSA && - __enable_rsa(up)) - port->type = PORT_RSA; -#endif + rsa_autoconfig(up); serial_out(up, UART_LCR, save_lcr); @@ -1269,22 +1185,17 @@ static void autoconfig(struct uart_8250_port *up) up->capabilities = uart_config[port->type].flags; up->tx_loadsz = uart_config[port->type].tx_loadsz; - if (port->type == PORT_UNKNOWN) - goto out_unlock; - - /* - * Reset the UART. - */ -#ifdef CONFIG_SERIAL_8250_RSA - if (port->type == PORT_RSA) - serial_out(up, UART_RSA_FRR, 0); -#endif - serial8250_out_MCR(up, save_mcr); - serial8250_clear_fifos(up); - serial_in(up, UART_RX); - serial8250_clear_IER(up); + if (port->type != PORT_UNKNOWN) { + /* + * Reset the UART. + */ + rsa_reset(up); + serial8250_out_MCR(up, save_mcr); + serial8250_clear_fifos(up); + serial_in(up, UART_RX); + serial8250_clear_IER(up); + } -out_unlock: uart_port_unlock_irqrestore(port, flags); /* @@ -1297,9 +1208,6 @@ out_unlock: dev_warn(port->dev, "detected caps %08x should be %08x\n", old_capabilities, up->capabilities); } -out: - DEBUG_AUTOCONF("iir=%d ", scratch); - DEBUG_AUTOCONF("type=%s\n", uart_config[port->type].name); } static void autoconfig_irq(struct uart_8250_port *up) @@ -1322,9 +1230,8 @@ static void autoconfig_irq(struct uart_8250_port *up) probe_irq_off(probe_irq_on()); save_mcr = serial8250_in_MCR(up); /* Synchronize UART_IER access against the console. */ - uart_port_lock_irq(port); - save_ier = serial_in(up, UART_IER); - uart_port_unlock_irq(port); + scoped_guard(uart_port_lock_irq, port) + save_ier = serial_in(up, UART_IER); serial8250_out_MCR(up, UART_MCR_OUT1 | UART_MCR_OUT2); irqs = probe_irq_on(); @@ -1337,22 +1244,17 @@ static void autoconfig_irq(struct uart_8250_port *up) UART_MCR_DTR | UART_MCR_RTS | UART_MCR_OUT2); } /* Synchronize UART_IER access against the console. */ - uart_port_lock_irq(port); - serial_out(up, UART_IER, UART_IER_ALL_INTR); - uart_port_unlock_irq(port); - serial_in(up, UART_LSR); - serial_in(up, UART_RX); - serial_in(up, UART_IIR); - serial_in(up, UART_MSR); + scoped_guard(uart_port_lock_irq, port) + serial_out(up, UART_IER, UART_IER_ALL_INTR); + serial8250_clear_interrupts(port); serial_out(up, UART_TX, 0xFF); udelay(20); irq = probe_irq_off(irqs); serial8250_out_MCR(up, save_mcr); /* Synchronize UART_IER access against the console. */ - uart_port_lock_irq(port); - serial_out(up, UART_IER, save_ier); - uart_port_unlock_irq(port); + scoped_guard(uart_port_lock_irq, port) + serial_out(up, UART_IER, save_ier); if (port->flags & UPF_FOURPORT) outb_p(save_ICP, ICP); @@ -1367,22 +1269,20 @@ static void serial8250_stop_rx(struct uart_port *port) /* Port locked to synchronize UART_IER access against the console. */ lockdep_assert_held_once(&port->lock); - serial8250_rpm_get(up); + guard(serial8250_rpm)(up); up->ier &= ~(UART_IER_RLSI | UART_IER_RDI); - up->port.read_status_mask &= ~UART_LSR_DR; serial_port_out(port, UART_IER, up->ier); - - serial8250_rpm_put(up); } /** * serial8250_em485_stop_tx() - generic ->rs485_stop_tx() callback * @p: uart 8250 port + * @toggle_ier: true to allow enabling receive interrupts * * Generic callback usable by 8250 uart drivers to stop rs485 transmission. */ -void serial8250_em485_stop_tx(struct uart_8250_port *p) +void serial8250_em485_stop_tx(struct uart_8250_port *p, bool toggle_ier) { unsigned char mcr = serial8250_in_MCR(p); @@ -1403,8 +1303,10 @@ void serial8250_em485_stop_tx(struct uart_8250_port *p) if (!(p->port.rs485.flags & SER_RS485_RX_DURING_TX)) { serial8250_clear_and_reinit_fifos(p); - p->ier |= UART_IER_RLSI | UART_IER_RDI; - serial_port_out(&p->port, UART_IER, p->ier); + if (toggle_ier) { + p->ier |= UART_IER_RLSI | UART_IER_RDI; + serial_port_out(&p->port, UART_IER, p->ier); + } } } EXPORT_SYMBOL_GPL(serial8250_em485_stop_tx); @@ -1414,17 +1316,15 @@ static enum hrtimer_restart serial8250_em485_handle_stop_tx(struct hrtimer *t) struct uart_8250_em485 *em485 = container_of(t, struct uart_8250_em485, stop_tx_timer); struct uart_8250_port *p = em485->port; - unsigned long flags; - serial8250_rpm_get(p); - uart_port_lock_irqsave(&p->port, &flags); + guard(serial8250_rpm)(p); + guard(uart_port_lock_irqsave)(&p->port); + if (em485->active_timer == &em485->stop_tx_timer) { - p->rs485_stop_tx(p); + p->rs485_stop_tx(p, true); em485->active_timer = NULL; em485->tx_stopped = true; } - uart_port_unlock_irqrestore(&p->port, flags); - serial8250_rpm_put(p); return HRTIMER_NORESTART; } @@ -1451,7 +1351,7 @@ static void __stop_tx_rs485(struct uart_8250_port *p, u64 stop_delay) em485->active_timer = &em485->stop_tx_timer; hrtimer_start(&em485->stop_tx_timer, ns_to_ktime(stop_delay), HRTIMER_MODE_REL); } else { - p->rs485_stop_tx(p); + p->rs485_stop_tx(p, true); em485->active_timer = NULL; em485->tx_stopped = true; } @@ -1499,7 +1399,7 @@ static void serial8250_stop_tx(struct uart_port *port) { struct uart_8250_port *up = up_to_u8250p(port); - serial8250_rpm_get(up); + guard(serial8250_rpm)(up); __stop_tx(up); /* @@ -1509,7 +1409,6 @@ static void serial8250_stop_tx(struct uart_port *port) up->acr |= UART_ACR_TXDIS; serial_icr_write(up, UART_ACR, up->acr); } - serial8250_rpm_put(up); } static inline void __start_tx(struct uart_port *port) @@ -1540,6 +1439,7 @@ static inline void __start_tx(struct uart_port *port) /** * serial8250_em485_start_tx() - generic ->rs485_start_tx() callback * @up: uart 8250 port + * @toggle_ier: true to allow disabling receive interrupts * * Generic callback usable by 8250 uart drivers to start rs485 transmission. * Assumes that setting the RTS bit in the MCR register means RTS is high. @@ -1547,11 +1447,11 @@ static inline void __start_tx(struct uart_port *port) * stoppable by disabling the UART_IER_RDI interrupt. (Some chips set the * UART_LSR_DR bit even when UART_IER_RDI is disabled, foiling this approach.) */ -void serial8250_em485_start_tx(struct uart_8250_port *up) +void serial8250_em485_start_tx(struct uart_8250_port *up, bool toggle_ier) { unsigned char mcr = serial8250_in_MCR(up); - if (!(up->port.rs485.flags & SER_RS485_RX_DURING_TX)) + if (!(up->port.rs485.flags & SER_RS485_RX_DURING_TX) && toggle_ier) serial8250_stop_rx(&up->port); if (up->port.rs485.flags & SER_RS485_RTS_ON_SEND) @@ -1585,7 +1485,7 @@ static bool start_tx_rs485(struct uart_port *port) if (em485->tx_stopped) { em485->tx_stopped = false; - up->rs485_start_tx(up); + up->rs485_start_tx(up, true); if (up->port.rs485.delay_rts_before_send > 0) { em485->active_timer = &em485->start_tx_timer; @@ -1603,14 +1503,13 @@ static enum hrtimer_restart serial8250_em485_handle_start_tx(struct hrtimer *t) struct uart_8250_em485 *em485 = container_of(t, struct uart_8250_em485, start_tx_timer); struct uart_8250_port *p = em485->port; - unsigned long flags; - uart_port_lock_irqsave(&p->port, &flags); + guard(uart_port_lock_irqsave)(&p->port); + if (em485->active_timer == &em485->start_tx_timer) { __start_tx(&p->port); em485->active_timer = NULL; } - uart_port_unlock_irqrestore(&p->port, flags); return HRTIMER_NORESTART; } @@ -1657,7 +1556,7 @@ static void serial8250_disable_ms(struct uart_port *port) if (up->bugs & UART_BUG_NOMSR) return; - mctrl_gpio_disable_ms(up->gpios); + mctrl_gpio_disable_ms_no_sync(up->gpios); up->ier &= ~UART_IER_MSI; serial_port_out(port, UART_IER, up->ier); @@ -1678,9 +1577,8 @@ static void serial8250_enable_ms(struct uart_port *port) up->ier |= UART_IER_MSI; - serial8250_rpm_get(up); + guard(serial8250_rpm)(up); serial_port_out(port, UART_IER, up->ier); - serial8250_rpm_put(up); } void serial8250_read_char(struct uart_8250_port *up, u16 lsr) @@ -1911,7 +1809,7 @@ int serial8250_handle_irq(struct uart_port *port, unsigned int iir) */ if (!(status & (UART_LSR_FIFOE | UART_LSR_BRK_ERROR_BITS)) && (port->status & (UPSTAT_AUTOCTS | UPSTAT_AUTORTS)) && - !(port->read_status_mask & UART_LSR_DR)) + !(up->ier & (UART_IER_RLSI | UART_IER_RDI))) skip_rx = true; if (status & (UART_LSR_DR | UART_LSR_BI) && !skip_rx) { @@ -1941,15 +1839,11 @@ static int serial8250_default_handle_irq(struct uart_port *port) { struct uart_8250_port *up = up_to_u8250p(port); unsigned int iir; - int ret; - serial8250_rpm_get(up); + guard(serial8250_rpm)(up); iir = serial_port_in(port, UART_IIR); - ret = serial8250_handle_irq(port, iir); - - serial8250_rpm_put(up); - return ret; + return serial8250_handle_irq(port, iir); } /* @@ -1960,16 +1854,14 @@ static int serial8250_default_handle_irq(struct uart_port *port) */ static int serial8250_tx_threshold_handle_irq(struct uart_port *port) { - unsigned long flags; unsigned int iir = serial_port_in(port, UART_IIR); /* TX Threshold IRQ triggered so load up FIFO */ if ((iir & UART_IIR_ID) == UART_IIR_THRI) { struct uart_8250_port *up = up_to_u8250p(port); - uart_port_lock_irqsave(port, &flags); + guard(uart_port_lock_irqsave)(port); serial8250_tx_chars(up); - uart_port_unlock_irqrestore(port, flags); } iir = serial_port_in(port, UART_IIR); @@ -1979,19 +1871,14 @@ static int serial8250_tx_threshold_handle_irq(struct uart_port *port) static unsigned int serial8250_tx_empty(struct uart_port *port) { struct uart_8250_port *up = up_to_u8250p(port); - unsigned int result = 0; - unsigned long flags; - serial8250_rpm_get(up); + guard(serial8250_rpm)(up); + guard(uart_port_lock_irqsave)(port); - uart_port_lock_irqsave(port, &flags); if (!serial8250_tx_dma_running(up) && uart_lsr_tx_empty(serial_lsr_in(up))) - result = TIOCSER_TEMT; - uart_port_unlock_irqrestore(port, flags); + return TIOCSER_TEMT; - serial8250_rpm_put(up); - - return result; + return 0; } unsigned int serial8250_do_get_mctrl(struct uart_port *port) @@ -2000,9 +1887,8 @@ unsigned int serial8250_do_get_mctrl(struct uart_port *port) unsigned int status; unsigned int val; - serial8250_rpm_get(up); - status = serial8250_modem_status(up); - serial8250_rpm_put(up); + scoped_guard(serial8250_rpm, up) + status = serial8250_modem_status(up); val = serial8250_MSR_to_TIOCM(status); if (up->gpios) @@ -2046,24 +1932,31 @@ static void serial8250_set_mctrl(struct uart_port *port, unsigned int mctrl) static void serial8250_break_ctl(struct uart_port *port, int break_state) { struct uart_8250_port *up = up_to_u8250p(port); - unsigned long flags; - serial8250_rpm_get(up); - uart_port_lock_irqsave(port, &flags); + guard(serial8250_rpm)(up); + guard(uart_port_lock_irqsave)(port); + if (break_state == -1) up->lcr |= UART_LCR_SBC; else up->lcr &= ~UART_LCR_SBC; serial_port_out(port, UART_LCR, up->lcr); - uart_port_unlock_irqrestore(port, flags); - serial8250_rpm_put(up); } -static void wait_for_lsr(struct uart_8250_port *up, int bits) +/* Returns true if @bits were set, false on timeout */ +static bool wait_for_lsr(struct uart_8250_port *up, int bits) { - unsigned int status, tmout = 10000; + unsigned int status, tmout; + + /* + * Wait for a character to be sent. Fallback to a safe default + * timeout value if @frame_time is not available. + */ + if (up->port.frame_time) + tmout = up->port.frame_time * 2 / NSEC_PER_USEC; + else + tmout = 10000; - /* Wait up to 10ms for the character(s) to be sent. */ for (;;) { status = serial_lsr_in(up); @@ -2074,11 +1967,11 @@ static void wait_for_lsr(struct uart_8250_port *up, int bits) udelay(1); touch_nmi_watchdog(); } + + return (tmout != 0); } -/* - * Wait for transmitter & holding register to empty - */ +/* Wait for transmitter and holding register to empty with timeout */ static void wait_for_xmitr(struct uart_8250_port *up, int bits) { unsigned int tmout; @@ -2107,22 +2000,15 @@ static void wait_for_xmitr(struct uart_8250_port *up, int bits) static int serial8250_get_poll_char(struct uart_port *port) { struct uart_8250_port *up = up_to_u8250p(port); - int status; u16 lsr; - serial8250_rpm_get(up); + guard(serial8250_rpm)(up); lsr = serial_port_in(port, UART_LSR); + if (!(lsr & UART_LSR_DR)) + return NO_POLL_CHAR; - if (!(lsr & UART_LSR_DR)) { - status = NO_POLL_CHAR; - goto out; - } - - status = serial_port_in(port, UART_RX); -out: - serial8250_rpm_put(up); - return status; + return serial_port_in(port, UART_RX); } @@ -2140,7 +2026,7 @@ static void serial8250_put_poll_char(struct uart_port *port, * should allow safe lockless usage here. */ - serial8250_rpm_get(up); + guard(serial8250_rpm)(up); /* * First save the IER then disable the interrupts */ @@ -2159,38 +2045,22 @@ static void serial8250_put_poll_char(struct uart_port *port, */ wait_for_xmitr(up, UART_LSR_BOTH_EMPTY); serial_port_out(port, UART_IER, ier); - serial8250_rpm_put(up); } #endif /* CONFIG_CONSOLE_POLL */ -int serial8250_do_startup(struct uart_port *port) +static void serial8250_startup_special(struct uart_port *port) { struct uart_8250_port *up = up_to_u8250p(port); - unsigned long flags; - unsigned char iir; - int retval; - u16 lsr; - if (!port->fifosize) - port->fifosize = uart_config[port->type].fifo_size; - if (!up->tx_loadsz) - up->tx_loadsz = uart_config[port->type].tx_loadsz; - if (!up->capabilities) - up->capabilities = uart_config[port->type].flags; - up->mcr = 0; - - if (port->iotype != up->cur_iotype) - set_io_from_upio(port); - - serial8250_rpm_get(up); - if (port->type == PORT_16C950) { + switch (port->type) { + case PORT_16C950: { /* * Wake up and initialize UART * * Synchronize UART_IER access against the console. */ - uart_port_lock_irqsave(port, &flags); + guard(uart_port_lock_irqsave)(port); up->acr = 0; serial_port_out(port, UART_LCR, UART_LCR_CONF_MODE_B); serial_port_out(port, UART_EFR, UART_EFR_ECB); @@ -2200,19 +2070,18 @@ int serial8250_do_startup(struct uart_port *port) serial_port_out(port, UART_LCR, UART_LCR_CONF_MODE_B); serial_port_out(port, UART_EFR, UART_EFR_ECB); serial_port_out(port, UART_LCR, 0); - uart_port_unlock_irqrestore(port, flags); + break; } - - if (port->type == PORT_DA830) { + case PORT_DA830: /* * Reset the port * * Synchronize UART_IER access against the console. */ - uart_port_lock_irqsave(port, &flags); - serial_port_out(port, UART_IER, 0); - serial_port_out(port, UART_DA830_PWREMU_MGMT, 0); - uart_port_unlock_irqrestore(port, flags); + scoped_guard(uart_port_lock_irqsave, port) { + serial_port_out(port, UART_IER, 0); + serial_port_out(port, UART_DA830_PWREMU_MGMT, 0); + } mdelay(10); /* Enable Tx, Rx and free run mode */ @@ -2220,195 +2089,217 @@ int serial8250_do_startup(struct uart_port *port) UART_DA830_PWREMU_MGMT_UTRST | UART_DA830_PWREMU_MGMT_URRST | UART_DA830_PWREMU_MGMT_FREE); + break; + case PORT_RSA: + rsa_enable(up); + break; } +} -#ifdef CONFIG_SERIAL_8250_RSA - /* - * If this is an RSA port, see if we can kick it up to the - * higher speed clock. - */ - enable_rsa(up); -#endif - - /* - * Clear the FIFO buffers and disable them. - * (they will be reenabled in set_termios()) - */ - serial8250_clear_fifos(up); - - /* - * Clear the interrupt registers. - */ - serial_port_in(port, UART_LSR); - serial_port_in(port, UART_RX); - serial_port_in(port, UART_IIR); - serial_port_in(port, UART_MSR); - - /* - * At this point, there's no way the LSR could still be 0xff; - * if it is, then bail out, because there's likely no UART - * here. - */ - if (!(port->flags & UPF_BUGGY_UART) && - (serial_port_in(port, UART_LSR) == 0xff)) { - dev_info_ratelimited(port->dev, "LSR safety check engaged!\n"); - retval = -ENODEV; - goto out; - } +static void serial8250_set_TRG_levels(struct uart_port *port) +{ + struct uart_8250_port *up = up_to_u8250p(port); - /* - * For a XR16C850, we need to set the trigger levels - */ - if (port->type == PORT_16850) { - unsigned char fctr; + switch (port->type) { + /* For a XR16C850, we need to set the trigger levels */ + case PORT_16850: { + u8 fctr; serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B); fctr = serial_in(up, UART_FCTR) & ~(UART_FCTR_RX|UART_FCTR_TX); - serial_port_out(port, UART_FCTR, - fctr | UART_FCTR_TRGD | UART_FCTR_RX); + fctr |= UART_FCTR_TRGD; + serial_port_out(port, UART_FCTR, fctr | UART_FCTR_RX); serial_port_out(port, UART_TRG, UART_TRG_96); - serial_port_out(port, UART_FCTR, - fctr | UART_FCTR_TRGD | UART_FCTR_TX); + serial_port_out(port, UART_FCTR, fctr | UART_FCTR_TX); serial_port_out(port, UART_TRG, UART_TRG_96); serial_port_out(port, UART_LCR, 0); + break; } + /* For the Altera 16550 variants, set TX threshold trigger level. */ + case PORT_ALTR_16550_F32: + case PORT_ALTR_16550_F64: + case PORT_ALTR_16550_F128: + if (port->fifosize <= 1) + return; - /* - * For the Altera 16550 variants, set TX threshold trigger level. - */ - if (((port->type == PORT_ALTR_16550_F32) || - (port->type == PORT_ALTR_16550_F64) || - (port->type == PORT_ALTR_16550_F128)) && (port->fifosize > 1)) { /* Bounds checking of TX threshold (valid 0 to fifosize-2) */ - if ((up->tx_loadsz < 2) || (up->tx_loadsz > port->fifosize)) { + if (up->tx_loadsz < 2 || up->tx_loadsz > port->fifosize) { dev_err(port->dev, "TX FIFO Threshold errors, skipping\n"); - } else { - serial_port_out(port, UART_ALTR_AFR, - UART_ALTR_EN_TXFIFO_LW); - serial_port_out(port, UART_ALTR_TX_LOW, - port->fifosize - up->tx_loadsz); - port->handle_irq = serial8250_tx_threshold_handle_irq; + return; } + serial_port_out(port, UART_ALTR_AFR, UART_ALTR_EN_TXFIFO_LW); + serial_port_out(port, UART_ALTR_TX_LOW, port->fifosize - up->tx_loadsz); + port->handle_irq = serial8250_tx_threshold_handle_irq; + break; } +} - /* Check if we need to have shared IRQs */ - if (port->irq && (up->port.flags & UPF_SHARE_IRQ)) - up->port.irqflags |= IRQF_SHARED; - - retval = up->ops->setup_irq(up); - if (retval) - goto out; +static void serial8250_THRE_test(struct uart_port *port) +{ + struct uart_8250_port *up = up_to_u8250p(port); + bool iir_noint1, iir_noint2; - if (port->irq && !(up->port.flags & UPF_NO_THRE_TEST)) { - unsigned char iir1; + if (!port->irq) + return; - if (port->irqflags & IRQF_SHARED) - disable_irq_nosync(port->irq); + if (up->port.flags & UPF_NO_THRE_TEST) + return; - /* - * Test for UARTs that do not reassert THRE when the - * transmitter is idle and the interrupt has already - * been cleared. Real 16550s should always reassert - * this interrupt whenever the transmitter is idle and - * the interrupt is enabled. Delays are necessary to - * allow register changes to become visible. - * - * Synchronize UART_IER access against the console. - */ - uart_port_lock_irqsave(port, &flags); + if (port->irqflags & IRQF_SHARED) + disable_irq_nosync(port->irq); + /* + * Test for UARTs that do not reassert THRE when the transmitter is idle and the interrupt + * has already been cleared. Real 16550s should always reassert this interrupt whenever the + * transmitter is idle and the interrupt is enabled. Delays are necessary to allow register + * changes to become visible. + * + * Synchronize UART_IER access against the console. + */ + scoped_guard(uart_port_lock_irqsave, port) { wait_for_xmitr(up, UART_LSR_THRE); serial_port_out_sync(port, UART_IER, UART_IER_THRI); udelay(1); /* allow THRE to set */ - iir1 = serial_port_in(port, UART_IIR); + iir_noint1 = serial_port_in(port, UART_IIR) & UART_IIR_NO_INT; serial_port_out(port, UART_IER, 0); serial_port_out_sync(port, UART_IER, UART_IER_THRI); udelay(1); /* allow a working UART time to re-assert THRE */ - iir = serial_port_in(port, UART_IIR); + iir_noint2 = serial_port_in(port, UART_IIR) & UART_IIR_NO_INT; serial_port_out(port, UART_IER, 0); - - uart_port_unlock_irqrestore(port, flags); - - if (port->irqflags & IRQF_SHARED) - enable_irq(port->irq); - - /* - * If the interrupt is not reasserted, or we otherwise - * don't trust the iir, setup a timer to kick the UART - * on a regular basis. - */ - if ((!(iir1 & UART_IIR_NO_INT) && (iir & UART_IIR_NO_INT)) || - up->port.flags & UPF_BUG_THRE) { - up->bugs |= UART_BUG_THRE; - } } - up->ops->setup_timer(up); + if (port->irqflags & IRQF_SHARED) + enable_irq(port->irq); /* - * Now, initialize the UART + * If the interrupt is not reasserted, or we otherwise don't trust the iir, setup a timer to + * kick the UART on a regular basis. */ - serial_port_out(port, UART_LCR, UART_LCR_WLEN8); + if ((!iir_noint1 && iir_noint2) || up->port.flags & UPF_BUG_THRE) + up->bugs |= UART_BUG_THRE; +} - uart_port_lock_irqsave(port, &flags); - if (up->port.flags & UPF_FOURPORT) { - if (!up->port.irq) - up->port.mctrl |= TIOCM_OUT1; - } else - /* - * Most PC uarts need OUT2 raised to enable interrupts. - */ +static void serial8250_init_mctrl(struct uart_port *port) +{ + if (port->flags & UPF_FOURPORT) { + if (!port->irq) + port->mctrl |= TIOCM_OUT1; + } else { + /* Most PC uarts need OUT2 raised to enable interrupts. */ if (port->irq) - up->port.mctrl |= TIOCM_OUT2; + port->mctrl |= TIOCM_OUT2; + } serial8250_set_mctrl(port, port->mctrl); +} - /* - * Serial over Lan (SoL) hack: - * Intel 8257x Gigabit ethernet chips have a 16550 emulation, to be - * used for Serial Over Lan. Those chips take a longer time than a - * normal serial device to signalize that a transmission data was - * queued. Due to that, the above test generally fails. One solution - * would be to delay the reading of iir. However, this is not - * reliable, since the timeout is variable. So, let's just don't - * test if we receive TX irq. This way, we'll never enable - * UART_BUG_TXEN. - */ - if (up->port.quirks & UPQ_NO_TXEN_TEST) - goto dont_test_tx_en; +static void serial8250_iir_txen_test(struct uart_port *port) +{ + struct uart_8250_port *up = up_to_u8250p(port); + bool lsr_temt, iir_noint; - /* - * Do a quick test to see if we receive an interrupt when we enable - * the TX irq. - */ + if (port->quirks & UPQ_NO_TXEN_TEST) + return; + + /* Do a quick test to see if we receive an interrupt when we enable the TX irq. */ serial_port_out(port, UART_IER, UART_IER_THRI); - lsr = serial_port_in(port, UART_LSR); - iir = serial_port_in(port, UART_IIR); + lsr_temt = serial_port_in(port, UART_LSR) & UART_LSR_TEMT; + iir_noint = serial_port_in(port, UART_IIR) & UART_IIR_NO_INT; serial_port_out(port, UART_IER, 0); - if (lsr & UART_LSR_TEMT && iir & UART_IIR_NO_INT) { + /* + * Serial over Lan (SoL) hack: + * Intel 8257x Gigabit ethernet chips have a 16550 emulation, to be used for Serial Over + * Lan. Those chips take a longer time than a normal serial device to signalize that a + * transmission data was queued. Due to that, the above test generally fails. One solution + * would be to delay the reading of iir. However, this is not reliable, since the timeout is + * variable. So, in case of UPQ_NO_TXEN_TEST, let's just don't test if we receive TX irq. + * This way, we'll never enable UART_BUG_TXEN. + */ + if (lsr_temt && iir_noint) { if (!(up->bugs & UART_BUG_TXEN)) { up->bugs |= UART_BUG_TXEN; dev_dbg(port->dev, "enabling bad tx status workarounds\n"); } - } else { - up->bugs &= ~UART_BUG_TXEN; + return; } -dont_test_tx_en: - uart_port_unlock_irqrestore(port, flags); + /* FIXME: why is this needed? */ + up->bugs &= ~UART_BUG_TXEN; +} + +static void serial8250_initialize(struct uart_port *port) +{ + guard(uart_port_lock_irqsave)(port); + serial_port_out(port, UART_LCR, UART_LCR_WLEN8); + + serial8250_init_mctrl(port); + serial8250_iir_txen_test(port); +} + +int serial8250_do_startup(struct uart_port *port) +{ + struct uart_8250_port *up = up_to_u8250p(port); + int retval; + + if (!port->fifosize) + port->fifosize = uart_config[port->type].fifo_size; + if (!up->tx_loadsz) + up->tx_loadsz = uart_config[port->type].tx_loadsz; + if (!up->capabilities) + up->capabilities = uart_config[port->type].flags; + up->mcr = 0; + + if (port->iotype != up->cur_iotype) + set_io_from_upio(port); + + guard(serial8250_rpm)(up); + + serial8250_startup_special(port); + + /* + * Clear the FIFO buffers and disable them. + * (they will be reenabled in set_termios()) + */ + serial8250_clear_fifos(up); + + serial8250_clear_interrupts(port); + + /* + * At this point, there's no way the LSR could still be 0xff; + * if it is, then bail out, because there's likely no UART + * here. + */ + if (!(port->flags & UPF_BUGGY_UART) && + (serial_port_in(port, UART_LSR) == 0xff)) { + dev_info_ratelimited(port->dev, "LSR safety check engaged!\n"); + return -ENODEV; + } + + serial8250_set_TRG_levels(port); + + /* Check if we need to have shared IRQs */ + if (port->irq && (up->port.flags & UPF_SHARE_IRQ)) + up->port.irqflags |= IRQF_SHARED; + + retval = up->ops->setup_irq(up); + if (retval) + return retval; + + serial8250_THRE_test(port); + + up->ops->setup_timer(up); + + serial8250_initialize(port); /* * Clear the interrupt registers again for luck, and clear the * saved flags to avoid getting false values from polling * routines or the previous session. */ - serial_port_in(port, UART_LSR); - serial_port_in(port, UART_RX); - serial_port_in(port, UART_IIR); - serial_port_in(port, UART_MSR); + serial8250_clear_interrupts(port); up->lsr_saved_flags = 0; up->msr_saved_flags = 0; @@ -2444,10 +2335,8 @@ dont_test_tx_en: outb_p(0x80, icp); inb_p(icp); } - retval = 0; -out: - serial8250_rpm_put(up); - return retval; + + return 0; } EXPORT_SYMBOL_GPL(serial8250_do_startup); @@ -2461,7 +2350,6 @@ static int serial8250_startup(struct uart_port *port) void serial8250_do_shutdown(struct uart_port *port) { struct uart_8250_port *up = up_to_u8250p(port); - unsigned long flags; serial8250_rpm_get(up); /* @@ -2469,26 +2357,26 @@ void serial8250_do_shutdown(struct uart_port *port) * * Synchronize UART_IER access against the console. */ - uart_port_lock_irqsave(port, &flags); - up->ier = 0; - serial_port_out(port, UART_IER, 0); - uart_port_unlock_irqrestore(port, flags); + scoped_guard(uart_port_lock_irqsave, port) { + up->ier = 0; + serial_port_out(port, UART_IER, 0); + } synchronize_irq(port->irq); if (up->dma) serial8250_release_dma(up); - uart_port_lock_irqsave(port, &flags); - if (port->flags & UPF_FOURPORT) { - /* reset interrupts on the AST Fourport board */ - inb((port->iobase & 0xfe0) | 0x1f); - port->mctrl |= TIOCM_OUT1; - } else - port->mctrl &= ~TIOCM_OUT2; + scoped_guard(uart_port_lock_irqsave, port) { + if (port->flags & UPF_FOURPORT) { + /* reset interrupts on the AST Fourport board */ + inb((port->iobase & 0xfe0) | 0x1f); + port->mctrl |= TIOCM_OUT1; + } else + port->mctrl &= ~TIOCM_OUT2; - serial8250_set_mctrl(port, port->mctrl); - uart_port_unlock_irqrestore(port, flags); + serial8250_set_mctrl(port, port->mctrl); + } /* * Disable break condition and FIFOs @@ -2497,12 +2385,7 @@ void serial8250_do_shutdown(struct uart_port *port) serial_port_in(port, UART_LCR) & ~UART_LCR_SBC); serial8250_clear_fifos(up); -#ifdef CONFIG_SERIAL_8250_RSA - /* - * Reset the RSA board back to 115kbps compat mode. - */ - disable_rsa(up); -#endif + rsa_disable(up); /* * Read data port to reset things, and then unlink from @@ -2523,9 +2406,15 @@ static void serial8250_shutdown(struct uart_port *port) serial8250_do_shutdown(port); } -static unsigned int serial8250_do_get_divisor(struct uart_port *port, - unsigned int baud, - unsigned int *frac) +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) { upf_t magic_multiplier = port->flags & UPF_MAGIC_MULTIPLIER; struct uart_8250_port *up = up_to_u8250p(port); @@ -2586,30 +2475,27 @@ static unsigned int serial8250_get_divisor(struct uart_port *port, if (port->get_divisor) return port->get_divisor(port, baud, frac); - return serial8250_do_get_divisor(port, baud, frac); + return serial8250_do_get_divisor(port, baud); } -static unsigned char serial8250_compute_lcr(struct uart_8250_port *up, - tcflag_t c_cflag) +static unsigned char serial8250_compute_lcr(struct uart_8250_port *up, tcflag_t c_cflag) { - unsigned char cval; - - cval = UART_LCR_WLEN(tty_get_char_size(c_cflag)); + u8 lcr = UART_LCR_WLEN(tty_get_char_size(c_cflag)); if (c_cflag & CSTOPB) - cval |= UART_LCR_STOP; + lcr |= UART_LCR_STOP; if (c_cflag & PARENB) - cval |= UART_LCR_PARITY; + lcr |= UART_LCR_PARITY; if (!(c_cflag & PARODD)) - cval |= UART_LCR_EPAR; + lcr |= UART_LCR_EPAR; if (c_cflag & CMSPAR) - cval |= UART_LCR_SPAR; + lcr |= UART_LCR_SPAR; - return cval; + return lcr; } void serial8250_do_set_divisor(struct uart_port *port, unsigned int baud, - unsigned int quot, unsigned int quot_frac) + unsigned int quot) { struct uart_8250_port *up = up_to_u8250p(port); @@ -2641,7 +2527,7 @@ static void serial8250_set_divisor(struct uart_port *port, unsigned int baud, if (port->set_divisor) port->set_divisor(port, baud, quot, quot_frac); else - serial8250_do_set_divisor(port, baud, quot, quot_frac); + serial8250_do_set_divisor(port, baud, quot); } static unsigned int serial8250_get_baud_rate(struct uart_port *port, @@ -2682,124 +2568,119 @@ static unsigned int serial8250_get_baud_rate(struct uart_port *port, void serial8250_update_uartclk(struct uart_port *port, unsigned int uartclk) { struct tty_port *tport = &port->state->port; - struct tty_struct *tty; - tty = tty_port_tty_get(tport); - if (!tty) { - mutex_lock(&tport->mutex); - port->uartclk = uartclk; - mutex_unlock(&tport->mutex); - return; - } + scoped_guard(tty_port_tty, tport) { + struct tty_struct *tty = scoped_tty(); - down_write(&tty->termios_rwsem); - mutex_lock(&tport->mutex); + guard(rwsem_write)(&tty->termios_rwsem); + guard(mutex)(&tport->mutex); - if (port->uartclk == uartclk) - goto out_unlock; + if (port->uartclk == uartclk) + return; - port->uartclk = uartclk; + port->uartclk = uartclk; - if (!tty_port_initialized(tport)) - goto out_unlock; + if (!tty_port_initialized(tport)) + return; - serial8250_do_set_termios(port, &tty->termios, NULL); + serial8250_do_set_termios(port, &tty->termios, NULL); -out_unlock: - mutex_unlock(&tport->mutex); - up_write(&tty->termios_rwsem); - tty_kref_put(tty); + return; + } + guard(mutex)(&tport->mutex); + port->uartclk = uartclk; } EXPORT_SYMBOL_GPL(serial8250_update_uartclk); -void -serial8250_do_set_termios(struct uart_port *port, struct ktermios *termios, - const struct ktermios *old) +static void serial8250_set_mini(struct uart_port *port, struct ktermios *termios) { struct uart_8250_port *up = up_to_u8250p(port); - unsigned char cval; - unsigned long flags; - unsigned int baud, quot, frac = 0; - if (up->capabilities & UART_CAP_MINI) { - termios->c_cflag &= ~(CSTOPB | PARENB | PARODD | CMSPAR); - if ((termios->c_cflag & CSIZE) == CS5 || - (termios->c_cflag & CSIZE) == CS6) - termios->c_cflag = (termios->c_cflag & ~CSIZE) | CS7; + if (!(up->capabilities & UART_CAP_MINI)) + return; + + termios->c_cflag &= ~(CSTOPB | PARENB | PARODD | CMSPAR); + + tcflag_t csize = termios->c_cflag & CSIZE; + if (csize == CS5 || csize == CS6) { + termios->c_cflag &= ~CSIZE; + termios->c_cflag |= CS7; } - cval = serial8250_compute_lcr(up, termios->c_cflag); +} - baud = serial8250_get_baud_rate(port, termios, old); - quot = serial8250_get_divisor(port, baud, &frac); +static void serial8250_set_trigger_for_slow_speed(struct uart_port *port, struct ktermios *termios, + unsigned int baud) +{ + struct uart_8250_port *up = up_to_u8250p(port); - /* - * Ok, we're now changing the port state. Do it with - * interrupts disabled. - * - * Synchronize UART_IER access against the console. - */ - serial8250_rpm_get(up); - uart_port_lock_irqsave(port, &flags); + if (!(up->capabilities & UART_CAP_FIFO)) + return; + if (port->fifosize <= 1) + return; + if (baud >= 2400) + return; + if (up->dma) + return; - up->lcr = cval; /* Save computed LCR */ + up->fcr &= ~UART_FCR_TRIGGER_MASK; + up->fcr |= UART_FCR_TRIGGER_1; +} - if (up->capabilities & UART_CAP_FIFO && port->fifosize > 1) { - if (baud < 2400 && !up->dma) { - up->fcr &= ~UART_FCR_TRIGGER_MASK; - up->fcr |= UART_FCR_TRIGGER_1; - } - } +/* + * MCR-based auto flow control. When AFE is enabled, RTS will be deasserted when the receive FIFO + * contains more characters than the trigger, or the MCR RTS bit is cleared. + */ +static void serial8250_set_afe(struct uart_port *port, struct ktermios *termios) +{ + struct uart_8250_port *up = up_to_u8250p(port); - /* - * MCR-based auto flow control. When AFE is enabled, RTS will be - * deasserted when the receive FIFO contains more characters than - * the trigger, or the MCR RTS bit is cleared. - */ - if (up->capabilities & UART_CAP_AFE) { - up->mcr &= ~UART_MCR_AFE; - if (termios->c_cflag & CRTSCTS) - up->mcr |= UART_MCR_AFE; - } + if (!(up->capabilities & UART_CAP_AFE)) + return; + up->mcr &= ~UART_MCR_AFE; + if (termios->c_cflag & CRTSCTS) + up->mcr |= UART_MCR_AFE; +} + +static void serial8250_set_errors_and_ignores(struct uart_port *port, struct ktermios *termios) +{ /* - * Update the per-port timeout. + * Specify which conditions may be considered for error handling and the ignoring of + * characters. The actual ignoring of characters only occurs if the bit is set in + * @ignore_status_mask as well. */ - uart_update_timeout(port, termios->c_cflag, baud); - - port->read_status_mask = UART_LSR_OE | UART_LSR_THRE | UART_LSR_DR; + port->read_status_mask = UART_LSR_OE | UART_LSR_DR; if (termios->c_iflag & INPCK) port->read_status_mask |= UART_LSR_FE | UART_LSR_PE; if (termios->c_iflag & (IGNBRK | BRKINT | PARMRK)) port->read_status_mask |= UART_LSR_BI; - /* - * Characters to ignore - */ + /* Characters to ignore */ port->ignore_status_mask = 0; if (termios->c_iflag & IGNPAR) port->ignore_status_mask |= UART_LSR_PE | UART_LSR_FE; if (termios->c_iflag & IGNBRK) { port->ignore_status_mask |= UART_LSR_BI; /* - * If we're ignoring parity and break indicators, - * ignore overruns too (for real raw support). + * If we're ignoring parity and break indicators, ignore overruns too (for real raw + * support). */ if (termios->c_iflag & IGNPAR) port->ignore_status_mask |= UART_LSR_OE; } - /* - * ignore all characters if CREAD is not set - */ + /* ignore all characters if CREAD is not set */ if ((termios->c_cflag & CREAD) == 0) port->ignore_status_mask |= UART_LSR_DR; +} - /* - * CTS flow control flag and modem status interrupts - */ +static void serial8250_set_ier(struct uart_port *port, struct ktermios *termios) +{ + struct uart_8250_port *up = up_to_u8250p(port); + + /* CTS flow control flag and modem status interrupts */ up->ier &= ~UART_IER_MSI; - if (!(up->bugs & UART_BUG_NOMSR) && - UART_ENABLE_MS(&up->port, termios->c_cflag)) + if (!(up->bugs & UART_BUG_NOMSR) && UART_ENABLE_MS(&up->port, termios->c_cflag)) up->ier |= UART_IER_MSI; if (up->capabilities & UART_CAP_UUE) up->ier |= UART_IER_UUE; @@ -2807,43 +2688,88 @@ serial8250_do_set_termios(struct uart_port *port, struct ktermios *termios, up->ier |= UART_IER_RTOIE; serial_port_out(port, UART_IER, up->ier); +} - if (up->capabilities & UART_CAP_EFR) { - unsigned char efr = 0; - /* - * TI16C752/Startech hardware flow control. FIXME: - * - TI16C752 requires control thresholds to be set. - * - UART_MCR_RTS is ineffective if auto-RTS mode is enabled. - */ - if (termios->c_cflag & CRTSCTS) - efr |= UART_EFR_CTS; - - serial_port_out(port, UART_LCR, UART_LCR_CONF_MODE_B); - if (port->flags & UPF_EXAR_EFR) - serial_port_out(port, UART_XR_EFR, efr); - else - serial_port_out(port, UART_EFR, efr); - } +static void serial8250_set_efr(struct uart_port *port, struct ktermios *termios) +{ + struct uart_8250_port *up = up_to_u8250p(port); + u8 efr_reg = UART_EFR; + u8 efr = 0; - serial8250_set_divisor(port, baud, quot, frac); + if (!(up->capabilities & UART_CAP_EFR)) + return; /* - * LCR DLAB must be set to enable 64-byte FIFO mode. If the FCR - * is written without DLAB set, this mode will be disabled. + * TI16C752/Startech hardware flow control. FIXME: + * - TI16C752 requires control thresholds to be set. + * - UART_MCR_RTS is ineffective if auto-RTS mode is enabled. */ - if (port->type == PORT_16750) + if (termios->c_cflag & CRTSCTS) + efr |= UART_EFR_CTS; + + if (port->flags & UPF_EXAR_EFR) + efr_reg = UART_XR_EFR; + + serial_port_out(port, UART_LCR, UART_LCR_CONF_MODE_B); + serial_port_out(port, efr_reg, efr); +} + +static void serial8250_set_fcr(struct uart_port *port, struct ktermios *termios) +{ + struct uart_8250_port *up = up_to_u8250p(port); + bool is_16750 = port->type == PORT_16750; + + if (is_16750) serial_port_out(port, UART_FCR, up->fcr); - serial_port_out(port, UART_LCR, up->lcr); /* reset DLAB */ - if (port->type != PORT_16750) { - /* emulated UARTs (Lucent Venus 167x) need two steps */ - if (up->fcr & UART_FCR_ENABLE_FIFO) - serial_port_out(port, UART_FCR, UART_FCR_ENABLE_FIFO); - serial_port_out(port, UART_FCR, up->fcr); /* set fcr */ + /* + * LCR DLAB must be reset to enable 64-byte FIFO mode. If the FCR is written without DLAB + * set, this mode will be disabled. + */ + serial_port_out(port, UART_LCR, up->lcr); + + if (is_16750) + return; + + /* emulated UARTs (Lucent Venus 167x) need two steps */ + if (up->fcr & UART_FCR_ENABLE_FIFO) + serial_port_out(port, UART_FCR, UART_FCR_ENABLE_FIFO); + + serial_port_out(port, UART_FCR, up->fcr); +} + +void +serial8250_do_set_termios(struct uart_port *port, struct ktermios *termios, + const struct ktermios *old) +{ + struct uart_8250_port *up = up_to_u8250p(port); + unsigned int baud, quot, frac = 0; + u8 lcr; + + serial8250_set_mini(port, termios); + lcr = serial8250_compute_lcr(up, termios->c_cflag); + baud = serial8250_get_baud_rate(port, termios, old); + quot = serial8250_get_divisor(port, baud, &frac); + + /* + * Ok, we're now changing the port state. Do it with interrupts disabled. + * + * Synchronize UART_IER access against the console. + */ + scoped_guard(serial8250_rpm, up) { + guard(uart_port_lock_irqsave)(port); + + up->lcr = lcr; + serial8250_set_trigger_for_slow_speed(port, termios, baud); + serial8250_set_afe(port, termios); + uart_update_timeout(port, termios->c_cflag, baud); + serial8250_set_errors_and_ignores(port, termios); + serial8250_set_ier(port, termios); + serial8250_set_efr(port, termios); + serial8250_set_divisor(port, baud, quot, frac); + serial8250_set_fcr(port, termios); + serial8250_set_mctrl(port, port->mctrl); } - serial8250_set_mctrl(port, port->mctrl); - uart_port_unlock_irqrestore(port, flags); - serial8250_rpm_put(up); /* Don't rewrite B0 */ if (tty_termios_baud_rate(termios)) @@ -2865,15 +2791,13 @@ void serial8250_do_set_ldisc(struct uart_port *port, struct ktermios *termios) { if (termios->c_line == N_PPS) { port->flags |= UPF_HARDPPS_CD; - uart_port_lock_irq(port); + guard(uart_port_lock_irq)(port); serial8250_enable_ms(port); - uart_port_unlock_irq(port); } else { port->flags &= ~UPF_HARDPPS_CD; if (!UART_ENABLE_MS(port, termios->c_cflag)) { - uart_port_lock_irq(port); + guard(uart_port_lock_irq)(port); serial8250_disable_ms(port); - uart_port_unlock_irq(port); } } } @@ -2924,7 +2848,6 @@ static int serial8250_request_std_resource(struct uart_8250_port *up) { unsigned int size = serial8250_port_size(up); struct uart_port *port = &up->port; - int ret = 0; switch (port->iotype) { case UPIO_AU: @@ -2933,32 +2856,30 @@ static int serial8250_request_std_resource(struct uart_8250_port *up) case UPIO_MEM32BE: case UPIO_MEM16: case UPIO_MEM: - if (!port->mapbase) { - ret = -EINVAL; - break; - } + if (!port->mapbase) + return -EINVAL; - if (!request_mem_region(port->mapbase, size, "serial")) { - ret = -EBUSY; - break; - } + if (!request_mem_region(port->mapbase, size, "serial")) + return -EBUSY; if (port->flags & UPF_IOREMAP) { port->membase = ioremap(port->mapbase, size); if (!port->membase) { release_mem_region(port->mapbase, size); - ret = -ENOMEM; + return -ENOMEM; } } - break; - + return 0; case UPIO_HUB6: case UPIO_PORT: if (!request_region(port->iobase, size, "serial")) - ret = -EBUSY; + return -EBUSY; + return 0; + case UPIO_UNKNOWN: break; } - return ret; + + return 0; } static void serial8250_release_std_resource(struct uart_8250_port *up) @@ -2988,6 +2909,8 @@ static void serial8250_release_std_resource(struct uart_8250_port *up) case UPIO_PORT: release_region(port->iobase, size); break; + case UPIO_UNKNOWN: + break; } } @@ -3176,7 +3099,7 @@ static void serial8250_config_port(struct uart_port *port, int flags) static int serial8250_verify_port(struct uart_port *port, struct serial_struct *ser) { - if (ser->irq >= nr_irqs || ser->irq < 0 || + if (ser->irq >= irq_get_nr_irqs() || ser->irq < 0 || ser->baud_base < 9600 || ser->type < PORT_UNKNOWN || ser->type >= ARRAY_SIZE(uart_config) || ser->type == PORT_CIRRUS || ser->type == PORT_STARTECH) @@ -3206,6 +3129,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, @@ -3230,7 +3154,7 @@ void serial8250_init_port(struct uart_8250_port *up) port->ops = &serial8250_pops; port->has_sysrq = IS_ENABLED(CONFIG_SERIAL_8250_CONSOLE); - up->cur_iotype = 0xFF; + up->cur_iotype = UPIO_UNKNOWN; } EXPORT_SYMBOL_GPL(serial8250_init_port); @@ -3265,10 +3189,15 @@ EXPORT_SYMBOL_GPL(serial8250_set_defaults); static void serial8250_console_putchar(struct uart_port *port, unsigned char ch) { + serial_port_out(port, UART_TX, ch); +} + +static void serial8250_console_wait_putchar(struct uart_port *port, unsigned char ch) +{ struct uart_8250_port *up = up_to_u8250p(port); wait_for_xmitr(up, UART_LSR_THRE); - serial_port_out(port, UART_TX, ch); + serial8250_console_putchar(port, ch); } /* @@ -3297,6 +3226,16 @@ static void serial8250_console_restore(struct uart_8250_port *up) serial8250_out_MCR(up, up->mcr | UART_MCR_DTR | UART_MCR_RTS); } +static void fifo_wait_for_lsr(struct uart_8250_port *up, unsigned int count) +{ + unsigned int i; + + for (i = 0; i < count; i++) { + if (wait_for_lsr(up, UART_LSR_THRE)) + return; + } +} + /* * Print a string to the serial port using the device FIFO * @@ -3306,24 +3245,34 @@ static void serial8250_console_restore(struct uart_8250_port *up) static void serial8250_console_fifo_write(struct uart_8250_port *up, const char *s, unsigned int count) { - int i; const char *end = s + count; unsigned int fifosize = up->tx_loadsz; + struct uart_port *port = &up->port; + unsigned int tx_count = 0; bool cr_sent = false; + unsigned int i; while (s != end) { - wait_for_lsr(up, UART_LSR_THRE); + /* Allow timeout for each byte of a possibly full FIFO */ + fifo_wait_for_lsr(up, fifosize); for (i = 0; i < fifosize && s != end; ++i) { if (*s == '\n' && !cr_sent) { - serial_out(up, UART_TX, '\r'); + serial8250_console_putchar(port, '\r'); cr_sent = true; } else { - serial_out(up, UART_TX, *s++); + serial8250_console_putchar(port, *s++); cr_sent = false; } } + tx_count = i; } + + /* + * Allow timeout for each byte written since the caller will only wait + * for UART_LSR_BOTH_EMPTY using the timeout of a single character + */ + fifo_wait_for_lsr(up, tx_count); } /* @@ -3365,7 +3314,7 @@ void serial8250_console_write(struct uart_8250_port *up, const char *s, if (em485) { if (em485->tx_stopped) - up->rs485_start_tx(up); + up->rs485_start_tx(up, false); mdelay(port->rs485.delay_rts_before_send); } @@ -3392,7 +3341,7 @@ void serial8250_console_write(struct uart_8250_port *up, const char *s, if (likely(use_fifo)) serial8250_console_fifo_write(up, s, count); else - uart_console_write(port, s, count, serial8250_console_putchar); + uart_console_write(port, s, count, serial8250_console_wait_putchar); /* * Finally, wait for transmitter to become empty @@ -3403,7 +3352,7 @@ void serial8250_console_write(struct uart_8250_port *up, const char *s, if (em485) { mdelay(port->rs485.delay_rts_after_send); if (em485->tx_stopped) - up->rs485_stop_tx(up); + up->rs485_stop_tx(up, false); } serial_port_out(port, UART_IER, ier); @@ -3473,4 +3422,5 @@ int serial8250_console_exit(struct uart_port *port) #endif /* CONFIG_SERIAL_8250_CONSOLE */ +MODULE_DESCRIPTION("Base port operations for 8250/16550-type serial ports"); MODULE_LICENSE("GPL"); |
