Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F145818114
D55012.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
8 KB
Referenced Files
None
Subscribers
None
D55012.diff
View Options
diff --git a/sys/dev/virtio/gpu/virtio_gpu.c b/sys/dev/virtio/gpu/virtio_gpu.c
--- a/sys/dev/virtio/gpu/virtio_gpu.c
+++ b/sys/dev/virtio/gpu/virtio_gpu.c
@@ -35,9 +35,13 @@
#include <sys/callout.h>
#include <sys/fbio.h>
#include <sys/kernel.h>
+#include <sys/lock.h>
#include <sys/malloc.h>
#include <sys/module.h>
+#include <sys/mutex.h>
#include <sys/sglist.h>
+#include <sys/sysctl.h>
+#include <sys/taskqueue.h>
#include <machine/atomic.h>
#include <machine/bus.h>
@@ -61,6 +65,12 @@
/* The guest can allocate resource IDs, we only need one */
#define VTGPU_RESOURCE_ID 1
+static int vtgpu_width_override = 0;
+static int vtgpu_height_override = 0;
+
+TUNABLE_INT("hw.virtio_gpu.width", &vtgpu_width_override);
+TUNABLE_INT("hw.virtio_gpu.height", &vtgpu_height_override);
+
struct vtgpu_softc {
/* Must be first so we can cast from info -> softc */
struct fb_info vtgpu_fb_info;
@@ -70,9 +80,17 @@
uint64_t vtgpu_features;
struct virtqueue *vtgpu_ctrl_vq;
+ struct mtx vtgpu_mtx;
uint64_t vtgpu_next_fence;
+ struct callout vtgpu_flush_callout;
+ struct task vtgpu_flush_task;
+ bool vtgpu_fb_registered;
+ bool vtgpu_detaching;
+ int vtgpu_refresh_rate; /* FPS for periodic flush */
+ struct sysctl_ctx_list vtgpu_sysctl_ctx;
+
bool vtgpu_have_fb_info;
};
@@ -96,6 +114,11 @@
uint32_t, uint32_t, uint32_t);
static int vtgpu_resource_flush(struct vtgpu_softc *, uint32_t, uint32_t,
uint32_t, uint32_t);
+static void vtgpu_flush_callout_cb(void *);
+static void vtgpu_flush_task_cb(void *, int);
+
+#define VTGPU_DEFAULT_REFRESH_RATE 30
+#define VTGPU_FLUSH_INTERVAL(sc) (hz / (sc)->vtgpu_refresh_rate)
static vd_blank_t vtgpu_fb_blank;
static vd_bitblt_text_t vtgpu_fb_bitblt_text;
@@ -118,7 +141,7 @@
.vd_postswitch = vt_fb_postswitch,
.vd_priority = VD_PRIORITY_GENERIC+10,
.vd_fb_ioctl = vt_fb_ioctl,
- .vd_fb_mmap = NULL, /* No mmap as we need to signal the host */
+ .vd_fb_mmap = vt_fb_mmap, /* mmap with periodic flushes to host */
.vd_suspend = vt_fb_suspend,
.vd_resume = vt_fb_resume,
};
@@ -293,6 +316,13 @@
sc->vtgpu_have_fb_info = false;
sc->vtgpu_dev = dev;
sc->vtgpu_next_fence = 1;
+ sc->vtgpu_detaching = false;
+ sc->vtgpu_fb_registered = false;
+
+ TASK_INIT(&sc->vtgpu_flush_task, 0, vtgpu_flush_task_cb, sc);
+ callout_init(&sc->vtgpu_flush_callout, 1);
+ mtx_init(&sc->vtgpu_mtx, "vtgpu", NULL, MTX_DEF);
+
virtio_set_feature_desc(dev, vtgpu_feature_desc);
error = vtgpu_setup_features(sc);
@@ -317,6 +347,14 @@
goto fail;
}
+ /* Setup sysctl for refresh rate control */
+ sc->vtgpu_refresh_rate = VTGPU_DEFAULT_REFRESH_RATE;
+ sysctl_ctx_init(&sc->vtgpu_sysctl_ctx);
+ SYSCTL_ADD_INT(&sc->vtgpu_sysctl_ctx,
+ SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), OID_AUTO,
+ "refresh_rate", CTLFLAG_RW, &sc->vtgpu_refresh_rate, 0,
+ "Framebuffer flush rate in FPS (1-120)");
+
/*
* TODO: This doesn't need to be contigmalloc as we
* can use scatter-gather lists.
@@ -325,6 +363,13 @@
sc->vtgpu_fb_info.fb_size, M_DEVBUF, M_WAITOK|M_ZERO, 0, ~0, 4, 0);
sc->vtgpu_fb_info.fb_pbase = pmap_kextract(sc->vtgpu_fb_info.fb_vbase);
+ /*
+ * Since this is a shadow buffer in regular RAM (not actual GPU VRAM),
+ * use VM_MEMATTR_DEFAULT
+ */
+ sc->vtgpu_fb_info.fb_flags |= FB_FLAG_MEMATTR;
+ sc->vtgpu_fb_info.fb_memattr = VM_MEMATTR_DEFAULT;
+
/* Create the 2d resource */
error = vtgpu_create_2d(sc);
if (error != 0) {
@@ -347,12 +392,34 @@
vt_allocate(&vtgpu_fb_driver, &sc->vtgpu_fb_info);
sc->vtgpu_have_fb_info = true;
+ /* Register framebuffer device so userland can access it via /dev/fb0 */
+ error = fbd_register(&sc->vtgpu_fb_info);
+ if (error != 0 && error != EEXIST) {
+ device_printf(dev, "warning: cannot register /dev/fb device"
+ " (error %d)\n", error);
+ /* Non-fatal - continue without /dev/fbN, console still works */
+ } else {
+ device_printf(dev, "/dev/fb0 created\n");
+ sc->vtgpu_fb_registered = true;
+ }
+
error = vtgpu_transfer_to_host_2d(sc, 0, 0, sc->vtgpu_fb_info.fb_width,
sc->vtgpu_fb_info.fb_height);
- if (error != 0)
+ if (error != 0) {
goto fail;
+ }
+
error = vtgpu_resource_flush(sc, 0, 0, sc->vtgpu_fb_info.fb_width,
sc->vtgpu_fb_info.fb_height);
+ if (error != 0) {
+ goto fail;
+ }
+
+ /* Start the periodic flush mechanism */
+ if (sc->vtgpu_fb_registered== true) {
+ callout_reset(&sc->vtgpu_flush_callout, VTGPU_FLUSH_INTERVAL(sc),
+ vtgpu_flush_callout_cb, sc);
+ }
fail:
if (error != 0)
@@ -367,19 +434,66 @@
struct vtgpu_softc *sc;
sc = device_get_softc(dev);
- if (sc->vtgpu_have_fb_info)
+
+ /* Stop the periodic flush callout and task */
+ sc->vtgpu_detaching = true;
+ callout_drain(&sc->vtgpu_flush_callout);
+ taskqueue_drain(taskqueue_thread, &sc->vtgpu_flush_task);
+
+ /* Unregister the framebuffer device */
+ if (sc->vtgpu_fb_registered) {
+ fbd_unregister(&sc->vtgpu_fb_info);
+ sc->vtgpu_fb_registered = false;
+ }
+
+ if (sc->vtgpu_have_fb_info) {
vt_deallocate(&vtgpu_fb_driver, &sc->vtgpu_fb_info);
+ }
if (sc->vtgpu_fb_info.fb_vbase != 0) {
MPASS(sc->vtgpu_fb_info.fb_size != 0);
free((void *)sc->vtgpu_fb_info.fb_vbase,
M_DEVBUF);
}
+ mtx_destroy(&sc->vtgpu_mtx);
+
+ sysctl_ctx_free(&sc->vtgpu_sysctl_ctx);
+
/* TODO: Tell the host we are detaching */
return (0);
}
+static void
+vtgpu_flush_callout_cb(void *arg)
+{
+ struct vtgpu_softc *sc = arg;
+
+ if (!sc->vtgpu_detaching)
+ taskqueue_enqueue(taskqueue_thread, &sc->vtgpu_flush_task);
+}
+
+static void
+vtgpu_flush_task_cb(void *arg, int pending __unused)
+{
+ struct vtgpu_softc *sc = arg;
+
+ if (sc->vtgpu_detaching)
+ return;
+
+ /* Transfer the entire framebuffer to the host and flush */
+ vtgpu_transfer_to_host_2d(sc, 0, 0, sc->vtgpu_fb_info.fb_width,
+ sc->vtgpu_fb_info.fb_height);
+ vtgpu_resource_flush(sc, 0, 0, sc->vtgpu_fb_info.fb_width,
+ sc->vtgpu_fb_info.fb_height);
+
+ /* Reschedule the callout for the next flush */
+ if (!sc->vtgpu_detaching)
+ callout_reset(&sc->vtgpu_flush_callout,
+ VTGPU_FLUSH_INTERVAL(sc),
+ vtgpu_flush_callout_cb, sc);
+}
+
static int
vtgpu_negotiate_features(struct vtgpu_softc *sc)
{
@@ -452,12 +566,15 @@
struct sglist_seg segs[2];
int error;
+ mtx_lock(&sc->vtgpu_mtx);
+
sglist_init(&sg, 2, segs);
error = sglist_append(&sg, req, reqlen);
if (error != 0) {
device_printf(sc->vtgpu_dev,
"Unable to append the request to the sglist: %d\n", error);
+ mtx_unlock(&sc->vtgpu_mtx);
return (error);
}
error = sglist_append(&sg, resp, resplen);
@@ -465,17 +582,21 @@
device_printf(sc->vtgpu_dev,
"Unable to append the response buffer to the sglist: %d\n",
error);
+ mtx_unlock(&sc->vtgpu_mtx);
return (error);
}
error = virtqueue_enqueue(sc->vtgpu_ctrl_vq, resp, &sg, 1, 1);
if (error != 0) {
device_printf(sc->vtgpu_dev, "Enqueue failed: %d\n", error);
+ mtx_unlock(&sc->vtgpu_mtx);
return (error);
}
virtqueue_notify(sc->vtgpu_ctrl_vq);
virtqueue_poll(sc->vtgpu_ctrl_vq, NULL);
+ mtx_unlock(&sc->vtgpu_mtx);
+
return (0);
}
@@ -508,6 +629,18 @@
le32toh(s.resp.pmodes[i].r.width);
sc->vtgpu_fb_info.fb_height =
le32toh(s.resp.pmodes[i].r.height);
+
+ if (vtgpu_width_override > 0 && vtgpu_height_override > 0) {
+ device_printf(sc->vtgpu_dev,
+ "overriding resolution %dx%d -> %dx%d\n",
+ sc->vtgpu_fb_info.fb_width,
+ sc->vtgpu_fb_info.fb_height,
+ vtgpu_width_override,
+ vtgpu_height_override);
+ sc->vtgpu_fb_info.fb_width = vtgpu_width_override;
+ sc->vtgpu_fb_info.fb_height = vtgpu_height_override;
+ }
+
/* 32 bits per pixel */
sc->vtgpu_fb_info.fb_bpp = 32;
sc->vtgpu_fb_info.fb_depth = 32;
diff --git a/sys/dev/vt/vt_core.c b/sys/dev/vt/vt_core.c
--- a/sys/dev/vt/vt_core.c
+++ b/sys/dev/vt/vt_core.c
@@ -3370,7 +3370,7 @@
* it is bad idea to replace KMS driver with generic VGA one.
*/
if (drv->vd_priority <= main_vd->vd_driver->vd_priority) {
- printf("VT: Driver priority %d too low. Current %d\n ",
+ printf("VT: Driver priority %d too low. Current %d\n",
drv->vd_priority, main_vd->vd_driver->vd_priority);
return (EEXIST);
}
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Wed, Feb 25, 9:27 PM (8 h, 32 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
28995698
Default Alt Text
D55012.diff (8 KB)
Attached To
Mode
D55012: virtio_gpu: add support for xf86-video-scfb
Attached
Detach File
Event Timeline
Log In to Comment