Skip to content

Commit e523365

Browse files
committed
Merge tag 'tty-3.13-rc5' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty
Pull tty/serial fixes from Greg KH: "Here are a few fixes for 3.13-rc5 that resolve a number of reported tty and serial driver issues" * tag 'tty-3.13-rc5' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty: tty: xuartps: Properly guard sysrq specific code n_tty: Fix apparent order of echoed output serial: 8250_dw: add new ACPI IDs serial: 8250_dw: Fix LCR workaround regression tty: Fix hang at ldsem_down_read()
2 parents 1aba038 + c2db11e commit e523365

File tree

4 files changed

+27
-6
lines changed

4 files changed

+27
-6
lines changed

drivers/tty/n_tty.c

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,7 @@ struct n_tty_data {
9393
size_t canon_head;
9494
size_t echo_head;
9595
size_t echo_commit;
96+
size_t echo_mark;
9697
DECLARE_BITMAP(char_map, 256);
9798

9899
/* private to n_tty_receive_overrun (single-threaded) */
@@ -336,6 +337,7 @@ static void reset_buffer_flags(struct n_tty_data *ldata)
336337
{
337338
ldata->read_head = ldata->canon_head = ldata->read_tail = 0;
338339
ldata->echo_head = ldata->echo_tail = ldata->echo_commit = 0;
340+
ldata->echo_mark = 0;
339341
ldata->line_start = 0;
340342

341343
ldata->erasing = 0;
@@ -787,6 +789,7 @@ static void commit_echoes(struct tty_struct *tty)
787789
size_t head;
788790

789791
head = ldata->echo_head;
792+
ldata->echo_mark = head;
790793
old = ldata->echo_commit - ldata->echo_tail;
791794

792795
/* Process committed echoes if the accumulated # of bytes
@@ -811,17 +814,19 @@ static void process_echoes(struct tty_struct *tty)
811814
size_t echoed;
812815

813816
if ((!L_ECHO(tty) && !L_ECHONL(tty)) ||
814-
ldata->echo_commit == ldata->echo_tail)
817+
ldata->echo_mark == ldata->echo_tail)
815818
return;
816819

817820
mutex_lock(&ldata->output_lock);
821+
ldata->echo_commit = ldata->echo_mark;
818822
echoed = __process_echoes(tty);
819823
mutex_unlock(&ldata->output_lock);
820824

821825
if (echoed && tty->ops->flush_chars)
822826
tty->ops->flush_chars(tty);
823827
}
824828

829+
/* NB: echo_mark and echo_head should be equivalent here */
825830
static void flush_echoes(struct tty_struct *tty)
826831
{
827832
struct n_tty_data *ldata = tty->disc_data;

drivers/tty/serial/8250/8250_dw.c

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,8 @@ static void dw8250_serial_out(struct uart_port *p, int offset, int value)
9696
if (offset == UART_LCR) {
9797
int tries = 1000;
9898
while (tries--) {
99-
if (value == p->serial_in(p, UART_LCR))
99+
unsigned int lcr = p->serial_in(p, UART_LCR);
100+
if ((value & ~UART_LCR_SPAR) == (lcr & ~UART_LCR_SPAR))
100101
return;
101102
dw8250_force_idle(p);
102103
writeb(value, p->membase + (UART_LCR << p->regshift));
@@ -132,7 +133,8 @@ static void dw8250_serial_out32(struct uart_port *p, int offset, int value)
132133
if (offset == UART_LCR) {
133134
int tries = 1000;
134135
while (tries--) {
135-
if (value == p->serial_in(p, UART_LCR))
136+
unsigned int lcr = p->serial_in(p, UART_LCR);
137+
if ((value & ~UART_LCR_SPAR) == (lcr & ~UART_LCR_SPAR))
136138
return;
137139
dw8250_force_idle(p);
138140
writel(value, p->membase + (UART_LCR << p->regshift));
@@ -455,6 +457,8 @@ MODULE_DEVICE_TABLE(of, dw8250_of_match);
455457
static const struct acpi_device_id dw8250_acpi_match[] = {
456458
{ "INT33C4", 0 },
457459
{ "INT33C5", 0 },
460+
{ "INT3434", 0 },
461+
{ "INT3435", 0 },
458462
{ "80860F0A", 0 },
459463
{ },
460464
};

drivers/tty/serial/xilinx_uartps.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -240,6 +240,7 @@ static irqreturn_t xuartps_isr(int irq, void *dev_id)
240240
continue;
241241
}
242242

243+
#ifdef SUPPORT_SYSRQ
243244
/*
244245
* uart_handle_sysrq_char() doesn't work if
245246
* spinlocked, for some reason
@@ -253,6 +254,7 @@ static irqreturn_t xuartps_isr(int irq, void *dev_id)
253254
}
254255
spin_lock(&port->lock);
255256
}
257+
#endif
256258

257259
port->icount.rx++;
258260

drivers/tty/tty_ldsem.c

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -86,11 +86,21 @@ static inline long ldsem_atomic_update(long delta, struct ld_semaphore *sem)
8686
return atomic_long_add_return(delta, (atomic_long_t *)&sem->count);
8787
}
8888

89+
/*
90+
* ldsem_cmpxchg() updates @*old with the last-known sem->count value.
91+
* Returns 1 if count was successfully changed; @*old will have @new value.
92+
* Returns 0 if count was not changed; @*old will have most recent sem->count
93+
*/
8994
static inline int ldsem_cmpxchg(long *old, long new, struct ld_semaphore *sem)
9095
{
91-
long tmp = *old;
92-
*old = atomic_long_cmpxchg(&sem->count, *old, new);
93-
return *old == tmp;
96+
long tmp = atomic_long_cmpxchg(&sem->count, *old, new);
97+
if (tmp == *old) {
98+
*old = new;
99+
return 1;
100+
} else {
101+
*old = tmp;
102+
return 0;
103+
}
94104
}
95105

96106
/*

0 commit comments

Comments
 (0)