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