Skip to content

Commit 42b34a8

Browse files
committed
Merge tag 'tty-6.11-rc3' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty
Pull tty / serial driver fixes from Greg KH: "Here are some small tty and serial driver fixes for reported problems for 6.11-rc3. Included in here are: - sc16is7xx serial driver fixes - uartclk bugfix for a divide by zero issue - conmakehash userspace build issue fix All of these have been in linux-next for a while with no reported issues" * tag 'tty-6.11-rc3' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty: tty: vt: conmakehash: cope with abs_srctree no longer in env serial: sc16is7xx: fix invalid FIFO access with special register set serial: sc16is7xx: fix TX fifo corruption serial: core: check uartclk for zero to avoid divide by zero
2 parents 84e6da5 + 6e20753 commit 42b34a8

File tree

3 files changed

+30
-23
lines changed

3 files changed

+30
-23
lines changed

drivers/tty/serial/sc16is7xx.c

Lines changed: 15 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -327,6 +327,7 @@ struct sc16is7xx_one {
327327
struct kthread_work reg_work;
328328
struct kthread_delayed_work ms_work;
329329
struct sc16is7xx_one_config config;
330+
unsigned char buf[SC16IS7XX_FIFO_SIZE]; /* Rx buffer. */
330331
unsigned int old_mctrl;
331332
u8 old_lcr; /* Value before EFR access. */
332333
bool irda_mode;
@@ -340,7 +341,6 @@ struct sc16is7xx_port {
340341
unsigned long gpio_valid_mask;
341342
#endif
342343
u8 mctrl_mask;
343-
unsigned char buf[SC16IS7XX_FIFO_SIZE];
344344
struct kthread_worker kworker;
345345
struct task_struct *kworker_task;
346346
struct sc16is7xx_one p[];
@@ -592,6 +592,8 @@ static int sc16is7xx_set_baud(struct uart_port *port, int baud)
592592
SC16IS7XX_MCR_CLKSEL_BIT,
593593
prescaler == 1 ? 0 : SC16IS7XX_MCR_CLKSEL_BIT);
594594

595+
mutex_lock(&one->efr_lock);
596+
595597
/* Backup LCR and access special register set (DLL/DLH) */
596598
lcr = sc16is7xx_port_read(port, SC16IS7XX_LCR_REG);
597599
sc16is7xx_port_write(port, SC16IS7XX_LCR_REG,
@@ -606,24 +608,26 @@ static int sc16is7xx_set_baud(struct uart_port *port, int baud)
606608
/* Restore LCR and access to general register set */
607609
sc16is7xx_port_write(port, SC16IS7XX_LCR_REG, lcr);
608610

611+
mutex_unlock(&one->efr_lock);
612+
609613
return DIV_ROUND_CLOSEST((clk / prescaler) / 16, div);
610614
}
611615

612616
static void sc16is7xx_handle_rx(struct uart_port *port, unsigned int rxlen,
613617
unsigned int iir)
614618
{
615-
struct sc16is7xx_port *s = dev_get_drvdata(port->dev);
619+
struct sc16is7xx_one *one = to_sc16is7xx_one(port, port);
616620
unsigned int lsr = 0, bytes_read, i;
617621
bool read_lsr = (iir == SC16IS7XX_IIR_RLSE_SRC) ? true : false;
618622
u8 ch, flag;
619623

620-
if (unlikely(rxlen >= sizeof(s->buf))) {
624+
if (unlikely(rxlen >= sizeof(one->buf))) {
621625
dev_warn_ratelimited(port->dev,
622626
"ttySC%i: Possible RX FIFO overrun: %d\n",
623627
port->line, rxlen);
624628
port->icount.buf_overrun++;
625629
/* Ensure sanity of RX level */
626-
rxlen = sizeof(s->buf);
630+
rxlen = sizeof(one->buf);
627631
}
628632

629633
while (rxlen) {
@@ -636,10 +640,10 @@ static void sc16is7xx_handle_rx(struct uart_port *port, unsigned int rxlen,
636640
lsr = 0;
637641

638642
if (read_lsr) {
639-
s->buf[0] = sc16is7xx_port_read(port, SC16IS7XX_RHR_REG);
643+
one->buf[0] = sc16is7xx_port_read(port, SC16IS7XX_RHR_REG);
640644
bytes_read = 1;
641645
} else {
642-
sc16is7xx_fifo_read(port, s->buf, rxlen);
646+
sc16is7xx_fifo_read(port, one->buf, rxlen);
643647
bytes_read = rxlen;
644648
}
645649

@@ -672,7 +676,7 @@ static void sc16is7xx_handle_rx(struct uart_port *port, unsigned int rxlen,
672676
}
673677

674678
for (i = 0; i < bytes_read; ++i) {
675-
ch = s->buf[i];
679+
ch = one->buf[i];
676680
if (uart_handle_sysrq_char(port, ch))
677681
continue;
678682

@@ -690,10 +694,10 @@ static void sc16is7xx_handle_rx(struct uart_port *port, unsigned int rxlen,
690694

691695
static void sc16is7xx_handle_tx(struct uart_port *port)
692696
{
693-
struct sc16is7xx_port *s = dev_get_drvdata(port->dev);
694697
struct tty_port *tport = &port->state->port;
695698
unsigned long flags;
696699
unsigned int txlen;
700+
unsigned char *tail;
697701

698702
if (unlikely(port->x_char)) {
699703
sc16is7xx_port_write(port, SC16IS7XX_THR_REG, port->x_char);
@@ -718,8 +722,9 @@ static void sc16is7xx_handle_tx(struct uart_port *port)
718722
txlen = 0;
719723
}
720724

721-
txlen = uart_fifo_out(port, s->buf, txlen);
722-
sc16is7xx_fifo_write(port, s->buf, txlen);
725+
txlen = kfifo_out_linear_ptr(&tport->xmit_fifo, &tail, txlen);
726+
sc16is7xx_fifo_write(port, tail, txlen);
727+
uart_xmit_advance(port, txlen);
723728

724729
uart_port_lock_irqsave(port, &flags);
725730
if (kfifo_len(&tport->xmit_fifo) < WAKEUP_CHARS)

drivers/tty/serial/serial_core.c

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -881,6 +881,14 @@ static int uart_set_info(struct tty_struct *tty, struct tty_port *port,
881881
new_flags = (__force upf_t)new_info->flags;
882882
old_custom_divisor = uport->custom_divisor;
883883

884+
if (!(uport->flags & UPF_FIXED_PORT)) {
885+
unsigned int uartclk = new_info->baud_base * 16;
886+
/* check needs to be done here before other settings made */
887+
if (uartclk == 0) {
888+
retval = -EINVAL;
889+
goto exit;
890+
}
891+
}
884892
if (!capable(CAP_SYS_ADMIN)) {
885893
retval = -EPERM;
886894
if (change_irq || change_port ||

drivers/tty/vt/conmakehash.c

Lines changed: 7 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@
1111
* Copyright (C) 1995-1997 H. Peter Anvin
1212
*/
1313

14+
#include <libgen.h>
15+
#include <linux/limits.h>
1416
#include <stdio.h>
1517
#include <stdlib.h>
1618
#include <sysexits.h>
@@ -76,8 +78,8 @@ static void addpair(int fp, int un)
7678
int main(int argc, char *argv[])
7779
{
7880
FILE *ctbl;
79-
const char *tblname, *rel_tblname;
80-
const char *abs_srctree;
81+
const char *tblname;
82+
char base_tblname[PATH_MAX];
8183
char buffer[65536];
8284
int fontlen;
8385
int i, nuni, nent;
@@ -102,16 +104,6 @@ int main(int argc, char *argv[])
102104
}
103105
}
104106

105-
abs_srctree = getenv("abs_srctree");
106-
if (abs_srctree && !strncmp(abs_srctree, tblname, strlen(abs_srctree)))
107-
{
108-
rel_tblname = tblname + strlen(abs_srctree);
109-
while (*rel_tblname == '/')
110-
++rel_tblname;
111-
}
112-
else
113-
rel_tblname = tblname;
114-
115107
/* For now we assume the default font is always 256 characters. */
116108
fontlen = 256;
117109

@@ -253,6 +245,8 @@ int main(int argc, char *argv[])
253245
for ( i = 0 ; i < fontlen ; i++ )
254246
nuni += unicount[i];
255247

248+
strncpy(base_tblname, tblname, PATH_MAX);
249+
base_tblname[PATH_MAX - 1] = 0;
256250
printf("\
257251
/*\n\
258252
* Do not edit this file; it was automatically generated by\n\
@@ -264,7 +258,7 @@ int main(int argc, char *argv[])
264258
#include <linux/types.h>\n\
265259
\n\
266260
u8 dfont_unicount[%d] = \n\
267-
{\n\t", rel_tblname, fontlen);
261+
{\n\t", basename(base_tblname), fontlen);
268262

269263
for ( i = 0 ; i < fontlen ; i++ )
270264
{

0 commit comments

Comments
 (0)