Skip to content

Commit

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

Pull tty/serial driver fixes from Greg KH:
 "Here are some small bug fixes and reverts for reported problems with
  the tty core and drivers. They include:

   - revert the fifo use for the 8250 console mode. It caused too many
     regressions and problems, and had a bug in it as well. This is
     being reworked and should show up in a later -rc1 release, but it's
     not ready for 5.17

   - rpmsg tty race fix

   - restore the cyclades.h uapi header file. Turns out a compiler test
     suite used it for some unknown reason. Bring it back just for the
     parts that are used by the builder test so they continue to build.
     No functionality is restored as no one actually has this hardware
     anymore, nor is it really tested.

   - stm32 driver fixes

   - n_gsm flow control fixes

   - pl011 driver fix

   - rs485 initialization fix

  All of these have been in linux-next this week with no reported
  problems"

* tag 'tty-5.17-rc2' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty:
  kbuild: remove include/linux/cyclades.h from header file check
  serial: core: Initialize rs485 RTS polarity already on probe
  serial: pl011: Fix incorrect rs485 RTS polarity on set_mctrl
  serial: stm32: fix software flow control transfer
  serial: stm32: prevent TDR register overwrite when sending x_char
  tty: n_gsm: fix SW flow control encoding/handling
  serial: 8250: of: Fix mapped region size when using reg-offset property
  tty: rpmsg: Fix race condition releasing tty port
  tty: Partially revert the removal of the Cyclades public API
  tty: Add support for Brainboxes UC cards.
  Revert "tty: serial: Use fifo in 8250 console driver"
  • Loading branch information
torvalds committed Jan 29, 2022
2 parents 44aa31a + d1ad272 commit bb37101
Show file tree
Hide file tree
Showing 10 changed files with 205 additions and 106 deletions.
4 changes: 3 additions & 1 deletion drivers/tty/n_gsm.c
Original file line number Diff line number Diff line change
Expand Up @@ -322,6 +322,7 @@ static int addr_cnt;
#define GSM1_ESCAPE_BITS 0x20
#define XON 0x11
#define XOFF 0x13
#define ISO_IEC_646_MASK 0x7F

static const struct tty_port_operations gsm_port_ops;

Expand Down Expand Up @@ -531,7 +532,8 @@ static int gsm_stuff_frame(const u8 *input, u8 *output, int len)
int olen = 0;
while (len--) {
if (*input == GSM1_SOF || *input == GSM1_ESCAPE
|| *input == XON || *input == XOFF) {
|| (*input & ISO_IEC_646_MASK) == XON
|| (*input & ISO_IEC_646_MASK) == XOFF) {
*output++ = GSM1_ESCAPE;
*output++ = *input++ ^ GSM1_ESCAPE_BITS;
olen++;
Expand Down
40 changes: 26 additions & 14 deletions drivers/tty/rpmsg_tty.c
Original file line number Diff line number Diff line change
Expand Up @@ -50,10 +50,17 @@ static int rpmsg_tty_cb(struct rpmsg_device *rpdev, void *data, int len, void *p
static int rpmsg_tty_install(struct tty_driver *driver, struct tty_struct *tty)
{
struct rpmsg_tty_port *cport = idr_find(&tty_idr, tty->index);
struct tty_port *port;

tty->driver_data = cport;

return tty_port_install(&cport->port, driver, tty);
port = tty_port_get(&cport->port);
return tty_port_install(port, driver, tty);
}

static void rpmsg_tty_cleanup(struct tty_struct *tty)
{
tty_port_put(tty->port);
}

static int rpmsg_tty_open(struct tty_struct *tty, struct file *filp)
Expand Down Expand Up @@ -106,12 +113,19 @@ static unsigned int rpmsg_tty_write_room(struct tty_struct *tty)
return size;
}

static void rpmsg_tty_hangup(struct tty_struct *tty)
{
tty_port_hangup(tty->port);
}

static const struct tty_operations rpmsg_tty_ops = {
.install = rpmsg_tty_install,
.open = rpmsg_tty_open,
.close = rpmsg_tty_close,
.write = rpmsg_tty_write,
.write_room = rpmsg_tty_write_room,
.hangup = rpmsg_tty_hangup,
.cleanup = rpmsg_tty_cleanup,
};

static struct rpmsg_tty_port *rpmsg_tty_alloc_cport(void)
Expand All @@ -137,16 +151,21 @@ static struct rpmsg_tty_port *rpmsg_tty_alloc_cport(void)
return cport;
}

static void rpmsg_tty_release_cport(struct rpmsg_tty_port *cport)
static void rpmsg_tty_destruct_port(struct tty_port *port)
{
struct rpmsg_tty_port *cport = container_of(port, struct rpmsg_tty_port, port);

mutex_lock(&idr_lock);
idr_remove(&tty_idr, cport->id);
mutex_unlock(&idr_lock);

kfree(cport);
}

static const struct tty_port_operations rpmsg_tty_port_ops = { };
static const struct tty_port_operations rpmsg_tty_port_ops = {
.destruct = rpmsg_tty_destruct_port,
};


static int rpmsg_tty_probe(struct rpmsg_device *rpdev)
{
Expand All @@ -166,7 +185,8 @@ static int rpmsg_tty_probe(struct rpmsg_device *rpdev)
cport->id, dev);
if (IS_ERR(tty_dev)) {
ret = dev_err_probe(dev, PTR_ERR(tty_dev), "Failed to register tty port\n");
goto err_destroy;
tty_port_put(&cport->port);
return ret;
}

cport->rpdev = rpdev;
Expand All @@ -177,12 +197,6 @@ static int rpmsg_tty_probe(struct rpmsg_device *rpdev)
rpdev->src, rpdev->dst, cport->id);

return 0;

err_destroy:
tty_port_destroy(&cport->port);
rpmsg_tty_release_cport(cport);

return ret;
}

static void rpmsg_tty_remove(struct rpmsg_device *rpdev)
Expand All @@ -192,13 +206,11 @@ static void rpmsg_tty_remove(struct rpmsg_device *rpdev)
dev_dbg(&rpdev->dev, "Removing rpmsg tty device %d\n", cport->id);

/* User hang up to release the tty */
if (tty_port_initialized(&cport->port))
tty_port_tty_hangup(&cport->port, false);
tty_port_tty_hangup(&cport->port, false);

tty_unregister_device(rpmsg_tty_driver, cport->id);

tty_port_destroy(&cport->port);
rpmsg_tty_release_cport(cport);
tty_port_put(&cport->port);
}

static struct rpmsg_device_id rpmsg_driver_tty_id_table[] = {
Expand Down
11 changes: 10 additions & 1 deletion drivers/tty/serial/8250/8250_of.c
Original file line number Diff line number Diff line change
Expand Up @@ -83,8 +83,17 @@ static int of_platform_serial_setup(struct platform_device *ofdev,
port->mapsize = resource_size(&resource);

/* Check for shifted address mapping */
if (of_property_read_u32(np, "reg-offset", &prop) == 0)
if (of_property_read_u32(np, "reg-offset", &prop) == 0) {
if (prop >= port->mapsize) {
dev_warn(&ofdev->dev, "reg-offset %u exceeds region size %pa\n",
prop, &port->mapsize);
ret = -EINVAL;
goto err_unprepare;
}

port->mapbase += prop;
port->mapsize -= prop;
}

port->iotype = UPIO_MEM;
if (of_property_read_u32(np, "reg-io-width", &prop) == 0) {
Expand Down
100 changes: 98 additions & 2 deletions drivers/tty/serial/8250/8250_pci.c
Original file line number Diff line number Diff line change
Expand Up @@ -4779,16 +4779,112 @@ static const struct pci_device_id serial_pci_tbl[] = {
{ PCI_VENDOR_ID_INTASHIELD, PCI_DEVICE_ID_INTASHIELD_IS400,
PCI_ANY_ID, PCI_ANY_ID, 0, 0, /* 135a.0dc0 */
pbn_b2_4_115200 },
/* Brainboxes Devices */
/*
* BrainBoxes UC-260
* Brainboxes UC-101
*/
{ PCI_VENDOR_ID_INTASHIELD, 0x0BA1,
PCI_ANY_ID, PCI_ANY_ID,
0, 0,
pbn_b2_2_115200 },
/*
* Brainboxes UC-235/246
*/
{ PCI_VENDOR_ID_INTASHIELD, 0x0AA1,
PCI_ANY_ID, PCI_ANY_ID,
0, 0,
pbn_b2_1_115200 },
/*
* Brainboxes UC-257
*/
{ PCI_VENDOR_ID_INTASHIELD, 0x0861,
PCI_ANY_ID, PCI_ANY_ID,
0, 0,
pbn_b2_2_115200 },
/*
* Brainboxes UC-260/271/701/756
*/
{ PCI_VENDOR_ID_INTASHIELD, 0x0D21,
PCI_ANY_ID, PCI_ANY_ID,
PCI_CLASS_COMMUNICATION_MULTISERIAL << 8, 0xffff00,
pbn_b2_4_115200 },
{ PCI_VENDOR_ID_INTASHIELD, 0x0E34,
PCI_ANY_ID, PCI_ANY_ID,
PCI_CLASS_COMMUNICATION_MULTISERIAL << 8, 0xffff00,
PCI_CLASS_COMMUNICATION_MULTISERIAL << 8, 0xffff00,
pbn_b2_4_115200 },
/*
* Brainboxes UC-268
*/
{ PCI_VENDOR_ID_INTASHIELD, 0x0841,
PCI_ANY_ID, PCI_ANY_ID,
0, 0,
pbn_b2_4_115200 },
/*
* Brainboxes UC-275/279
*/
{ PCI_VENDOR_ID_INTASHIELD, 0x0881,
PCI_ANY_ID, PCI_ANY_ID,
0, 0,
pbn_b2_8_115200 },
/*
* Brainboxes UC-302
*/
{ PCI_VENDOR_ID_INTASHIELD, 0x08E1,
PCI_ANY_ID, PCI_ANY_ID,
0, 0,
pbn_b2_2_115200 },
/*
* Brainboxes UC-310
*/
{ PCI_VENDOR_ID_INTASHIELD, 0x08C1,
PCI_ANY_ID, PCI_ANY_ID,
0, 0,
pbn_b2_2_115200 },
/*
* Brainboxes UC-313
*/
{ PCI_VENDOR_ID_INTASHIELD, 0x08A3,
PCI_ANY_ID, PCI_ANY_ID,
0, 0,
pbn_b2_2_115200 },
/*
* Brainboxes UC-320/324
*/
{ PCI_VENDOR_ID_INTASHIELD, 0x0A61,
PCI_ANY_ID, PCI_ANY_ID,
0, 0,
pbn_b2_1_115200 },
/*
* Brainboxes UC-346
*/
{ PCI_VENDOR_ID_INTASHIELD, 0x0B02,
PCI_ANY_ID, PCI_ANY_ID,
0, 0,
pbn_b2_4_115200 },
/*
* Brainboxes UC-357
*/
{ PCI_VENDOR_ID_INTASHIELD, 0x0A81,
PCI_ANY_ID, PCI_ANY_ID,
0, 0,
pbn_b2_2_115200 },
{ PCI_VENDOR_ID_INTASHIELD, 0x0A83,
PCI_ANY_ID, PCI_ANY_ID,
0, 0,
pbn_b2_2_115200 },
/*
* Brainboxes UC-368
*/
{ PCI_VENDOR_ID_INTASHIELD, 0x0C41,
PCI_ANY_ID, PCI_ANY_ID,
0, 0,
pbn_b2_4_115200 },
/*
* Brainboxes UC-420/431
*/
{ PCI_VENDOR_ID_INTASHIELD, 0x0921,
PCI_ANY_ID, PCI_ANY_ID,
0, 0,
pbn_b2_4_115200 },
/*
* Perle PCI-RAS cards
Expand Down
61 changes: 6 additions & 55 deletions drivers/tty/serial/8250/8250_port.c
Original file line number Diff line number Diff line change
Expand Up @@ -2056,7 +2056,10 @@ static void serial8250_break_ctl(struct uart_port *port, int break_state)
serial8250_rpm_put(up);
}

static void wait_for_lsr(struct uart_8250_port *up, int bits)
/*
* Wait for transmitter & holding register to empty
*/
static void wait_for_xmitr(struct uart_8250_port *up, int bits)
{
unsigned int status, tmout = 10000;

Expand All @@ -2073,16 +2076,6 @@ static void wait_for_lsr(struct uart_8250_port *up, int bits)
udelay(1);
touch_nmi_watchdog();
}
}

/*
* Wait for transmitter & holding register to empty
*/
static void wait_for_xmitr(struct uart_8250_port *up, int bits)
{
unsigned int tmout;

wait_for_lsr(up, bits);

/* Wait up to 1s for flow control if necessary */
if (up->port.flags & UPF_CONS_FLOW) {
Expand Down Expand Up @@ -3332,35 +3325,6 @@ static void serial8250_console_restore(struct uart_8250_port *up)
serial8250_out_MCR(up, UART_MCR_DTR | UART_MCR_RTS);
}

/*
* Print a string to the serial port using the device FIFO
*
* It sends fifosize bytes and then waits for the fifo
* to get empty.
*/
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->port.fifosize;
bool cr_sent = false;

while (s != end) {
wait_for_lsr(up, UART_LSR_THRE);

for (i = 0; i < fifosize && s != end; ++i) {
if (*s == '\n' && !cr_sent) {
serial_out(up, UART_TX, '\r');
cr_sent = true;
} else {
serial_out(up, UART_TX, *s++);
cr_sent = false;
}
}
}
}

/*
* Print a string to the serial port trying not to disturb
* any possible real use of the port...
Expand All @@ -3376,7 +3340,7 @@ void serial8250_console_write(struct uart_8250_port *up, const char *s,
struct uart_8250_em485 *em485 = up->em485;
struct uart_port *port = &up->port;
unsigned long flags;
unsigned int ier, use_fifo;
unsigned int ier;
int locked = 1;

touch_nmi_watchdog();
Expand Down Expand Up @@ -3408,20 +3372,7 @@ void serial8250_console_write(struct uart_8250_port *up, const char *s,
mdelay(port->rs485.delay_rts_before_send);
}

use_fifo = (up->capabilities & UART_CAP_FIFO) &&
port->fifosize > 1 &&
(serial_port_in(port, UART_FCR) & UART_FCR_ENABLE_FIFO) &&
/*
* After we put a data in the fifo, the controller will send
* it regardless of the CTS state. Therefore, only use fifo
* if we don't use control flow.
*/
!(up->port.flags & UPF_CONS_FLOW);

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_putchar);

/*
* Finally, wait for transmitter to become empty
Expand Down
11 changes: 1 addition & 10 deletions drivers/tty/serial/amba-pl011.c
Original file line number Diff line number Diff line change
Expand Up @@ -1582,9 +1582,6 @@ static void pl011_set_mctrl(struct uart_port *port, unsigned int mctrl)
container_of(port, struct uart_amba_port, port);
unsigned int cr;

if (port->rs485.flags & SER_RS485_ENABLED)
mctrl &= ~TIOCM_RTS;

cr = pl011_read(uap, REG_CR);

#define TIOCMBIT(tiocmbit, uartbit) \
Expand Down Expand Up @@ -1808,14 +1805,8 @@ static int pl011_startup(struct uart_port *port)
cr &= UART011_CR_RTS | UART011_CR_DTR;
cr |= UART01x_CR_UARTEN | UART011_CR_RXE;

if (port->rs485.flags & SER_RS485_ENABLED) {
if (port->rs485.flags & SER_RS485_RTS_AFTER_SEND)
cr &= ~UART011_CR_RTS;
else
cr |= UART011_CR_RTS;
} else {
if (!(port->rs485.flags & SER_RS485_ENABLED))
cr |= UART011_CR_TXE;
}

pl011_write(cr, uap, REG_CR);

Expand Down
Loading

0 comments on commit bb37101

Please sign in to comment.