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

Merge tag 'tty-5.13-rc4' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty

Pull tty / serial driver fixes from Greg KH:
"Here are some small fixes for reported problems for tty and serial
drivers for 5.13-rc4.

They consist of:

- 8250 bugfixes and new device support

- lockdown security mode fixup

- syzbot found problems fixed

- 8250_omap fix for interrupt storm

- revert of 8250_omap driver fix as it caused worse problem than the
original issue

All but the last patch have been in linux-next for a while, the last
one is a revert of a problem found in linux-next with the 8250_omap
driver change"

* tag 'tty-5.13-rc4' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty:
Revert "serial: 8250: 8250_omap: Fix possible interrupt storm"
serial: 8250_pci: handle FL_NOIRQ board flag
serial: rp2: use 'request_firmware' instead of 'request_firmware_nowait'
serial: 8250_pci: Add support for new HPE serial device
serial: 8250: 8250_omap: Fix possible interrupt storm
serial: 8250: Use BIT(x) for UART_{CAP,BUG}_*
serial: 8250: Add UART_BUG_TXRACE workaround for Aspeed VUART
serial: 8250_dw: Add device HID for new AMD UART controller
serial: sh-sci: Fix off-by-one error in FIFO threshold register setting
serial: core: fix suspicious security_locked_down() call
serial: tegra: Fix a mask operation that is always true

+92 -68
+1
drivers/acpi/acpi_apd.c
··· 226 226 { "AMDI0010", APD_ADDR(wt_i2c_desc) }, 227 227 { "AMD0020", APD_ADDR(cz_uart_desc) }, 228 228 { "AMDI0020", APD_ADDR(cz_uart_desc) }, 229 + { "AMDI0022", APD_ADDR(cz_uart_desc) }, 229 230 { "AMD0030", }, 230 231 { "AMD0040", APD_ADDR(fch_misc_desc)}, 231 232 { "HYGO0010", APD_ADDR(wt_i2c_desc) },
+17 -15
drivers/tty/serial/8250/8250.h
··· 7 7 * Copyright (C) 2001 Russell King. 8 8 */ 9 9 10 + #include <linux/bits.h> 10 11 #include <linux/serial_8250.h> 11 12 #include <linux/serial_reg.h> 12 13 #include <linux/dmaengine.h> ··· 71 70 unsigned int flags; 72 71 }; 73 72 74 - #define UART_CAP_FIFO (1 << 8) /* UART has FIFO */ 75 - #define UART_CAP_EFR (1 << 9) /* UART has EFR */ 76 - #define UART_CAP_SLEEP (1 << 10) /* UART has IER sleep */ 77 - #define UART_CAP_AFE (1 << 11) /* MCR-based hw flow control */ 78 - #define UART_CAP_UUE (1 << 12) /* UART needs IER bit 6 set (Xscale) */ 79 - #define UART_CAP_RTOIE (1 << 13) /* UART needs IER bit 4 set (Xscale, Tegra) */ 80 - #define UART_CAP_HFIFO (1 << 14) /* UART has a "hidden" FIFO */ 81 - #define UART_CAP_RPM (1 << 15) /* Runtime PM is active while idle */ 82 - #define UART_CAP_IRDA (1 << 16) /* UART supports IrDA line discipline */ 83 - #define UART_CAP_MINI (1 << 17) /* Mini UART on BCM283X family lacks: 73 + #define UART_CAP_FIFO BIT(8) /* UART has FIFO */ 74 + #define UART_CAP_EFR BIT(9) /* UART has EFR */ 75 + #define UART_CAP_SLEEP BIT(10) /* UART has IER sleep */ 76 + #define UART_CAP_AFE BIT(11) /* MCR-based hw flow control */ 77 + #define UART_CAP_UUE BIT(12) /* UART needs IER bit 6 set (Xscale) */ 78 + #define UART_CAP_RTOIE BIT(13) /* UART needs IER bit 4 set (Xscale, Tegra) */ 79 + #define UART_CAP_HFIFO BIT(14) /* UART has a "hidden" FIFO */ 80 + #define UART_CAP_RPM BIT(15) /* Runtime PM is active while idle */ 81 + #define UART_CAP_IRDA BIT(16) /* UART supports IrDA line discipline */ 82 + #define UART_CAP_MINI BIT(17) /* Mini UART on BCM283X family lacks: 84 83 * STOP PARITY EPAR SPAR WLEN5 WLEN6 85 84 */ 86 85 87 - #define UART_BUG_QUOT (1 << 0) /* UART has buggy quot LSB */ 88 - #define UART_BUG_TXEN (1 << 1) /* UART has buggy TX IIR status */ 89 - #define UART_BUG_NOMSR (1 << 2) /* UART has buggy MSR status bits (Au1x00) */ 90 - #define UART_BUG_THRE (1 << 3) /* UART has buggy THRE reassertion */ 91 - #define UART_BUG_PARITY (1 << 4) /* UART mishandles parity if FIFO enabled */ 86 + #define UART_BUG_QUOT BIT(0) /* UART has buggy quot LSB */ 87 + #define UART_BUG_TXEN BIT(1) /* UART has buggy TX IIR status */ 88 + #define UART_BUG_NOMSR BIT(2) /* UART has buggy MSR status bits (Au1x00) */ 89 + #define UART_BUG_THRE BIT(3) /* UART has buggy THRE reassertion */ 90 + #define UART_BUG_PARITY BIT(4) /* UART mishandles parity if FIFO enabled */ 91 + #define UART_BUG_TXRACE BIT(5) /* UART Tx fails to set remote DR */ 92 92 93 93 94 94 #ifdef CONFIG_SERIAL_8250_SHARE_IRQ
+1
drivers/tty/serial/8250/8250_aspeed_vuart.c
··· 437 437 port.port.status = UPSTAT_SYNC_FIFO; 438 438 port.port.dev = &pdev->dev; 439 439 port.port.has_sysrq = IS_ENABLED(CONFIG_SERIAL_8250_CONSOLE); 440 + port.bugs |= UART_BUG_TXRACE; 440 441 441 442 rc = sysfs_create_group(&vuart->dev->kobj, &aspeed_vuart_attr_group); 442 443 if (rc < 0)
+1
drivers/tty/serial/8250/8250_dw.c
··· 714 714 { "APMC0D08", 0}, 715 715 { "AMD0020", 0 }, 716 716 { "AMDI0020", 0 }, 717 + { "AMDI0022", 0 }, 717 718 { "BRCM2032", 0 }, 718 719 { "HISI0031", 0 }, 719 720 { },
+35 -12
drivers/tty/serial/8250/8250_pci.c
··· 56 56 int line[]; 57 57 }; 58 58 59 + #define PCI_DEVICE_ID_HPE_PCI_SERIAL 0x37e 60 + 59 61 static const struct pci_device_id pci_use_msi[] = { 60 62 { PCI_DEVICE_SUB(PCI_VENDOR_ID_NETMOS, PCI_DEVICE_ID_NETMOS_9900, 61 63 0xA000, 0x1000) }, ··· 65 63 0xA000, 0x1000) }, 66 64 { PCI_DEVICE_SUB(PCI_VENDOR_ID_NETMOS, PCI_DEVICE_ID_NETMOS_9922, 67 65 0xA000, 0x1000) }, 66 + { PCI_DEVICE_SUB(PCI_VENDOR_ID_HP_3PAR, PCI_DEVICE_ID_HPE_PCI_SERIAL, 67 + PCI_ANY_ID, PCI_ANY_ID) }, 68 68 { } 69 69 }; 70 70 ··· 1999 1995 .subvendor = PCI_ANY_ID, 2000 1996 .subdevice = PCI_ANY_ID, 2001 1997 .init = pci_hp_diva_init, 1998 + .setup = pci_hp_diva_setup, 1999 + }, 2000 + /* 2001 + * HPE PCI serial device 2002 + */ 2003 + { 2004 + .vendor = PCI_VENDOR_ID_HP_3PAR, 2005 + .device = PCI_DEVICE_ID_HPE_PCI_SERIAL, 2006 + .subvendor = PCI_ANY_ID, 2007 + .subdevice = PCI_ANY_ID, 2002 2008 .setup = pci_hp_diva_setup, 2003 2009 }, 2004 2010 /* ··· 3958 3944 uart.port.flags = UPF_SKIP_TEST | UPF_BOOT_AUTOCONF | UPF_SHARE_IRQ; 3959 3945 uart.port.uartclk = board->base_baud * 16; 3960 3946 3961 - if (pci_match_id(pci_use_msi, dev)) { 3962 - dev_dbg(&dev->dev, "Using MSI(-X) interrupts\n"); 3963 - pci_set_master(dev); 3964 - rc = pci_alloc_irq_vectors(dev, 1, 1, PCI_IRQ_ALL_TYPES); 3947 + if (board->flags & FL_NOIRQ) { 3948 + uart.port.irq = 0; 3965 3949 } else { 3966 - dev_dbg(&dev->dev, "Using legacy interrupts\n"); 3967 - rc = pci_alloc_irq_vectors(dev, 1, 1, PCI_IRQ_LEGACY); 3968 - } 3969 - if (rc < 0) { 3970 - kfree(priv); 3971 - priv = ERR_PTR(rc); 3972 - goto err_deinit; 3950 + if (pci_match_id(pci_use_msi, dev)) { 3951 + dev_dbg(&dev->dev, "Using MSI(-X) interrupts\n"); 3952 + pci_set_master(dev); 3953 + rc = pci_alloc_irq_vectors(dev, 1, 1, PCI_IRQ_ALL_TYPES); 3954 + } else { 3955 + dev_dbg(&dev->dev, "Using legacy interrupts\n"); 3956 + rc = pci_alloc_irq_vectors(dev, 1, 1, PCI_IRQ_LEGACY); 3957 + } 3958 + if (rc < 0) { 3959 + kfree(priv); 3960 + priv = ERR_PTR(rc); 3961 + goto err_deinit; 3962 + } 3963 + 3964 + uart.port.irq = pci_irq_vector(dev, 0); 3973 3965 } 3974 3966 3975 - uart.port.irq = pci_irq_vector(dev, 0); 3976 3967 uart.port.dev = &dev->dev; 3977 3968 3978 3969 for (i = 0; i < nr_ports; i++) { ··· 4992 4973 { PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_DIVA_AUX, 4993 4974 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 4994 4975 pbn_b2_1_115200 }, 4976 + /* HPE PCI serial device */ 4977 + { PCI_VENDOR_ID_HP_3PAR, PCI_DEVICE_ID_HPE_PCI_SERIAL, 4978 + PCI_ANY_ID, PCI_ANY_ID, 0, 0, 4979 + pbn_b1_1_115200 }, 4995 4980 4996 4981 { PCI_VENDOR_ID_DCI, PCI_DEVICE_ID_DCI_PCCOM2, 4997 4982 PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+12
drivers/tty/serial/8250/8250_port.c
··· 1809 1809 count = up->tx_loadsz; 1810 1810 do { 1811 1811 serial_out(up, UART_TX, xmit->buf[xmit->tail]); 1812 + if (up->bugs & UART_BUG_TXRACE) { 1813 + /* 1814 + * The Aspeed BMC virtual UARTs have a bug where data 1815 + * may get stuck in the BMC's Tx FIFO from bursts of 1816 + * writes on the APB interface. 1817 + * 1818 + * Delay back-to-back writes by a read cycle to avoid 1819 + * stalling the VUART. Read a register that won't have 1820 + * side-effects and discard the result. 1821 + */ 1822 + serial_in(up, UART_SCR); 1823 + } 1812 1824 xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1); 1813 1825 port->icount.tx++; 1814 1826 if (uart_circ_empty(xmit))
+17 -35
drivers/tty/serial/rp2.c
··· 195 195 void __iomem *bar0; 196 196 void __iomem *bar1; 197 197 spinlock_t card_lock; 198 - struct completion fw_loaded; 199 198 }; 200 199 201 200 #define RP_ID(prod) PCI_VDEVICE(RP, (prod)) ··· 661 662 card->initialized_ports = 0; 662 663 } 663 664 664 - static void rp2_fw_cb(const struct firmware *fw, void *context) 665 + static int rp2_load_firmware(struct rp2_card *card, const struct firmware *fw) 665 666 { 666 - struct rp2_card *card = context; 667 667 resource_size_t phys_base; 668 - int i, rc = -ENOENT; 669 - 670 - if (!fw) { 671 - dev_err(&card->pdev->dev, "cannot find '%s' firmware image\n", 672 - RP2_FW_NAME); 673 - goto no_fw; 674 - } 668 + int i, rc = 0; 675 669 676 670 phys_base = pci_resource_start(card->pdev, 1); 677 671 ··· 710 718 card->initialized_ports++; 711 719 } 712 720 713 - release_firmware(fw); 714 - no_fw: 715 - /* 716 - * rp2_fw_cb() is called from a workqueue long after rp2_probe() 717 - * has already returned success. So if something failed here, 718 - * we'll just leave the now-dormant device in place until somebody 719 - * unbinds it. 720 - */ 721 - if (rc) 722 - dev_warn(&card->pdev->dev, "driver initialization failed\n"); 723 - 724 - complete(&card->fw_loaded); 721 + return rc; 725 722 } 726 723 727 724 static int rp2_probe(struct pci_dev *pdev, 728 725 const struct pci_device_id *id) 729 726 { 727 + const struct firmware *fw; 730 728 struct rp2_card *card; 731 729 struct rp2_uart_port *ports; 732 730 void __iomem * const *bars; ··· 727 745 return -ENOMEM; 728 746 pci_set_drvdata(pdev, card); 729 747 spin_lock_init(&card->card_lock); 730 - init_completion(&card->fw_loaded); 731 748 732 749 rc = pcim_enable_device(pdev); 733 750 if (rc) ··· 759 778 return -ENOMEM; 760 779 card->ports = ports; 761 780 781 + rc = request_firmware(&fw, RP2_FW_NAME, &pdev->dev); 782 + if (rc < 0) { 783 + dev_err(&pdev->dev, "cannot find '%s' firmware image\n", 784 + RP2_FW_NAME); 785 + return rc; 786 + } 787 + 788 + rc = rp2_load_firmware(card, fw); 789 + 790 + release_firmware(fw); 791 + if (rc < 0) 792 + return rc; 793 + 762 794 rc = devm_request_irq(&pdev->dev, pdev->irq, rp2_uart_interrupt, 763 795 IRQF_SHARED, DRV_NAME, card); 764 796 if (rc) 765 797 return rc; 766 - 767 - /* 768 - * Only catastrophic errors (e.g. ENOMEM) are reported here. 769 - * If the FW image is missing, we'll find out in rp2_fw_cb() 770 - * and print an error message. 771 - */ 772 - rc = request_firmware_nowait(THIS_MODULE, 1, RP2_FW_NAME, &pdev->dev, 773 - GFP_KERNEL, card, rp2_fw_cb); 774 - if (rc) 775 - return rc; 776 - dev_dbg(&pdev->dev, "waiting for firmware blob...\n"); 777 798 778 799 return 0; 779 800 } ··· 784 801 { 785 802 struct rp2_card *card = pci_get_drvdata(pdev); 786 803 787 - wait_for_completion(&card->fw_loaded); 788 804 rp2_remove_ports(card); 789 805 } 790 806
+1 -1
drivers/tty/serial/serial-tegra.c
··· 338 338 339 339 do { 340 340 lsr = tegra_uart_read(tup, UART_LSR); 341 - if ((lsr | UART_LSR_TEMT) && !(lsr & UART_LSR_DR)) 341 + if ((lsr & UART_LSR_TEMT) && !(lsr & UART_LSR_DR)) 342 342 break; 343 343 udelay(1); 344 344 } while (--tmout);
+5 -3
drivers/tty/serial/serial_core.c
··· 863 863 goto check_and_exit; 864 864 } 865 865 866 - retval = security_locked_down(LOCKDOWN_TIOCSSERIAL); 867 - if (retval && (change_irq || change_port)) 868 - goto exit; 866 + if (change_irq || change_port) { 867 + retval = security_locked_down(LOCKDOWN_TIOCSSERIAL); 868 + if (retval) 869 + goto exit; 870 + } 869 871 870 872 /* 871 873 * Ask the low level driver to verify the settings.
+2 -2
drivers/tty/serial/sh-sci.c
··· 1023 1023 { 1024 1024 unsigned int bits; 1025 1025 1026 + if (rx_trig >= port->fifosize) 1027 + rx_trig = port->fifosize - 1; 1026 1028 if (rx_trig < 1) 1027 1029 rx_trig = 1; 1028 - if (rx_trig >= port->fifosize) 1029 - rx_trig = port->fifosize; 1030 1030 1031 1031 /* HSCIF can be set to an arbitrary level. */ 1032 1032 if (sci_getreg(port, HSRTRGR)->size) {