--- zzzz-none-000/linux-5.4.213/drivers/tty/serial/serial_core.c 2022-09-15 10:04:56.000000000 +0000 +++ miami-7690-761/linux-5.4.213/drivers/tty/serial/serial_core.c 2024-05-29 11:20:02.000000000 +0000 @@ -22,6 +22,7 @@ #include #include #include +#include #include #include @@ -2089,8 +2090,10 @@ * early. * If this port is a console, then the spinlock is already * initialised. + * AVM: This should also hold true for devices used with tty polling. */ - if (!(uart_console(port) && (port->cons->flags & CON_ENABLED))) { + if (!((uart_console(port) && (port->cons->flags & CON_ENABLED)) + || port->flags)) { spin_lock_init(&port->lock); lockdep_set_class(&port->lock, &port_lock_key); } @@ -2483,6 +2486,11 @@ if (!port) return; + if(IS_ENABLED(CONFIG_CONSOLE_POLL)){ + port->ops->poll_put_char(port, ch); + return; + } + if (ch == '\n') port->ops->poll_put_char(port, '\r'); port->ops->poll_put_char(port, ch); @@ -2533,6 +2541,189 @@ .shutdown = uart_tty_port_shutdown, }; +#ifdef CONFIG_AVM_TTY_POLLING +struct polling_tty_port { + struct tty_driver *driver; + int line; +}; + +struct polling_tty_port *avm_tty_poll_acquire(const char *ttyname) +{ + struct polling_tty_port *pport; + struct tty_driver *ttydrv; + struct uart_driver *drv; + struct uart_state *state; + struct uart_port *uport; + struct tty_port *port; + int line, err; + char name[40]; + + pr_debug("Acquiring polling tty port %s\n", ttyname); + + strscpy(name, ttyname, sizeof(name)); + ttydrv = tty_find_polling_driver(name, &line); + if (!ttydrv) { + err = -ENODEV; + goto err_out; + } + + drv = ttydrv->driver_state; + state = drv->state + line; + if (!state) + goto noport; + port = &state->port; + + mutex_lock(&port->mutex); + + uport = state->uart_port; + if (!uport) { + mutex_unlock(&port->mutex); + goto noport; + } + + pport = kmalloc(sizeof(*pport), GFP_KERNEL); + if (!pport) { + err = -ENOMEM; + mutex_unlock(&port->mutex); + goto put_driver; + } + // This can be omitted for Puna and GRX + uport->ops->startup(uport); + if (uport->irq) + disable_irq(uport->irq); + + pm_runtime_get_sync(uport->dev); + + mutex_unlock(&port->mutex); + + pport->driver = ttydrv; + pport->line = line; + + return pport; +noport: + pr_err("No port state for %s\n", ttyname); + err = -EL3HLT; +put_driver: + put_tty_driver(ttydrv); +err_out: + pr_err("Error acquiring polling tty port %s: %d\n", ttyname, err); + + return ERR_PTR(err); +} +EXPORT_SYMBOL(avm_tty_poll_acquire); + +int avm_tty_poll_configure(struct polling_tty_port *pport, int baud, + int parity, int bits, int flow) +{ + struct tty_driver *ttydrv = pport->driver; + struct uart_driver *drv; + struct uart_state *state; + struct uart_port *uport; + struct tty_port *port; + + pr_debug("Setting polling tty port %s%d to %u baud\n", + ttydrv->name, pport->line, baud); + + drv = ttydrv->driver_state; + state = drv->state + pport->line; + if (!state) + goto noport; + port = &state->port; + + mutex_lock(&port->mutex); + uport = state->uart_port; + if (!uport) { + mutex_unlock(&port->mutex); + goto noport; + } + uart_set_options(uport, NULL, baud, parity, bits, flow); + mutex_unlock(&port->mutex); + + return 0; +noport: + pr_err("Error setting baudrate of polling tty port %s%d: no port state\n", + ttydrv->name, pport->line); + return -EL3HLT; +} +EXPORT_SYMBOL(avm_tty_poll_configure); + +void avm_tty_poll_release(struct polling_tty_port *pport) +{ + struct tty_driver *ttydrv = pport->driver; + struct uart_driver *drv; + struct uart_state *state; + struct uart_port *uport; + struct tty_port *port; + + pr_debug("Releasing polling tty port %s%d\n", + ttydrv->name, pport->line); + + drv = ttydrv->driver_state; + state = drv->state + pport->line; + if (!state) + goto out; + + port = &state->port; + mutex_lock(&port->mutex); + + uport = state->uart_port; + if (!uport) { + mutex_unlock(&port->mutex); + goto out; + } + + if (uport->irq) + enable_irq(uport->irq); + + pm_runtime_put(uport->dev); + // This can be omitted for Puna and GRX + uport->ops->shutdown(uport); + mutex_unlock(&port->mutex); +out: + put_tty_driver(ttydrv); + kfree(pport); +} +EXPORT_SYMBOL(avm_tty_poll_release); + +int avm_tty_poll_get_char(struct polling_tty_port *pport) +{ + return pport->driver->ops->poll_get_char(pport->driver, pport->line); +} +EXPORT_SYMBOL(avm_tty_poll_get_char); + +void avm_tty_poll_put_char(struct polling_tty_port *pport, unsigned char c) +{ + pport->driver->ops->poll_put_char(pport->driver, pport->line, c); +} +EXPORT_SYMBOL(avm_tty_poll_put_char); +#endif /* CONFIG_AVM_TTY_POLLING */ + +#ifdef CONFIG_INTEL_UART_ENABLE_CONTROL +static ssize_t uart_get_attr_enable_ctrl(struct device *dev, + struct device_attribute *attr, char *buf) +{ + int enable; + + if (intel_ce2700_read_atom_uartctrl(&enable) != IOCNFG_OK) + pr_err(KERN_ERR "Unable to read AtomUartCtrl status\n"); + + return sprintf(buf, "%d\n", enable); +} + +static ssize_t uart_set_attr_enable_ctrl(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + int enable; + + enable = (int)(buf[0] - '0'); + if ((enable == 0) || (enable == 1)) + intel_ce2700_config_atom_uartctrl(enable); + else + pr_info(KERN_ERR "uart_enable_ctrl: 0(disable) / 1(enable) UART\n"); + + return count; +} +#endif /** * uart_register_driver - register a driver with the uart core layer * @drv: low level driver structure