mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2025-01-12 08:09:56 +00:00
TTY/Serial fixes for 3.13-rc5
Here are a few fixes for 3.13-rc5 that resolve a number of reported tty and serial driver issues. Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> -----BEGIN PGP SIGNATURE----- Version: GnuPG v2.0.22 (GNU/Linux) iEYEABECAAYFAlKx3gwACgkQMUfUDdst+ymW2QCfY6G4f7J3ZBMKJAiceQtkV28Y mp4AoM6u81l+y+yT1VAKeK00jTJ/EvjJ =Ut64 -----END PGP SIGNATURE----- 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()
This commit is contained in:
commit
e523365820
@ -93,6 +93,7 @@ struct n_tty_data {
|
||||
size_t canon_head;
|
||||
size_t echo_head;
|
||||
size_t echo_commit;
|
||||
size_t echo_mark;
|
||||
DECLARE_BITMAP(char_map, 256);
|
||||
|
||||
/* private to n_tty_receive_overrun (single-threaded) */
|
||||
@ -336,6 +337,7 @@ static void reset_buffer_flags(struct n_tty_data *ldata)
|
||||
{
|
||||
ldata->read_head = ldata->canon_head = ldata->read_tail = 0;
|
||||
ldata->echo_head = ldata->echo_tail = ldata->echo_commit = 0;
|
||||
ldata->echo_mark = 0;
|
||||
ldata->line_start = 0;
|
||||
|
||||
ldata->erasing = 0;
|
||||
@ -787,6 +789,7 @@ static void commit_echoes(struct tty_struct *tty)
|
||||
size_t head;
|
||||
|
||||
head = ldata->echo_head;
|
||||
ldata->echo_mark = head;
|
||||
old = ldata->echo_commit - ldata->echo_tail;
|
||||
|
||||
/* Process committed echoes if the accumulated # of bytes
|
||||
@ -811,10 +814,11 @@ static void process_echoes(struct tty_struct *tty)
|
||||
size_t echoed;
|
||||
|
||||
if ((!L_ECHO(tty) && !L_ECHONL(tty)) ||
|
||||
ldata->echo_commit == ldata->echo_tail)
|
||||
ldata->echo_mark == ldata->echo_tail)
|
||||
return;
|
||||
|
||||
mutex_lock(&ldata->output_lock);
|
||||
ldata->echo_commit = ldata->echo_mark;
|
||||
echoed = __process_echoes(tty);
|
||||
mutex_unlock(&ldata->output_lock);
|
||||
|
||||
@ -822,6 +826,7 @@ static void process_echoes(struct tty_struct *tty)
|
||||
tty->ops->flush_chars(tty);
|
||||
}
|
||||
|
||||
/* NB: echo_mark and echo_head should be equivalent here */
|
||||
static void flush_echoes(struct tty_struct *tty)
|
||||
{
|
||||
struct n_tty_data *ldata = tty->disc_data;
|
||||
|
@ -96,7 +96,8 @@ static void dw8250_serial_out(struct uart_port *p, int offset, int value)
|
||||
if (offset == UART_LCR) {
|
||||
int tries = 1000;
|
||||
while (tries--) {
|
||||
if (value == p->serial_in(p, UART_LCR))
|
||||
unsigned int lcr = p->serial_in(p, UART_LCR);
|
||||
if ((value & ~UART_LCR_SPAR) == (lcr & ~UART_LCR_SPAR))
|
||||
return;
|
||||
dw8250_force_idle(p);
|
||||
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)
|
||||
if (offset == UART_LCR) {
|
||||
int tries = 1000;
|
||||
while (tries--) {
|
||||
if (value == p->serial_in(p, UART_LCR))
|
||||
unsigned int lcr = p->serial_in(p, UART_LCR);
|
||||
if ((value & ~UART_LCR_SPAR) == (lcr & ~UART_LCR_SPAR))
|
||||
return;
|
||||
dw8250_force_idle(p);
|
||||
writel(value, p->membase + (UART_LCR << p->regshift));
|
||||
@ -455,6 +457,8 @@ MODULE_DEVICE_TABLE(of, dw8250_of_match);
|
||||
static const struct acpi_device_id dw8250_acpi_match[] = {
|
||||
{ "INT33C4", 0 },
|
||||
{ "INT33C5", 0 },
|
||||
{ "INT3434", 0 },
|
||||
{ "INT3435", 0 },
|
||||
{ "80860F0A", 0 },
|
||||
{ },
|
||||
};
|
||||
|
@ -240,6 +240,7 @@ static irqreturn_t xuartps_isr(int irq, void *dev_id)
|
||||
continue;
|
||||
}
|
||||
|
||||
#ifdef SUPPORT_SYSRQ
|
||||
/*
|
||||
* uart_handle_sysrq_char() doesn't work if
|
||||
* spinlocked, for some reason
|
||||
@ -253,6 +254,7 @@ static irqreturn_t xuartps_isr(int irq, void *dev_id)
|
||||
}
|
||||
spin_lock(&port->lock);
|
||||
}
|
||||
#endif
|
||||
|
||||
port->icount.rx++;
|
||||
|
||||
|
@ -86,11 +86,21 @@ static inline long ldsem_atomic_update(long delta, struct ld_semaphore *sem)
|
||||
return atomic_long_add_return(delta, (atomic_long_t *)&sem->count);
|
||||
}
|
||||
|
||||
/*
|
||||
* ldsem_cmpxchg() updates @*old with the last-known sem->count value.
|
||||
* Returns 1 if count was successfully changed; @*old will have @new value.
|
||||
* Returns 0 if count was not changed; @*old will have most recent sem->count
|
||||
*/
|
||||
static inline int ldsem_cmpxchg(long *old, long new, struct ld_semaphore *sem)
|
||||
{
|
||||
long tmp = *old;
|
||||
*old = atomic_long_cmpxchg(&sem->count, *old, new);
|
||||
return *old == tmp;
|
||||
long tmp = atomic_long_cmpxchg(&sem->count, *old, new);
|
||||
if (tmp == *old) {
|
||||
*old = new;
|
||||
return 1;
|
||||
} else {
|
||||
*old = tmp;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
|
Loading…
x
Reference in New Issue
Block a user