Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

tty: serial: uartlite: Prevent changing fixed parameters

This device does not support changing baud, parity, data bits, stop
bits, or detecting breaks. Disable "changing" these settings to prevent
their termios from diverging from the actual state of the uart.

In order to determine the correct parameters to enforce, we read the
various new devicetree parameters to discover how the uart was
configured when it was synthesized. The defaults match
ulite_console_setup. xlnx,use-parity, xlnx,odd-parity, and
xlnx,data-bits are optional since there were in-tree users (and
presumably out-of-tree users) who did not set them.

Signed-off-by: Sean Anderson <sean.anderson@seco.com>
Link: https://lore.kernel.org/r/20210826192154.3202269-5-sean.anderson@seco.com
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

authored by

Sean Anderson and committed by
Greg Kroah-Hartman
ea017f58 8517b62e

+80 -11
+80 -11
drivers/tty/serial/uartlite.c
··· 8 8 9 9 #include <linux/platform_device.h> 10 10 #include <linux/module.h> 11 + #include <linux/bitfield.h> 11 12 #include <linux/console.h> 12 13 #include <linux/serial.h> 13 14 #include <linux/serial_core.h> ··· 64 63 static struct uart_port *console_port; 65 64 #endif 66 65 66 + /** 67 + * struct uartlite_data: Driver private data 68 + * reg_ops: Functions to read/write registers 69 + * clk: Our parent clock, if present 70 + * baud: The baud rate configured when this device was synthesized 71 + * cflags: The cflags for parity and data bits 72 + */ 67 73 struct uartlite_data { 68 74 const struct uartlite_reg_ops *reg_ops; 69 75 struct clk *clk; 76 + unsigned int baud; 77 + tcflag_t cflags; 70 78 }; 71 79 72 80 struct uartlite_reg_ops { ··· 128 118 } 129 119 130 120 static struct uart_port ulite_ports[ULITE_NR_UARTS]; 121 + 122 + static struct uart_driver ulite_uart_driver; 131 123 132 124 /* --------------------------------------------------------------------- 133 125 * Core UART driver operations ··· 318 306 struct ktermios *old) 319 307 { 320 308 unsigned long flags; 321 - unsigned int baud; 309 + struct uartlite_data *pdata = port->private_data; 310 + 311 + /* Set termios to what the hardware supports */ 312 + termios->c_cflag &= ~(BRKINT | CSTOPB | PARENB | PARODD | CSIZE); 313 + termios->c_cflag |= pdata->cflags & (PARENB | PARODD | CSIZE); 314 + tty_termios_encode_baud_rate(termios, pdata->baud, pdata->baud); 322 315 323 316 spin_lock_irqsave(&port->lock, flags); 324 317 ··· 346 329 | ULITE_STATUS_FRAME | ULITE_STATUS_OVERRUN; 347 330 348 331 /* update timeout */ 349 - baud = uart_get_baud_rate(port, termios, old, 0, 460800); 350 - uart_update_timeout(port, termios->c_cflag, baud); 332 + uart_update_timeout(port, termios->c_cflag, pdata->baud); 351 333 352 334 spin_unlock_irqrestore(&port->lock, flags); 353 335 } ··· 547 531 548 532 return uart_set_options(port, co, baud, parity, bits, flow); 549 533 } 550 - 551 - static struct uart_driver ulite_uart_driver; 552 534 553 535 static struct console ulite_console = { 554 536 .name = ULITE_NAME, ··· 779 765 struct uartlite_data *pdata; 780 766 int irq, ret; 781 767 int id = pdev->id; 782 - #ifdef CONFIG_OF 783 - const __be32 *prop; 784 768 785 - prop = of_get_property(pdev->dev.of_node, "port-number", NULL); 786 - if (prop) 787 - id = be32_to_cpup(prop); 788 - #endif 789 769 pdata = devm_kzalloc(&pdev->dev, sizeof(struct uartlite_data), 790 770 GFP_KERNEL); 791 771 if (!pdata) 792 772 return -ENOMEM; 773 + 774 + if (IS_ENABLED(CONFIG_OF)) { 775 + const char *prop; 776 + struct device_node *np = pdev->dev.of_node; 777 + u32 val = 0; 778 + 779 + prop = "port-number"; 780 + ret = of_property_read_u32(np, prop, &id); 781 + if (ret && ret != -EINVAL) 782 + of_err: 783 + return dev_err_probe(&pdev->dev, ret, 784 + "could not read %s\n", prop); 785 + 786 + prop = "current-speed"; 787 + ret = of_property_read_u32(np, prop, &pdata->baud); 788 + if (ret) 789 + goto of_err; 790 + 791 + prop = "xlnx,use-parity"; 792 + ret = of_property_read_u32(np, prop, &val); 793 + if (ret && ret != -EINVAL) 794 + goto of_err; 795 + 796 + if (val) { 797 + prop = "xlnx,odd-parity"; 798 + ret = of_property_read_u32(np, prop, &val); 799 + if (ret) 800 + goto of_err; 801 + 802 + if (val) 803 + pdata->cflags |= PARODD; 804 + pdata->cflags |= PARENB; 805 + } 806 + 807 + val = 8; 808 + prop = "xlnx,data-bits"; 809 + ret = of_property_read_u32(np, prop, &val); 810 + if (ret && ret != -EINVAL) 811 + goto of_err; 812 + 813 + switch (val) { 814 + case 5: 815 + pdata->cflags |= CS5; 816 + break; 817 + case 6: 818 + pdata->cflags |= CS6; 819 + break; 820 + case 7: 821 + pdata->cflags |= CS7; 822 + break; 823 + case 8: 824 + pdata->cflags |= CS8; 825 + break; 826 + default: 827 + return dev_err_probe(&pdev->dev, -EINVAL, 828 + "bad data bits %d\n", val); 829 + } 830 + } else { 831 + pdata->baud = 9600; 832 + pdata->cflags = CS8; 833 + } 793 834 794 835 res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 795 836 if (!res)