169b9a
From 8d537fb77d744265a23b0eda33da269ed672e549 Mon Sep 17 00:00:00 2001
169b9a
From: Tarun Gupta <tgupta@redhat.com>
169b9a
Date: Wed, 20 Jun 2018 18:54:19 +0200
169b9a
Subject: [PATCH 11/17] console: minimal hotplug suport
169b9a
169b9a
RH-Author: Tarun Gupta <tgupta@redhat.com>
169b9a
Message-id: <1529520865-18127-6-git-send-email-tgupta@redhat.com>
169b9a
Patchwork-id: 80914
169b9a
O-Subject: [RHEL7.6 qemu-kvm PATCH v3 05/11] console: minimal hotplug suport
169b9a
Bugzilla: 1555246
169b9a
RH-Acked-by: Alex Williamson <alex.williamson@redhat.com>
169b9a
RH-Acked-by: Gerd Hoffmann <kraxel@redhat.com>
169b9a
RH-Acked-by: Miroslav Rezanina <mrezanin@redhat.com>
169b9a
169b9a
This patch allows to unbind devices from QemuConsoles, using the new
169b9a
graphic_console_close() function.  The QemuConsole will show a static
169b9a
display then, saying the device was unplugged.  When re-plugging a
169b9a
display later on the QemuConsole will be reused.
169b9a
169b9a
Eventually we will allocate and release QemuConsoles dynamically at some
169b9a
point in the future, that'll need more infrastructure though to notify
169b9a
user interfaces (gtk, sdl, spice, ...) about QemuConsoles coming and
169b9a
going.
169b9a
169b9a
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
169b9a
Signed-off-by: Alex Williamson <alex.williamson@redhat.com>
169b9a
169b9a
(cherry picked from 9588d67e72f853349dbb318503368ad01b12feb6)
169b9a
169b9a
Signed-off-by: Miroslav Rezanina <mrezanin@redhat.com>
169b9a
169b9a
Conflicts:
169b9a
    qemu-kvm does not have ui/trace-events, so adding traces in
169b9a
    trace_events.
169b9a
169b9a
    qemu-kvm does not have graphic_console_set_hwops() function,
169b9a
    so manually setting the ops.
169b9a
---
169b9a
 include/ui/console.h |  3 ++-
169b9a
 trace-events         |  2 ++
169b9a
 ui/console.c         | 75 ++++++++++++++++++++++++++++++++++++++++++++++++----
169b9a
 3 files changed, 74 insertions(+), 6 deletions(-)
169b9a
169b9a
diff --git a/include/ui/console.h b/include/ui/console.h
169b9a
index 7f5fa66..e23f809 100644
169b9a
--- a/include/ui/console.h
169b9a
+++ b/include/ui/console.h
169b9a
@@ -275,13 +275,14 @@ typedef struct GraphicHwOps {
169b9a
 QemuConsole *graphic_console_init(DeviceState *dev,
169b9a
                                   const GraphicHwOps *ops,
169b9a
                                   void *opaque);
169b9a
-
169b9a
+void graphic_console_close(QemuConsole *con);
169b9a
 void graphic_hw_update(QemuConsole *con);
169b9a
 void graphic_hw_invalidate(QemuConsole *con);
169b9a
 void graphic_hw_text_update(QemuConsole *con, console_ch_t *chardata);
169b9a
 
169b9a
 QemuConsole *qemu_console_lookup_by_index(unsigned int index);
169b9a
 QemuConsole *qemu_console_lookup_by_device(DeviceState *dev);
169b9a
+QemuConsole *qemu_console_lookup_unused(void);
169b9a
 bool qemu_console_is_visible(QemuConsole *con);
169b9a
 bool qemu_console_is_graphic(QemuConsole *con);
169b9a
 bool qemu_console_is_fixedsize(QemuConsole *con);
169b9a
diff --git a/trace-events b/trace-events
169b9a
index 8c3ce0c..7b7aad1 100644
169b9a
--- a/trace-events
169b9a
+++ b/trace-events
169b9a
@@ -994,6 +994,8 @@ dma_map_wait(void *dbs) "dbs=%p"
169b9a
 
169b9a
 # ui/console.c
169b9a
 console_gfx_new(void) ""
169b9a
+console_gfx_reuse(int index) "%d"
169b9a
+console_gfx_close(int index) "%d"
169b9a
 console_txt_new(int w, int h) "%dx%d"
169b9a
 console_select(int nr) "%d"
169b9a
 console_refresh(int interval) "interval %d ms"
169b9a
diff --git a/ui/console.c b/ui/console.c
169b9a
index c14a0bc..cc319a9 100644
169b9a
--- a/ui/console.c
169b9a
+++ b/ui/console.c
169b9a
@@ -1246,11 +1246,16 @@ static QemuConsole *new_console(DisplayState *ds, console_type_t console_type)
169b9a
     }
169b9a
     s->ds = ds;
169b9a
     s->console_type = console_type;
169b9a
-    if (console_type != GRAPHIC_CONSOLE) {
169b9a
+    if (console_type != GRAPHIC_CONSOLE || qdev_hotplug) {
169b9a
         s->index = nb_consoles;
169b9a
         consoles[nb_consoles++] = s;
169b9a
     } else {
169b9a
-        /* HACK: Put graphical consoles before text consoles.  */
169b9a
+        /*
169b9a
+         * HACK: Put graphical consoles before text consoles.
169b9a
+         *
169b9a
+         * Only do that for coldplugged devices.  After initial device
169b9a
+         * initialization we will not renumber the consoles any more.
169b9a
+         */
169b9a
         for (i = nb_consoles; i > 0; i--) {
169b9a
             if (consoles[i - 1]->console_type == GRAPHIC_CONSOLE)
169b9a
                 break;
169b9a
@@ -1610,21 +1615,59 @@ QemuConsole *graphic_console_init(DeviceState *dev,
169b9a
     int height = 480;
169b9a
     QemuConsole *s;
169b9a
     DisplayState *ds;
169b9a
+    DisplaySurface *surface;
169b9a
 
169b9a
     ds = get_alloc_displaystate();
169b9a
-    trace_console_gfx_new();
169b9a
-    s = new_console(ds, GRAPHIC_CONSOLE);
169b9a
+    s = qemu_console_lookup_unused();
169b9a
+    if (s) {
169b9a
+        trace_console_gfx_reuse(s->index);
169b9a
+        if (s->surface) {
169b9a
+            width = surface_width(s->surface);
169b9a
+            height = surface_height(s->surface);
169b9a
+        }
169b9a
+    } else {
169b9a
+        trace_console_gfx_new();
169b9a
+        s = new_console(ds, GRAPHIC_CONSOLE);
169b9a
+    }
169b9a
+
169b9a
     s->hw_ops = hw_ops;
169b9a
     s->hw = opaque;
169b9a
+
169b9a
     if (dev) {
169b9a
         object_property_set_link(OBJECT(s), OBJECT(dev),
169b9a
                                  "device", &local_err);
169b9a
     }
169b9a
 
169b9a
-    s->surface = qemu_create_message_surface(width, height, noinit);
169b9a
+    surface = qemu_create_message_surface(width, height, noinit);
169b9a
+    dpy_gfx_replace_surface(s, surface);
169b9a
     return s;
169b9a
 }
169b9a
 
169b9a
+static const GraphicHwOps unused_ops = {
169b9a
+    /* no callbacks */
169b9a
+};
169b9a
+
169b9a
+void graphic_console_close(QemuConsole *con)
169b9a
+{
169b9a
+    DisplaySurface *surface;
169b9a
+    int width = 640;
169b9a
+    int height = 480;
169b9a
+
169b9a
+    if (con->surface) {
169b9a
+        width = surface_width(con->surface);
169b9a
+        height = surface_height(con->surface);
169b9a
+    }
169b9a
+
169b9a
+    trace_console_gfx_close(con->index);
169b9a
+    object_property_set_link(OBJECT(con), NULL, "device", &error_abort);
169b9a
+
169b9a
+    con->hw_ops = &unused_ops;
169b9a
+    con->hw = NULL;
169b9a
+
169b9a
+    surface = qemu_create_displaysurface(width, height);
169b9a
+    dpy_gfx_replace_surface(con, surface);
169b9a
+}
169b9a
+
169b9a
 QemuConsole *qemu_console_lookup_by_index(unsigned int index)
169b9a
 {
169b9a
     if (index >= MAX_CONSOLES) {
169b9a
@@ -1652,6 +1695,28 @@ QemuConsole *qemu_console_lookup_by_device(DeviceState *dev)
169b9a
     return NULL;
169b9a
 }
169b9a
 
169b9a
+QemuConsole *qemu_console_lookup_unused(void)
169b9a
+{
169b9a
+    Object *obj;
169b9a
+    int i;
169b9a
+
169b9a
+    for (i = 0; i < nb_consoles; i++) {
169b9a
+        if (!consoles[i]) {
169b9a
+            continue;
169b9a
+        }
169b9a
+        if (consoles[i]->hw_ops != &unused_ops) {
169b9a
+            continue;
169b9a
+        }
169b9a
+        obj = object_property_get_link(OBJECT(consoles[i]),
169b9a
+                                       "device", &error_abort);
169b9a
+        if (obj != NULL) {
169b9a
+            continue;
169b9a
+        }
169b9a
+        return consoles[i];
169b9a
+    }
169b9a
+    return NULL;
169b9a
+}
169b9a
+
169b9a
 bool qemu_console_is_visible(QemuConsole *con)
169b9a
 {
169b9a
     return (con == active_console) || (con->dcls > 0);
169b9a
-- 
169b9a
1.8.3.1
169b9a