|
|
b28c64 |
From ac39e63d788b8bcb748f08347312b0fccde7ce0e Mon Sep 17 00:00:00 2001
|
|
|
b28c64 |
From: Fam Zheng <famz@redhat.com>
|
|
|
b28c64 |
Date: Fri, 19 May 2017 00:35:23 +0200
|
|
|
b28c64 |
Subject: [PATCH 18/18] serial: remove watch on reset
|
|
|
b28c64 |
|
|
|
b28c64 |
RH-Author: Fam Zheng <famz@redhat.com>
|
|
|
b28c64 |
Message-id: <20170519003523.21163-19-famz@redhat.com>
|
|
|
b28c64 |
Patchwork-id: 75373
|
|
|
b28c64 |
O-Subject: [RHEL-7.3.z qemu-kvm PATCH 18/18] serial: remove watch on reset
|
|
|
b28c64 |
Bugzilla: 1452332
|
|
|
b28c64 |
RH-Acked-by: Paolo Bonzini <pbonzini@redhat.com>
|
|
|
b28c64 |
RH-Acked-by: Laurent Vivier <lvivier@redhat.com>
|
|
|
b28c64 |
RH-Acked-by: Eduardo Habkost <ehabkost@redhat.com>
|
|
|
b28c64 |
|
|
|
b28c64 |
From: Paolo Bonzini <pbonzini@redhat.com>
|
|
|
b28c64 |
|
|
|
b28c64 |
Otherwise, this can cause serial_xmit to be entered with LSR.TEMT=0,
|
|
|
b28c64 |
which is invalid and causes an assertion failure.
|
|
|
b28c64 |
|
|
|
b28c64 |
Reported-by: Bret Ketchum <bcketchum@gmail.com>
|
|
|
b28c64 |
Tested-by: Bret Ketchum <bcketchum@gmail.com>
|
|
|
b28c64 |
Reviewed-by: Dr. David Alan Gilbert <dgilbert@redhat.com>
|
|
|
b28c64 |
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
|
|
|
b28c64 |
(cherry picked from commit a1df76da57aa8772a75e7c49f8e3829d07b4c46c)
|
|
|
b28c64 |
Signed-off-by: Fam Zheng <famz@redhat.com>
|
|
|
b28c64 |
Signed-off-by: Miroslav Rezanina <mrezanin@redhat.com>
|
|
|
b28c64 |
---
|
|
|
b28c64 |
hw/char/serial.c | 16 ++++++++++++----
|
|
|
b28c64 |
include/hw/char/serial.h | 1 +
|
|
|
b28c64 |
2 files changed, 13 insertions(+), 4 deletions(-)
|
|
|
b28c64 |
|
|
|
b28c64 |
diff --git a/hw/char/serial.c b/hw/char/serial.c
|
|
|
b28c64 |
index 69fefb2..39de1ca 100644
|
|
|
b28c64 |
--- a/hw/char/serial.c
|
|
|
b28c64 |
+++ b/hw/char/serial.c
|
|
|
b28c64 |
@@ -224,6 +224,7 @@ static gboolean serial_watch_cb(GIOChannel *chan, GIOCondition cond,
|
|
|
b28c64 |
void *opaque)
|
|
|
b28c64 |
{
|
|
|
b28c64 |
SerialState *s = opaque;
|
|
|
b28c64 |
+ s->watch_tag = 0;
|
|
|
b28c64 |
serial_xmit(s);
|
|
|
b28c64 |
return FALSE;
|
|
|
b28c64 |
}
|
|
|
b28c64 |
@@ -254,10 +255,12 @@ static void serial_xmit(SerialState *s)
|
|
|
b28c64 |
if (s->mcr & UART_MCR_LOOP) {
|
|
|
b28c64 |
/* in loopback mode, say that we just received a char */
|
|
|
b28c64 |
serial_receive1(s, &s->tsr, 1);
|
|
|
b28c64 |
- } else if (qemu_chr_fe_write(s->chr, &s->tsr, 1) != 1) {
|
|
|
b28c64 |
- if (s->tsr_retry < MAX_XMIT_RETRY &&
|
|
|
b28c64 |
- qemu_chr_fe_add_watch(s->chr, G_IO_OUT|G_IO_HUP,
|
|
|
b28c64 |
- serial_watch_cb, s) > 0) {
|
|
|
b28c64 |
+ } else if (qemu_chr_fe_write(s->chr, &s->tsr, 1) != 1 &&
|
|
|
b28c64 |
+ s->tsr_retry < MAX_XMIT_RETRY) {
|
|
|
b28c64 |
+ assert(s->watch_tag == 0);
|
|
|
b28c64 |
+ s->watch_tag = qemu_chr_fe_add_watch(s->chr, G_IO_OUT|G_IO_HUP,
|
|
|
b28c64 |
+ serial_watch_cb, s);
|
|
|
b28c64 |
+ if (s->watch_tag > 0) {
|
|
|
b28c64 |
s->tsr_retry++;
|
|
|
b28c64 |
return;
|
|
|
b28c64 |
}
|
|
|
b28c64 |
@@ -656,6 +659,11 @@ static void serial_reset(void *opaque)
|
|
|
b28c64 |
{
|
|
|
b28c64 |
SerialState *s = opaque;
|
|
|
b28c64 |
|
|
|
b28c64 |
+ if (s->watch_tag > 0) {
|
|
|
b28c64 |
+ g_source_remove(s->watch_tag);
|
|
|
b28c64 |
+ s->watch_tag = 0;
|
|
|
b28c64 |
+ }
|
|
|
b28c64 |
+
|
|
|
b28c64 |
s->rbr = 0;
|
|
|
b28c64 |
s->ier = 0;
|
|
|
b28c64 |
s->iir = UART_IIR_NO_INT;
|
|
|
b28c64 |
diff --git a/include/hw/char/serial.h b/include/hw/char/serial.h
|
|
|
b28c64 |
index 2661f8c..19c7763 100644
|
|
|
b28c64 |
--- a/include/hw/char/serial.h
|
|
|
b28c64 |
+++ b/include/hw/char/serial.h
|
|
|
b28c64 |
@@ -56,6 +56,7 @@ struct SerialState {
|
|
|
b28c64 |
int it_shift;
|
|
|
b28c64 |
int baudbase;
|
|
|
b28c64 |
uint32_t tsr_retry;
|
|
|
b28c64 |
+ guint watch_tag;
|
|
|
b28c64 |
uint32_t wakeup;
|
|
|
b28c64 |
|
|
|
b28c64 |
/* Time when the last byte was successfully sent out of the tsr */
|
|
|
b28c64 |
--
|
|
|
b28c64 |
1.8.3.1
|
|
|
b28c64 |
|