* [PATCH v4 0/9] drm: Add generic fbdev emulation
@ 2018-07-02 13:54 Noralf Trønnes
2018-07-02 13:54 ` [PATCH v4 1/9] drm: Begin an API for in-kernel clients Noralf Trønnes
` (12 more replies)
0 siblings, 13 replies; 24+ messages in thread
From: Noralf Trønnes @ 2018-07-02 13:54 UTC (permalink / raw)
To: dri-devel; +Cc: intel-gfx, laurent.pinchart, david
This patchset adds generic fbdev emulation for drivers that supports GEM
based dumb buffers which support .gem_prime_vmap and gem_prime_mmap. An
API is begun to support in-kernel clients in general.
Change this version:
Fix a bug in an error path that the kbuild test robot caught.
Change previous version:
Rework client removal (again). Drop reference counting, only allow the
driver to remove a client.
Noralf.
Changes since version 3:
- drm/cma-helper: Use the generic fbdev emulation: Fix error path
- Remove setting .lastclose in new tinydrm driver ili9341
Changes since version 2:
- Applied first 3 patches to drm-misc-next
- Drop client reference counting and only allow the driver to release
clients.
Noralf Trønnes (9):
drm: Begin an API for in-kernel clients
drm/fb-helper: Add generic fbdev emulation .fb_probe function
drm/pl111: Set .gem_prime_vmap and .gem_prime_mmap
drm/cma-helper: Use the generic fbdev emulation
drm/client: Add client callbacks
drm/debugfs: Add internal client debugfs file
drm/fb-helper: Finish the generic fbdev emulation
drm/tinydrm: Use drm_fbdev_generic_setup()
drm/cma-helper: Remove drm_fb_cma_fbdev_init_with_funcs()
Documentation/gpu/drm-client.rst | 12 +
Documentation/gpu/index.rst | 1 +
drivers/gpu/drm/Makefile | 2 +-
drivers/gpu/drm/drm_client.c | 405 ++++++++++++++++++++++++++++
drivers/gpu/drm/drm_debugfs.c | 7 +
drivers/gpu/drm/drm_drv.c | 8 +
drivers/gpu/drm/drm_fb_cma_helper.c | 379 +++-----------------------
drivers/gpu/drm/drm_fb_helper.c | 316 +++++++++++++++++++++-
drivers/gpu/drm/drm_file.c | 3 +
drivers/gpu/drm/drm_probe_helper.c | 3 +
drivers/gpu/drm/pl111/pl111_drv.c | 2 +
drivers/gpu/drm/tinydrm/core/tinydrm-core.c | 3 +-
drivers/gpu/drm/tinydrm/ili9225.c | 1 -
drivers/gpu/drm/tinydrm/ili9341.c | 1 -
drivers/gpu/drm/tinydrm/mi0283qt.c | 1 -
drivers/gpu/drm/tinydrm/st7586.c | 1 -
drivers/gpu/drm/tinydrm/st7735r.c | 1 -
include/drm/drm_client.h | 152 +++++++++++
include/drm/drm_device.h | 21 ++
include/drm/drm_fb_cma_helper.h | 6 -
include/drm/drm_fb_helper.h | 38 +++
21 files changed, 1010 insertions(+), 353 deletions(-)
create mode 100644 Documentation/gpu/drm-client.rst
create mode 100644 drivers/gpu/drm/drm_client.c
create mode 100644 include/drm/drm_client.h
--
2.15.1
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel
^ permalink raw reply [flat|nested] 24+ messages in thread
* [PATCH v4 1/9] drm: Begin an API for in-kernel clients
2018-07-02 13:54 [PATCH v4 0/9] drm: Add generic fbdev emulation Noralf Trønnes
@ 2018-07-02 13:54 ` Noralf Trønnes
2018-07-03 7:43 ` Daniel Vetter
2018-07-02 13:54 ` [PATCH v4 2/9] drm/fb-helper: Add generic fbdev emulation .fb_probe function Noralf Trønnes
` (11 subsequent siblings)
12 siblings, 1 reply; 24+ messages in thread
From: Noralf Trønnes @ 2018-07-02 13:54 UTC (permalink / raw)
To: dri-devel; +Cc: intel-gfx, Noralf Trønnes, laurent.pinchart, david
This the beginning of an API for in-kernel clients.
First out is a way to get a framebuffer backed by a dumb buffer.
Only GEM drivers are supported.
The original idea of using an exported dma-buf was dropped because it
also creates an anonomous file descriptor which doesn't work when the
buffer is created from a kernel thread. The easy way out is to use
drm_driver.gem_prime_vmap to get the virtual address, which requires a
GEM object. This excludes the vmwgfx driver which is the only non-GEM
driver apart from the legacy ones. A solution for vmwgfx will have to be
worked out later if it wants to support the client API which it probably
will when we have a bootsplash client.
Signed-off-by: Noralf Trønnes <noralf@tronnes.org>
Reviewed-by: Daniel Vetter <daniel.vetter@ffwll.ch>
---
Documentation/gpu/drm-client.rst | 12 ++
Documentation/gpu/index.rst | 1 +
drivers/gpu/drm/Makefile | 2 +-
drivers/gpu/drm/drm_client.c | 289 +++++++++++++++++++++++++++++++++++++++
drivers/gpu/drm/drm_drv.c | 1 +
include/drm/drm_client.h | 76 ++++++++++
include/drm/drm_device.h | 7 +
7 files changed, 387 insertions(+), 1 deletion(-)
create mode 100644 Documentation/gpu/drm-client.rst
create mode 100644 drivers/gpu/drm/drm_client.c
create mode 100644 include/drm/drm_client.h
diff --git a/Documentation/gpu/drm-client.rst b/Documentation/gpu/drm-client.rst
new file mode 100644
index 000000000000..7e672063e7eb
--- /dev/null
+++ b/Documentation/gpu/drm-client.rst
@@ -0,0 +1,12 @@
+=================
+Kernel clients
+=================
+
+.. kernel-doc:: drivers/gpu/drm/drm_client.c
+ :doc: overview
+
+.. kernel-doc:: include/drm/drm_client.h
+ :internal:
+
+.. kernel-doc:: drivers/gpu/drm/drm_client.c
+ :export:
diff --git a/Documentation/gpu/index.rst b/Documentation/gpu/index.rst
index 00288f34c5a6..1fcf8e851e15 100644
--- a/Documentation/gpu/index.rst
+++ b/Documentation/gpu/index.rst
@@ -10,6 +10,7 @@ Linux GPU Driver Developer's Guide
drm-kms
drm-kms-helpers
drm-uapi
+ drm-client
drivers
vga-switcheroo
vgaarbiter
diff --git a/drivers/gpu/drm/Makefile b/drivers/gpu/drm/Makefile
index 69c13517ea3a..d6657a61d037 100644
--- a/drivers/gpu/drm/Makefile
+++ b/drivers/gpu/drm/Makefile
@@ -18,7 +18,7 @@ drm-y := drm_auth.o drm_bufs.o drm_cache.o \
drm_encoder.o drm_mode_object.o drm_property.o \
drm_plane.o drm_color_mgmt.o drm_print.o \
drm_dumb_buffers.o drm_mode_config.o drm_vblank.o \
- drm_syncobj.o drm_lease.o drm_writeback.o
+ drm_syncobj.o drm_lease.o drm_writeback.o drm_client.o
drm-$(CONFIG_DRM_LIB_RANDOM) += lib/drm_random.o
drm-$(CONFIG_DRM_VM) += drm_vm.o
diff --git a/drivers/gpu/drm/drm_client.c b/drivers/gpu/drm/drm_client.c
new file mode 100644
index 000000000000..9c9b8ac7aea3
--- /dev/null
+++ b/drivers/gpu/drm/drm_client.c
@@ -0,0 +1,289 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright 2018 Noralf Trønnes
+ */
+
+#include <linux/list.h>
+#include <linux/mutex.h>
+#include <linux/seq_file.h>
+#include <linux/slab.h>
+
+#include <drm/drm_client.h>
+#include <drm/drm_debugfs.h>
+#include <drm/drm_device.h>
+#include <drm/drm_drv.h>
+#include <drm/drm_file.h>
+#include <drm/drm_fourcc.h>
+#include <drm/drm_gem.h>
+#include <drm/drm_mode.h>
+#include <drm/drm_print.h>
+#include <drm/drmP.h>
+
+#include "drm_crtc_internal.h"
+#include "drm_internal.h"
+
+/**
+ * DOC: overview
+ *
+ * This library provides support for clients running in the kernel like fbdev and bootsplash.
+ * Currently it's only partially implemented, just enough to support fbdev.
+ *
+ * GEM drivers which provide a GEM based dumb buffer with a virtual address are supported.
+ */
+
+static int drm_client_open(struct drm_client_dev *client)
+{
+ struct drm_device *dev = client->dev;
+ struct drm_file *file;
+
+ file = drm_file_alloc(dev->primary);
+ if (IS_ERR(file))
+ return PTR_ERR(file);
+
+ mutex_lock(&dev->filelist_mutex);
+ list_add(&file->lhead, &dev->filelist_internal);
+ mutex_unlock(&dev->filelist_mutex);
+
+ client->file = file;
+
+ return 0;
+}
+
+static void drm_client_close(struct drm_client_dev *client)
+{
+ struct drm_device *dev = client->dev;
+
+ mutex_lock(&dev->filelist_mutex);
+ list_del(&client->file->lhead);
+ mutex_unlock(&dev->filelist_mutex);
+
+ drm_file_free(client->file);
+}
+EXPORT_SYMBOL(drm_client_close);
+
+/**
+ * drm_client_new - Create a DRM client
+ * @dev: DRM device
+ * @client: DRM client
+ * @name: Client name
+ *
+ * Use drm_client_put() to free the client.
+ *
+ * Returns:
+ * Zero on success or negative error code on failure.
+ */
+int drm_client_new(struct drm_device *dev, struct drm_client_dev *client,
+ const char *name)
+{
+ int ret;
+
+ if (!drm_core_check_feature(dev, DRIVER_MODESET) ||
+ !dev->driver->dumb_create || !dev->driver->gem_prime_vmap)
+ return -ENOTSUPP;
+
+ client->dev = dev;
+ client->name = name;
+
+ ret = drm_client_open(client);
+ if (ret)
+ return ret;
+
+ drm_dev_get(dev);
+
+ return 0;
+}
+EXPORT_SYMBOL(drm_client_new);
+
+/**
+ * drm_client_release - Release DRM client resources
+ * @client: DRM client
+ *
+ * Releases resources by closing the &drm_file that was opened by drm_client_new().
+ * It is called automatically if the &drm_client_funcs.unregister callback is _not_ set.
+ *
+ * This function should only be called from the unregister callback. An exception
+ * is fbdev which cannot free the buffer if userspace has open file descriptors.
+ *
+ * Note:
+ * Clients cannot initiate a release by themselves. This is done to keep the code simple.
+ * The driver has to be unloaded before the client can be unloaded.
+ */
+void drm_client_release(struct drm_client_dev *client)
+{
+ struct drm_device *dev = client->dev;
+
+ DRM_DEV_DEBUG_KMS(dev->dev, "%s\n", client->name);
+
+ drm_client_close(client);
+ drm_dev_put(dev);
+}
+EXPORT_SYMBOL(drm_client_release);
+
+static void drm_client_buffer_delete(struct drm_client_buffer *buffer)
+{
+ struct drm_device *dev = buffer->client->dev;
+
+ if (buffer->vaddr && dev->driver->gem_prime_vunmap)
+ dev->driver->gem_prime_vunmap(buffer->gem, buffer->vaddr);
+
+ if (buffer->gem)
+ drm_gem_object_put_unlocked(buffer->gem);
+
+ drm_mode_destroy_dumb(dev, buffer->handle, buffer->client->file);
+ kfree(buffer);
+}
+
+static struct drm_client_buffer *
+drm_client_buffer_create(struct drm_client_dev *client, u32 width, u32 height, u32 format)
+{
+ struct drm_mode_create_dumb dumb_args = { };
+ struct drm_device *dev = client->dev;
+ struct drm_client_buffer *buffer;
+ struct drm_gem_object *obj;
+ void *vaddr;
+ int ret;
+
+ buffer = kzalloc(sizeof(*buffer), GFP_KERNEL);
+ if (!buffer)
+ return ERR_PTR(-ENOMEM);
+
+ buffer->client = client;
+
+ dumb_args.width = width;
+ dumb_args.height = height;
+ dumb_args.bpp = drm_format_plane_cpp(format, 0) * 8;
+ ret = drm_mode_create_dumb(dev, &dumb_args, client->file);
+ if (ret)
+ goto err_free;
+
+ buffer->handle = dumb_args.handle;
+ buffer->pitch = dumb_args.pitch;
+
+ obj = drm_gem_object_lookup(client->file, dumb_args.handle);
+ if (!obj) {
+ ret = -ENOENT;
+ goto err_delete;
+ }
+
+ buffer->gem = obj;
+
+ /*
+ * FIXME: The dependency on GEM here isn't required, we could
+ * convert the driver handle to a dma-buf instead and use the
+ * backend-agnostic dma-buf vmap support instead. This would
+ * require that the handle2fd prime ioctl is reworked to pull the
+ * fd_install step out of the driver backend hooks, to make that
+ * final step optional for internal users.
+ */
+ vaddr = dev->driver->gem_prime_vmap(obj);
+ if (!vaddr) {
+ ret = -ENOMEM;
+ goto err_delete;
+ }
+
+ buffer->vaddr = vaddr;
+
+ return buffer;
+
+err_delete:
+ drm_client_buffer_delete(buffer);
+err_free:
+ kfree(buffer);
+
+ return ERR_PTR(ret);
+}
+
+static void drm_client_buffer_rmfb(struct drm_client_buffer *buffer)
+{
+ int ret;
+
+ if (!buffer->fb)
+ return;
+
+ ret = drm_mode_rmfb(buffer->client->dev, buffer->fb->base.id, buffer->client->file);
+ if (ret)
+ DRM_DEV_ERROR(buffer->client->dev->dev,
+ "Error removing FB:%u (%d)\n", buffer->fb->base.id, ret);
+
+ buffer->fb = NULL;
+}
+
+static int drm_client_buffer_addfb(struct drm_client_buffer *buffer,
+ u32 width, u32 height, u32 format)
+{
+ struct drm_client_dev *client = buffer->client;
+ struct drm_mode_fb_cmd fb_req = { };
+ const struct drm_format_info *info;
+ int ret;
+
+ info = drm_format_info(format);
+ fb_req.bpp = info->cpp[0] * 8;
+ fb_req.depth = info->depth;
+ fb_req.width = width;
+ fb_req.height = height;
+ fb_req.handle = buffer->handle;
+ fb_req.pitch = buffer->pitch;
+
+ ret = drm_mode_addfb(client->dev, &fb_req, client->file);
+ if (ret)
+ return ret;
+
+ buffer->fb = drm_framebuffer_lookup(client->dev, buffer->client->file, fb_req.fb_id);
+ if (WARN_ON(!buffer->fb))
+ return -ENOENT;
+
+ /* drop the reference we picked up in framebuffer lookup */
+ drm_framebuffer_put(buffer->fb);
+
+ strscpy(buffer->fb->comm, client->name, TASK_COMM_LEN);
+
+ return 0;
+}
+
+/**
+ * drm_client_framebuffer_create - Create a client framebuffer
+ * @client: DRM client
+ * @width: Framebuffer width
+ * @height: Framebuffer height
+ * @format: Buffer format
+ *
+ * This function creates a &drm_client_buffer which consists of a
+ * &drm_framebuffer backed by a dumb buffer.
+ * Call drm_client_framebuffer_delete() to free the buffer.
+ *
+ * Returns:
+ * Pointer to a client buffer or an error pointer on failure.
+ */
+struct drm_client_buffer *
+drm_client_framebuffer_create(struct drm_client_dev *client, u32 width, u32 height, u32 format)
+{
+ struct drm_client_buffer *buffer;
+ int ret;
+
+ buffer = drm_client_buffer_create(client, width, height, format);
+ if (IS_ERR(buffer))
+ return buffer;
+
+ ret = drm_client_buffer_addfb(buffer, width, height, format);
+ if (ret) {
+ drm_client_buffer_delete(buffer);
+ return ERR_PTR(ret);
+ }
+
+ return buffer;
+}
+EXPORT_SYMBOL(drm_client_framebuffer_create);
+
+/**
+ * drm_client_framebuffer_delete - Delete a client framebuffer
+ * @buffer: DRM client buffer (can be NULL)
+ */
+void drm_client_framebuffer_delete(struct drm_client_buffer *buffer)
+{
+ if (!buffer)
+ return;
+
+ drm_client_buffer_rmfb(buffer);
+ drm_client_buffer_delete(buffer);
+}
+EXPORT_SYMBOL(drm_client_framebuffer_delete);
diff --git a/drivers/gpu/drm/drm_drv.c b/drivers/gpu/drm/drm_drv.c
index 7af748ed1c58..e7ff0b03328b 100644
--- a/drivers/gpu/drm/drm_drv.c
+++ b/drivers/gpu/drm/drm_drv.c
@@ -505,6 +505,7 @@ int drm_dev_init(struct drm_device *dev,
dev->driver = driver;
INIT_LIST_HEAD(&dev->filelist);
+ INIT_LIST_HEAD(&dev->filelist_internal);
INIT_LIST_HEAD(&dev->ctxlist);
INIT_LIST_HEAD(&dev->vmalist);
INIT_LIST_HEAD(&dev->maplist);
diff --git a/include/drm/drm_client.h b/include/drm/drm_client.h
new file mode 100644
index 000000000000..e366f95d4414
--- /dev/null
+++ b/include/drm/drm_client.h
@@ -0,0 +1,76 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+
+#ifndef _DRM_CLIENT_H_
+#define _DRM_CLIENT_H_
+
+#include <linux/types.h>
+
+struct drm_device;
+struct drm_file;
+struct drm_framebuffer;
+struct drm_gem_object;
+
+/**
+ * struct drm_client_dev - DRM client instance
+ */
+struct drm_client_dev {
+ /**
+ * @dev: DRM device
+ */
+ struct drm_device *dev;
+
+ /**
+ * @name: Name of the client.
+ */
+ const char *name;
+
+ /**
+ * @file: DRM file
+ */
+ struct drm_file *file;
+};
+
+int drm_client_new(struct drm_device *dev, struct drm_client_dev *client,
+ const char *name);
+void drm_client_release(struct drm_client_dev *client);
+
+/**
+ * struct drm_client_buffer - DRM client buffer
+ */
+struct drm_client_buffer {
+ /**
+ * @client: DRM client
+ */
+ struct drm_client_dev *client;
+
+ /**
+ * @handle: Buffer handle
+ */
+ u32 handle;
+
+ /**
+ * @pitch: Buffer pitch
+ */
+ u32 pitch;
+
+ /**
+ * @gem: GEM object backing this buffer
+ */
+ struct drm_gem_object *gem;
+
+ /**
+ * @vaddr: Virtual address for the buffer
+ */
+ void *vaddr;
+
+ /**
+ * @fb: DRM framebuffer
+ */
+ struct drm_framebuffer *fb;
+};
+
+struct drm_client_buffer *
+drm_client_framebuffer_create(struct drm_client_dev *client, u32 width, u32 height, u32 format);
+void drm_client_framebuffer_delete(struct drm_client_buffer *buffer);
+
+#endif
diff --git a/include/drm/drm_device.h b/include/drm/drm_device.h
index 858ba19a3e29..9e29976d4e98 100644
--- a/include/drm/drm_device.h
+++ b/include/drm/drm_device.h
@@ -74,6 +74,13 @@ struct drm_device {
struct mutex filelist_mutex;
struct list_head filelist;
+ /**
+ * @filelist_internal:
+ *
+ * List of open DRM files for in-kernel clients. Protected by @filelist_mutex.
+ */
+ struct list_head filelist_internal;
+
/** \name Memory management */
/*@{ */
struct list_head maplist; /**< Linked list of regions */
--
2.15.1
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx
^ permalink raw reply related [flat|nested] 24+ messages in thread
* [PATCH v4 2/9] drm/fb-helper: Add generic fbdev emulation .fb_probe function
2018-07-02 13:54 [PATCH v4 0/9] drm: Add generic fbdev emulation Noralf Trønnes
2018-07-02 13:54 ` [PATCH v4 1/9] drm: Begin an API for in-kernel clients Noralf Trønnes
@ 2018-07-02 13:54 ` Noralf Trønnes
2018-07-02 13:54 ` [PATCH v4 3/9] drm/pl111: Set .gem_prime_vmap and .gem_prime_mmap Noralf Trønnes
` (10 subsequent siblings)
12 siblings, 0 replies; 24+ messages in thread
From: Noralf Trønnes @ 2018-07-02 13:54 UTC (permalink / raw)
To: dri-devel; +Cc: intel-gfx, laurent.pinchart, david
This is the first step in getting generic fbdev emulation.
A drm_fb_helper_funcs.fb_probe function is added which uses the
DRM client API to get a framebuffer backed by a dumb buffer.
Signed-off-by: Noralf Trønnes <noralf@tronnes.org>
Reviewed-by: Daniel Vetter <daniel.vetter@ffwll.ch>
---
drivers/gpu/drm/drm_fb_helper.c | 192 +++++++++++++++++++++++++++++++++++++++-
include/drm/drm_fb_helper.h | 31 +++++++
2 files changed, 222 insertions(+), 1 deletion(-)
diff --git a/drivers/gpu/drm/drm_fb_helper.c b/drivers/gpu/drm/drm_fb_helper.c
index cab14f253384..0a0a577ebc3c 100644
--- a/drivers/gpu/drm/drm_fb_helper.c
+++ b/drivers/gpu/drm/drm_fb_helper.c
@@ -30,6 +30,7 @@
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
#include <linux/console.h>
+#include <linux/dma-buf.h>
#include <linux/kernel.h>
#include <linux/sysrq.h>
#include <linux/slab.h>
@@ -738,6 +739,24 @@ static void drm_fb_helper_resume_worker(struct work_struct *work)
console_unlock();
}
+static void drm_fb_helper_dirty_blit_real(struct drm_fb_helper *fb_helper,
+ struct drm_clip_rect *clip)
+{
+ struct drm_framebuffer *fb = fb_helper->fb;
+ unsigned int cpp = drm_format_plane_cpp(fb->format->format, 0);
+ size_t offset = clip->y1 * fb->pitches[0] + clip->x1 * cpp;
+ void *src = fb_helper->fbdev->screen_buffer + offset;
+ void *dst = fb_helper->buffer->vaddr + offset;
+ size_t len = (clip->x2 - clip->x1) * cpp;
+ unsigned int y;
+
+ for (y = clip->y1; y < clip->y2; y++) {
+ memcpy(dst, src, len);
+ src += fb->pitches[0];
+ dst += fb->pitches[0];
+ }
+}
+
static void drm_fb_helper_dirty_work(struct work_struct *work)
{
struct drm_fb_helper *helper = container_of(work, struct drm_fb_helper,
@@ -753,8 +772,12 @@ static void drm_fb_helper_dirty_work(struct work_struct *work)
spin_unlock_irqrestore(&helper->dirty_lock, flags);
/* call dirty callback only when it has been really touched */
- if (clip_copy.x1 < clip_copy.x2 && clip_copy.y1 < clip_copy.y2)
+ if (clip_copy.x1 < clip_copy.x2 && clip_copy.y1 < clip_copy.y2) {
+ /* Generic fbdev uses a shadow buffer */
+ if (helper->buffer)
+ drm_fb_helper_dirty_blit_real(helper, &clip_copy);
helper->fb->funcs->dirty(helper->fb, NULL, 0, 0, &clip_copy, 1);
+ }
}
/**
@@ -2921,6 +2944,173 @@ void drm_fb_helper_output_poll_changed(struct drm_device *dev)
}
EXPORT_SYMBOL(drm_fb_helper_output_poll_changed);
+/* @user: 1=userspace, 0=fbcon */
+static int drm_fbdev_fb_open(struct fb_info *info, int user)
+{
+ struct drm_fb_helper *fb_helper = info->par;
+
+ if (!try_module_get(fb_helper->dev->driver->fops->owner))
+ return -ENODEV;
+
+ return 0;
+}
+
+static int drm_fbdev_fb_release(struct fb_info *info, int user)
+{
+ struct drm_fb_helper *fb_helper = info->par;
+
+ module_put(fb_helper->dev->driver->fops->owner);
+
+ return 0;
+}
+
+/*
+ * fb_ops.fb_destroy is called by the last put_fb_info() call at the end of
+ * unregister_framebuffer() or fb_release().
+ */
+static void drm_fbdev_fb_destroy(struct fb_info *info)
+{
+ struct drm_fb_helper *fb_helper = info->par;
+ struct fb_info *fbi = fb_helper->fbdev;
+ struct fb_ops *fbops = NULL;
+ void *shadow = NULL;
+
+ if (fbi->fbdefio) {
+ fb_deferred_io_cleanup(fbi);
+ shadow = fbi->screen_buffer;
+ fbops = fbi->fbops;
+ }
+
+ drm_fb_helper_fini(fb_helper);
+
+ if (shadow) {
+ vfree(shadow);
+ kfree(fbops);
+ }
+
+ drm_client_framebuffer_delete(fb_helper->buffer);
+ drm_client_release(&fb_helper->client);
+ kfree(fb_helper);
+}
+
+static int drm_fbdev_fb_mmap(struct fb_info *info, struct vm_area_struct *vma)
+{
+ struct drm_fb_helper *fb_helper = info->par;
+
+ if (fb_helper->dev->driver->gem_prime_mmap)
+ return fb_helper->dev->driver->gem_prime_mmap(fb_helper->buffer->gem, vma);
+ else
+ return -ENODEV;
+}
+
+static struct fb_ops drm_fbdev_fb_ops = {
+ .owner = THIS_MODULE,
+ DRM_FB_HELPER_DEFAULT_OPS,
+ .fb_open = drm_fbdev_fb_open,
+ .fb_release = drm_fbdev_fb_release,
+ .fb_destroy = drm_fbdev_fb_destroy,
+ .fb_mmap = drm_fbdev_fb_mmap,
+ .fb_read = drm_fb_helper_sys_read,
+ .fb_write = drm_fb_helper_sys_write,
+ .fb_fillrect = drm_fb_helper_sys_fillrect,
+ .fb_copyarea = drm_fb_helper_sys_copyarea,
+ .fb_imageblit = drm_fb_helper_sys_imageblit,
+};
+
+static struct fb_deferred_io drm_fbdev_defio = {
+ .delay = HZ / 20,
+ .deferred_io = drm_fb_helper_deferred_io,
+};
+
+/**
+ * drm_fb_helper_generic_probe - Generic fbdev emulation probe helper
+ * @fb_helper: fbdev helper structure
+ * @sizes: describes fbdev size and scanout surface size
+ *
+ * This function uses the client API to crate a framebuffer backed by a dumb buffer.
+ *
+ * The _sys_ versions are used for &fb_ops.fb_read, fb_write, fb_fillrect,
+ * fb_copyarea, fb_imageblit.
+ *
+ * Returns:
+ * Zero on success or negative error code on failure.
+ */
+int drm_fb_helper_generic_probe(struct drm_fb_helper *fb_helper,
+ struct drm_fb_helper_surface_size *sizes)
+{
+ struct drm_client_dev *client = &fb_helper->client;
+ struct drm_client_buffer *buffer;
+ struct drm_framebuffer *fb;
+ struct fb_info *fbi;
+ u32 format;
+ int ret;
+
+ DRM_DEBUG_KMS("surface width(%d), height(%d) and bpp(%d)\n",
+ sizes->surface_width, sizes->surface_height,
+ sizes->surface_bpp);
+
+ format = drm_mode_legacy_fb_format(sizes->surface_bpp, sizes->surface_depth);
+ buffer = drm_client_framebuffer_create(client, sizes->surface_width,
+ sizes->surface_height, format);
+ if (IS_ERR(buffer))
+ return PTR_ERR(buffer);
+
+ fb_helper->buffer = buffer;
+ fb_helper->fb = buffer->fb;
+ fb = buffer->fb;
+
+ fbi = drm_fb_helper_alloc_fbi(fb_helper);
+ if (IS_ERR(fbi)) {
+ ret = PTR_ERR(fbi);
+ goto err_free_buffer;
+ }
+
+ fbi->par = fb_helper;
+ fbi->fbops = &drm_fbdev_fb_ops;
+ fbi->screen_size = fb->height * fb->pitches[0];
+ fbi->fix.smem_len = fbi->screen_size;
+ fbi->screen_buffer = buffer->vaddr;
+ strcpy(fbi->fix.id, "DRM emulated");
+
+ drm_fb_helper_fill_fix(fbi, fb->pitches[0], fb->format->depth);
+ drm_fb_helper_fill_var(fbi, fb_helper, sizes->fb_width, sizes->fb_height);
+
+ if (fb->funcs->dirty) {
+ struct fb_ops *fbops;
+ void *shadow;
+
+ /*
+ * fb_deferred_io_cleanup() clears &fbops->fb_mmap so a per
+ * instance version is necessary.
+ */
+ fbops = kzalloc(sizeof(*fbops), GFP_KERNEL);
+ shadow = vzalloc(fbi->screen_size);
+ if (!fbops || !shadow) {
+ kfree(fbops);
+ vfree(shadow);
+ ret = -ENOMEM;
+ goto err_fb_info_destroy;
+ }
+
+ *fbops = *fbi->fbops;
+ fbi->fbops = fbops;
+ fbi->screen_buffer = shadow;
+ fbi->fbdefio = &drm_fbdev_defio;
+
+ fb_deferred_io_init(fbi);
+ }
+
+ return 0;
+
+err_fb_info_destroy:
+ drm_fb_helper_fini(fb_helper);
+err_free_buffer:
+ drm_client_framebuffer_delete(buffer);
+
+ return ret;
+}
+EXPORT_SYMBOL(drm_fb_helper_generic_probe);
+
/* The Kconfig DRM_KMS_HELPER selects FRAMEBUFFER_CONSOLE (if !EXPERT)
* but the module doesn't depend on any fb console symbols. At least
* attempt to load fbcon to avoid leaving the system without a usable console.
diff --git a/include/drm/drm_fb_helper.h b/include/drm/drm_fb_helper.h
index b069433e7fc1..c134bbcfd2e9 100644
--- a/include/drm/drm_fb_helper.h
+++ b/include/drm/drm_fb_helper.h
@@ -32,6 +32,7 @@
struct drm_fb_helper;
+#include <drm/drm_client.h>
#include <drm/drm_crtc.h>
#include <drm/drm_device.h>
#include <linux/kgdb.h>
@@ -154,6 +155,20 @@ struct drm_fb_helper_connector {
* operations.
*/
struct drm_fb_helper {
+ /**
+ * @client:
+ *
+ * DRM client used by the generic fbdev emulation.
+ */
+ struct drm_client_dev client;
+
+ /**
+ * @buffer:
+ *
+ * Framebuffer used by the generic fbdev emulation.
+ */
+ struct drm_client_buffer *buffer;
+
struct drm_framebuffer *fb;
struct drm_device *dev;
int crtc_count;
@@ -234,6 +249,12 @@ struct drm_fb_helper {
int preferred_bpp;
};
+static inline struct drm_fb_helper *
+drm_fb_helper_from_client(struct drm_client_dev *client)
+{
+ return container_of(client, struct drm_fb_helper, client);
+}
+
/**
* define DRM_FB_HELPER_DEFAULT_OPS - helper define for drm drivers
*
@@ -330,6 +351,9 @@ void drm_fb_helper_fbdev_teardown(struct drm_device *dev);
void drm_fb_helper_lastclose(struct drm_device *dev);
void drm_fb_helper_output_poll_changed(struct drm_device *dev);
+
+int drm_fb_helper_generic_probe(struct drm_fb_helper *fb_helper,
+ struct drm_fb_helper_surface_size *sizes);
#else
static inline void drm_fb_helper_prepare(struct drm_device *dev,
struct drm_fb_helper *helper,
@@ -564,6 +588,13 @@ static inline void drm_fb_helper_output_poll_changed(struct drm_device *dev)
{
}
+static inline int
+drm_fb_helper_generic_probe(struct drm_fb_helper *fb_helper,
+ struct drm_fb_helper_surface_size *sizes)
+{
+ return 0;
+}
+
#endif
static inline int
--
2.15.1
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel
^ permalink raw reply related [flat|nested] 24+ messages in thread
* [PATCH v4 3/9] drm/pl111: Set .gem_prime_vmap and .gem_prime_mmap
2018-07-02 13:54 [PATCH v4 0/9] drm: Add generic fbdev emulation Noralf Trønnes
2018-07-02 13:54 ` [PATCH v4 1/9] drm: Begin an API for in-kernel clients Noralf Trønnes
2018-07-02 13:54 ` [PATCH v4 2/9] drm/fb-helper: Add generic fbdev emulation .fb_probe function Noralf Trønnes
@ 2018-07-02 13:54 ` Noralf Trønnes
2018-07-02 13:54 ` [PATCH v4 4/9] drm/cma-helper: Use the generic fbdev emulation Noralf Trønnes
` (9 subsequent siblings)
12 siblings, 0 replies; 24+ messages in thread
From: Noralf Trønnes @ 2018-07-02 13:54 UTC (permalink / raw)
To: dri-devel; +Cc: intel-gfx, laurent.pinchart, david
These are needed for pl111 to use the generic fbdev emulation.
Cc: Eric Anholt <eric@anholt.net>
Signed-off-by: Noralf Trønnes <noralf@tronnes.org>
Reviewed-by: Eric Anholt <eric@anholt.net>
---
drivers/gpu/drm/pl111/pl111_drv.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/drivers/gpu/drm/pl111/pl111_drv.c b/drivers/gpu/drm/pl111/pl111_drv.c
index 054b93689d94..17a38e85ba7d 100644
--- a/drivers/gpu/drm/pl111/pl111_drv.c
+++ b/drivers/gpu/drm/pl111/pl111_drv.c
@@ -250,6 +250,8 @@ static struct drm_driver pl111_drm_driver = {
.gem_prime_import_sg_table = pl111_gem_import_sg_table,
.gem_prime_export = drm_gem_prime_export,
.gem_prime_get_sg_table = drm_gem_cma_prime_get_sg_table,
+ .gem_prime_mmap = drm_gem_cma_prime_mmap,
+ .gem_prime_vmap = drm_gem_cma_prime_vmap,
#if defined(CONFIG_DEBUG_FS)
.debugfs_init = pl111_debugfs_init,
--
2.15.1
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel
^ permalink raw reply related [flat|nested] 24+ messages in thread
* [PATCH v4 4/9] drm/cma-helper: Use the generic fbdev emulation
2018-07-02 13:54 [PATCH v4 0/9] drm: Add generic fbdev emulation Noralf Trønnes
` (2 preceding siblings ...)
2018-07-02 13:54 ` [PATCH v4 3/9] drm/pl111: Set .gem_prime_vmap and .gem_prime_mmap Noralf Trønnes
@ 2018-07-02 13:54 ` Noralf Trønnes
2018-07-02 13:54 ` [PATCH v4 5/9] drm/client: Add client callbacks Noralf Trønnes
` (8 subsequent siblings)
12 siblings, 0 replies; 24+ messages in thread
From: Noralf Trønnes @ 2018-07-02 13:54 UTC (permalink / raw)
To: dri-devel; +Cc: intel-gfx, laurent.pinchart, david
This switches the CMA helper drivers that use its fbdev emulation over
to the generic fbdev emulation. It's the first phase of using generic
fbdev. A later phase will use DRM client callbacks for the
lastclose/hotplug/remove callbacks.
There are currently 2 fbdev init/fini functions:
- drm_fb_cma_fbdev_init/drm_fb_cma_fbdev_fini
- drm_fbdev_cma_init/drm_fbdev_cma_fini
This is because the work on generic fbdev came up during a fbdev
refactoring and thus wasn't completed. No point in completing that
refactoring when drivers will soon move to drm_fb_helper_generic_probe().
tinydrm uses drm_fb_cma_fbdev_init_with_funcs().
Cc: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Signed-off-by: Noralf Trønnes <noralf@tronnes.org>
Acked-by: Daniel Vetter <daniel.vetter@ffwll.ch>
---
drivers/gpu/drm/drm_fb_cma_helper.c | 360 +++++-------------------------------
include/drm/drm_fb_cma_helper.h | 3 -
2 files changed, 42 insertions(+), 321 deletions(-)
diff --git a/drivers/gpu/drm/drm_fb_cma_helper.c b/drivers/gpu/drm/drm_fb_cma_helper.c
index 186d00adfb5f..5762a7c441e9 100644
--- a/drivers/gpu/drm/drm_fb_cma_helper.c
+++ b/drivers/gpu/drm/drm_fb_cma_helper.c
@@ -18,6 +18,7 @@
*/
#include <drm/drmP.h>
+#include <drm/drm_client.h>
#include <drm/drm_fb_helper.h>
#include <drm/drm_framebuffer.h>
#include <drm/drm_gem_cma_helper.h>
@@ -26,11 +27,8 @@
#include <drm/drm_print.h>
#include <linux/module.h>
-#define DEFAULT_FBDEFIO_DELAY_MS 50
-
struct drm_fbdev_cma {
struct drm_fb_helper fb_helper;
- const struct drm_framebuffer_funcs *fb_funcs;
};
/**
@@ -44,36 +42,6 @@ struct drm_fbdev_cma {
*
* An fbdev framebuffer backed by cma is also available by calling
* drm_fb_cma_fbdev_init(). drm_fb_cma_fbdev_fini() tears it down.
- * If the &drm_framebuffer_funcs.dirty callback is set, fb_deferred_io will be
- * set up automatically. &drm_framebuffer_funcs.dirty is called by
- * drm_fb_helper_deferred_io() in process context (&struct delayed_work).
- *
- * Example fbdev deferred io code::
- *
- * static int driver_fb_dirty(struct drm_framebuffer *fb,
- * struct drm_file *file_priv,
- * unsigned flags, unsigned color,
- * struct drm_clip_rect *clips,
- * unsigned num_clips)
- * {
- * struct drm_gem_cma_object *cma = drm_fb_cma_get_gem_obj(fb, 0);
- * ... push changes ...
- * return 0;
- * }
- *
- * static struct drm_framebuffer_funcs driver_fb_funcs = {
- * .destroy = drm_gem_fb_destroy,
- * .create_handle = drm_gem_fb_create_handle,
- * .dirty = driver_fb_dirty,
- * };
- *
- * Initialize::
- *
- * fbdev = drm_fb_cma_fbdev_init_with_funcs(dev, 16,
- * dev->mode_config.num_crtc,
- * dev->mode_config.num_connector,
- * &driver_fb_funcs);
- *
*/
static inline struct drm_fbdev_cma *to_fbdev_cma(struct drm_fb_helper *helper)
@@ -131,153 +99,6 @@ dma_addr_t drm_fb_cma_get_gem_addr(struct drm_framebuffer *fb,
}
EXPORT_SYMBOL_GPL(drm_fb_cma_get_gem_addr);
-static int drm_fb_cma_mmap(struct fb_info *info, struct vm_area_struct *vma)
-{
- return dma_mmap_writecombine(info->device, vma, info->screen_base,
- info->fix.smem_start, info->fix.smem_len);
-}
-
-static struct fb_ops drm_fbdev_cma_ops = {
- .owner = THIS_MODULE,
- DRM_FB_HELPER_DEFAULT_OPS,
- .fb_fillrect = drm_fb_helper_sys_fillrect,
- .fb_copyarea = drm_fb_helper_sys_copyarea,
- .fb_imageblit = drm_fb_helper_sys_imageblit,
- .fb_mmap = drm_fb_cma_mmap,
-};
-
-static int drm_fbdev_cma_deferred_io_mmap(struct fb_info *info,
- struct vm_area_struct *vma)
-{
- fb_deferred_io_mmap(info, vma);
- vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot);
-
- return 0;
-}
-
-static int drm_fbdev_cma_defio_init(struct fb_info *fbi,
- struct drm_gem_cma_object *cma_obj)
-{
- struct fb_deferred_io *fbdefio;
- struct fb_ops *fbops;
-
- /*
- * Per device structures are needed because:
- * fbops: fb_deferred_io_cleanup() clears fbops.fb_mmap
- * fbdefio: individual delays
- */
- fbdefio = kzalloc(sizeof(*fbdefio), GFP_KERNEL);
- fbops = kzalloc(sizeof(*fbops), GFP_KERNEL);
- if (!fbdefio || !fbops) {
- kfree(fbdefio);
- kfree(fbops);
- return -ENOMEM;
- }
-
- /* can't be offset from vaddr since dirty() uses cma_obj */
- fbi->screen_buffer = cma_obj->vaddr;
- /* fb_deferred_io_fault() needs a physical address */
- fbi->fix.smem_start = page_to_phys(virt_to_page(fbi->screen_buffer));
-
- *fbops = *fbi->fbops;
- fbi->fbops = fbops;
-
- fbdefio->delay = msecs_to_jiffies(DEFAULT_FBDEFIO_DELAY_MS);
- fbdefio->deferred_io = drm_fb_helper_deferred_io;
- fbi->fbdefio = fbdefio;
- fb_deferred_io_init(fbi);
- fbi->fbops->fb_mmap = drm_fbdev_cma_deferred_io_mmap;
-
- return 0;
-}
-
-static void drm_fbdev_cma_defio_fini(struct fb_info *fbi)
-{
- if (!fbi->fbdefio)
- return;
-
- fb_deferred_io_cleanup(fbi);
- kfree(fbi->fbdefio);
- kfree(fbi->fbops);
-}
-
-static int
-drm_fbdev_cma_create(struct drm_fb_helper *helper,
- struct drm_fb_helper_surface_size *sizes)
-{
- struct drm_fbdev_cma *fbdev_cma = to_fbdev_cma(helper);
- struct drm_device *dev = helper->dev;
- struct drm_gem_cma_object *obj;
- struct drm_framebuffer *fb;
- unsigned int bytes_per_pixel;
- unsigned long offset;
- struct fb_info *fbi;
- size_t size;
- int ret;
-
- DRM_DEBUG_KMS("surface width(%d), height(%d) and bpp(%d)\n",
- sizes->surface_width, sizes->surface_height,
- sizes->surface_bpp);
-
- bytes_per_pixel = DIV_ROUND_UP(sizes->surface_bpp, 8);
- size = sizes->surface_width * sizes->surface_height * bytes_per_pixel;
- obj = drm_gem_cma_create(dev, size);
- if (IS_ERR(obj))
- return -ENOMEM;
-
- fbi = drm_fb_helper_alloc_fbi(helper);
- if (IS_ERR(fbi)) {
- ret = PTR_ERR(fbi);
- goto err_gem_free_object;
- }
-
- fb = drm_gem_fbdev_fb_create(dev, sizes, 0, &obj->base,
- fbdev_cma->fb_funcs);
- if (IS_ERR(fb)) {
- dev_err(dev->dev, "Failed to allocate DRM framebuffer.\n");
- ret = PTR_ERR(fb);
- goto err_fb_info_destroy;
- }
-
- helper->fb = fb;
-
- fbi->par = helper;
- fbi->flags = FBINFO_FLAG_DEFAULT;
- fbi->fbops = &drm_fbdev_cma_ops;
-
- drm_fb_helper_fill_fix(fbi, fb->pitches[0], fb->format->depth);
- drm_fb_helper_fill_var(fbi, helper, sizes->fb_width, sizes->fb_height);
-
- offset = fbi->var.xoffset * bytes_per_pixel;
- offset += fbi->var.yoffset * fb->pitches[0];
-
- dev->mode_config.fb_base = (resource_size_t)obj->paddr;
- fbi->screen_base = obj->vaddr + offset;
- fbi->fix.smem_start = (unsigned long)(obj->paddr + offset);
- fbi->screen_size = size;
- fbi->fix.smem_len = size;
-
- if (fb->funcs->dirty) {
- ret = drm_fbdev_cma_defio_init(fbi, obj);
- if (ret)
- goto err_cma_destroy;
- }
-
- return 0;
-
-err_cma_destroy:
- drm_framebuffer_remove(fb);
-err_fb_info_destroy:
- drm_fb_helper_fini(helper);
-err_gem_free_object:
- drm_gem_object_put_unlocked(&obj->base);
- return ret;
-}
-
-static const struct drm_fb_helper_funcs drm_fb_cma_helper_funcs = {
- .fb_probe = drm_fbdev_cma_create,
-};
-
/**
* drm_fb_cma_fbdev_init_with_funcs() - Allocate and initialize fbdev emulation
* @dev: DRM device
@@ -295,53 +116,7 @@ int drm_fb_cma_fbdev_init_with_funcs(struct drm_device *dev,
unsigned int preferred_bpp, unsigned int max_conn_count,
const struct drm_framebuffer_funcs *funcs)
{
- struct drm_fbdev_cma *fbdev_cma;
- struct drm_fb_helper *fb_helper;
- int ret;
-
- if (!preferred_bpp)
- preferred_bpp = dev->mode_config.preferred_depth;
- if (!preferred_bpp)
- preferred_bpp = 32;
-
- if (!max_conn_count)
- max_conn_count = dev->mode_config.num_connector;
-
- fbdev_cma = kzalloc(sizeof(*fbdev_cma), GFP_KERNEL);
- if (!fbdev_cma)
- return -ENOMEM;
-
- fbdev_cma->fb_funcs = funcs;
- fb_helper = &fbdev_cma->fb_helper;
-
- drm_fb_helper_prepare(dev, fb_helper, &drm_fb_cma_helper_funcs);
-
- ret = drm_fb_helper_init(dev, fb_helper, max_conn_count);
- if (ret < 0) {
- DRM_DEV_ERROR(dev->dev, "Failed to initialize fbdev helper.\n");
- goto err_free;
- }
-
- ret = drm_fb_helper_single_add_all_connectors(fb_helper);
- if (ret < 0) {
- DRM_DEV_ERROR(dev->dev, "Failed to add connectors.\n");
- goto err_drm_fb_helper_fini;
- }
-
- ret = drm_fb_helper_initial_config(fb_helper, preferred_bpp);
- if (ret < 0) {
- DRM_DEV_ERROR(dev->dev, "Failed to set fbdev configuration.\n");
- goto err_drm_fb_helper_fini;
- }
-
- return 0;
-
-err_drm_fb_helper_fini:
- drm_fb_helper_fini(fb_helper);
-err_free:
- kfree(fbdev_cma);
-
- return ret;
+ return drm_fb_cma_fbdev_init(dev, preferred_bpp, max_conn_count);
}
EXPORT_SYMBOL_GPL(drm_fb_cma_fbdev_init_with_funcs);
@@ -359,8 +134,14 @@ EXPORT_SYMBOL_GPL(drm_fb_cma_fbdev_init_with_funcs);
int drm_fb_cma_fbdev_init(struct drm_device *dev, unsigned int preferred_bpp,
unsigned int max_conn_count)
{
- return drm_fb_cma_fbdev_init_with_funcs(dev, preferred_bpp,
- max_conn_count, NULL);
+ struct drm_fbdev_cma *fbdev_cma;
+
+ /* dev->fb_helper will indirectly point to fbdev_cma after this call */
+ fbdev_cma = drm_fbdev_cma_init(dev, preferred_bpp, max_conn_count);
+ if (IS_ERR(fbdev_cma))
+ return PTR_ERR(fbdev_cma);
+
+ return 0;
}
EXPORT_SYMBOL_GPL(drm_fb_cma_fbdev_init);
@@ -370,87 +151,13 @@ EXPORT_SYMBOL_GPL(drm_fb_cma_fbdev_init);
*/
void drm_fb_cma_fbdev_fini(struct drm_device *dev)
{
- struct drm_fb_helper *fb_helper = dev->fb_helper;
-
- if (!fb_helper)
- return;
-
- /* Unregister if it hasn't been done already */
- if (fb_helper->fbdev && fb_helper->fbdev->dev)
- drm_fb_helper_unregister_fbi(fb_helper);
-
- if (fb_helper->fbdev)
- drm_fbdev_cma_defio_fini(fb_helper->fbdev);
-
- if (fb_helper->fb)
- drm_framebuffer_remove(fb_helper->fb);
-
- drm_fb_helper_fini(fb_helper);
- kfree(to_fbdev_cma(fb_helper));
+ if (dev->fb_helper)
+ drm_fbdev_cma_fini(to_fbdev_cma(dev->fb_helper));
}
EXPORT_SYMBOL_GPL(drm_fb_cma_fbdev_fini);
-/**
- * drm_fbdev_cma_init_with_funcs() - Allocate and initializes a drm_fbdev_cma struct
- * @dev: DRM device
- * @preferred_bpp: Preferred bits per pixel for the device
- * @max_conn_count: Maximum number of connectors
- * @funcs: fb helper functions, in particular a custom dirty() callback
- *
- * Returns a newly allocated drm_fbdev_cma struct or a ERR_PTR.
- */
-struct drm_fbdev_cma *drm_fbdev_cma_init_with_funcs(struct drm_device *dev,
- unsigned int preferred_bpp, unsigned int max_conn_count,
- const struct drm_framebuffer_funcs *funcs)
-{
- struct drm_fbdev_cma *fbdev_cma;
- struct drm_fb_helper *helper;
- int ret;
-
- fbdev_cma = kzalloc(sizeof(*fbdev_cma), GFP_KERNEL);
- if (!fbdev_cma) {
- dev_err(dev->dev, "Failed to allocate drm fbdev.\n");
- return ERR_PTR(-ENOMEM);
- }
- fbdev_cma->fb_funcs = funcs;
-
- helper = &fbdev_cma->fb_helper;
-
- drm_fb_helper_prepare(dev, helper, &drm_fb_cma_helper_funcs);
-
- ret = drm_fb_helper_init(dev, helper, max_conn_count);
- if (ret < 0) {
- dev_err(dev->dev, "Failed to initialize drm fb helper.\n");
- goto err_free;
- }
-
- ret = drm_fb_helper_single_add_all_connectors(helper);
- if (ret < 0) {
- dev_err(dev->dev, "Failed to add connectors.\n");
- goto err_drm_fb_helper_fini;
-
- }
-
- ret = drm_fb_helper_initial_config(helper, preferred_bpp);
- if (ret < 0) {
- dev_err(dev->dev, "Failed to set initial hw configuration.\n");
- goto err_drm_fb_helper_fini;
- }
-
- return fbdev_cma;
-
-err_drm_fb_helper_fini:
- drm_fb_helper_fini(helper);
-err_free:
- kfree(fbdev_cma);
-
- return ERR_PTR(ret);
-}
-EXPORT_SYMBOL_GPL(drm_fbdev_cma_init_with_funcs);
-
-static const struct drm_framebuffer_funcs drm_fb_cma_funcs = {
- .destroy = drm_gem_fb_destroy,
- .create_handle = drm_gem_fb_create_handle,
+static const struct drm_fb_helper_funcs drm_fb_cma_helper_funcs = {
+ .fb_probe = drm_fb_helper_generic_probe,
};
/**
@@ -464,9 +171,33 @@ static const struct drm_framebuffer_funcs drm_fb_cma_funcs = {
struct drm_fbdev_cma *drm_fbdev_cma_init(struct drm_device *dev,
unsigned int preferred_bpp, unsigned int max_conn_count)
{
- return drm_fbdev_cma_init_with_funcs(dev, preferred_bpp,
- max_conn_count,
- &drm_fb_cma_funcs);
+ struct drm_fbdev_cma *fbdev_cma;
+ struct drm_fb_helper *fb_helper;
+ int ret;
+
+ fbdev_cma = kzalloc(sizeof(*fbdev_cma), GFP_KERNEL);
+ if (!fbdev_cma)
+ return ERR_PTR(-ENOMEM);
+
+ fb_helper = &fbdev_cma->fb_helper;
+
+ ret = drm_client_new(dev, &fb_helper->client, "fbdev");
+ if (ret)
+ goto err_free;
+
+ ret = drm_fb_helper_fbdev_setup(dev, fb_helper, &drm_fb_cma_helper_funcs,
+ preferred_bpp, max_conn_count);
+ if (ret)
+ goto err_client_put;
+
+ return fbdev_cma;
+
+err_client_put:
+ drm_client_release(&fb_helper->client);
+err_free:
+ kfree(fbdev_cma);
+
+ return ERR_PTR(ret);
}
EXPORT_SYMBOL_GPL(drm_fbdev_cma_init);
@@ -477,14 +208,7 @@ EXPORT_SYMBOL_GPL(drm_fbdev_cma_init);
void drm_fbdev_cma_fini(struct drm_fbdev_cma *fbdev_cma)
{
drm_fb_helper_unregister_fbi(&fbdev_cma->fb_helper);
- if (fbdev_cma->fb_helper.fbdev)
- drm_fbdev_cma_defio_fini(fbdev_cma->fb_helper.fbdev);
-
- if (fbdev_cma->fb_helper.fb)
- drm_framebuffer_remove(fbdev_cma->fb_helper.fb);
-
- drm_fb_helper_fini(&fbdev_cma->fb_helper);
- kfree(fbdev_cma);
+ /* All resources have now been freed by drm_fbdev_fb_destroy() */
}
EXPORT_SYMBOL_GPL(drm_fbdev_cma_fini);
diff --git a/include/drm/drm_fb_cma_helper.h b/include/drm/drm_fb_cma_helper.h
index d532f88a8d55..a0546c3451f9 100644
--- a/include/drm/drm_fb_cma_helper.h
+++ b/include/drm/drm_fb_cma_helper.h
@@ -23,9 +23,6 @@ int drm_fb_cma_fbdev_init(struct drm_device *dev, unsigned int preferred_bpp,
unsigned int max_conn_count);
void drm_fb_cma_fbdev_fini(struct drm_device *dev);
-struct drm_fbdev_cma *drm_fbdev_cma_init_with_funcs(struct drm_device *dev,
- unsigned int preferred_bpp, unsigned int max_conn_count,
- const struct drm_framebuffer_funcs *funcs);
struct drm_fbdev_cma *drm_fbdev_cma_init(struct drm_device *dev,
unsigned int preferred_bpp, unsigned int max_conn_count);
void drm_fbdev_cma_fini(struct drm_fbdev_cma *fbdev_cma);
--
2.15.1
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel
^ permalink raw reply related [flat|nested] 24+ messages in thread
* [PATCH v4 5/9] drm/client: Add client callbacks
2018-07-02 13:54 [PATCH v4 0/9] drm: Add generic fbdev emulation Noralf Trønnes
` (3 preceding siblings ...)
2018-07-02 13:54 ` [PATCH v4 4/9] drm/cma-helper: Use the generic fbdev emulation Noralf Trønnes
@ 2018-07-02 13:54 ` Noralf Trønnes
2018-07-03 7:46 ` Daniel Vetter
2018-07-02 13:54 ` [PATCH v4 6/9] drm/debugfs: Add internal client debugfs file Noralf Trønnes
` (7 subsequent siblings)
12 siblings, 1 reply; 24+ messages in thread
From: Noralf Trønnes @ 2018-07-02 13:54 UTC (permalink / raw)
To: dri-devel; +Cc: intel-gfx, laurent.pinchart, david
Add client callbacks and hook them up.
Add a list of clients per drm_device.
Signed-off-by: Noralf Trønnes <noralf@tronnes.org>
---
drivers/gpu/drm/drm_client.c | 92 ++++++++++++++++++++++++++++++++++++-
drivers/gpu/drm/drm_drv.c | 7 +++
drivers/gpu/drm/drm_fb_cma_helper.c | 2 +-
drivers/gpu/drm/drm_fb_helper.c | 11 ++++-
drivers/gpu/drm/drm_file.c | 3 ++
drivers/gpu/drm/drm_probe_helper.c | 3 ++
include/drm/drm_client.h | 75 +++++++++++++++++++++++++++++-
include/drm/drm_device.h | 14 ++++++
8 files changed, 201 insertions(+), 6 deletions(-)
diff --git a/drivers/gpu/drm/drm_client.c b/drivers/gpu/drm/drm_client.c
index 9c9b8ac7aea3..f05ee98bd10c 100644
--- a/drivers/gpu/drm/drm_client.c
+++ b/drivers/gpu/drm/drm_client.c
@@ -4,6 +4,7 @@
*/
#include <linux/list.h>
+#include <linux/module.h>
#include <linux/mutex.h>
#include <linux/seq_file.h>
#include <linux/slab.h>
@@ -66,6 +67,7 @@ EXPORT_SYMBOL(drm_client_close);
* @dev: DRM device
* @client: DRM client
* @name: Client name
+ * @funcs: DRM client functions (optional)
*
* Use drm_client_put() to free the client.
*
@@ -73,24 +75,47 @@ EXPORT_SYMBOL(drm_client_close);
* Zero on success or negative error code on failure.
*/
int drm_client_new(struct drm_device *dev, struct drm_client_dev *client,
- const char *name)
+ const char *name, const struct drm_client_funcs *funcs)
{
+ bool registered;
int ret;
if (!drm_core_check_feature(dev, DRIVER_MODESET) ||
!dev->driver->dumb_create || !dev->driver->gem_prime_vmap)
return -ENOTSUPP;
+ if (funcs && !try_module_get(funcs->owner))
+ return -ENODEV;
+
client->dev = dev;
client->name = name;
+ client->funcs = funcs;
ret = drm_client_open(client);
if (ret)
- return ret;
+ goto err_put_module;
+
+ mutex_lock(&dev->clientlist_mutex);
+ registered = dev->registered;
+ if (registered)
+ list_add(&client->list, &dev->clientlist);
+ mutex_unlock(&dev->clientlist_mutex);
+ if (!registered) {
+ ret = -ENODEV;
+ goto err_close;
+ }
drm_dev_get(dev);
return 0;
+
+err_close:
+ drm_client_close(client);
+err_put_module:
+ if (funcs)
+ module_put(funcs->owner);
+
+ return ret;
}
EXPORT_SYMBOL(drm_client_new);
@@ -116,9 +141,72 @@ void drm_client_release(struct drm_client_dev *client)
drm_client_close(client);
drm_dev_put(dev);
+ if (client->funcs)
+ module_put(client->funcs->owner);
}
EXPORT_SYMBOL(drm_client_release);
+void drm_client_dev_unregister(struct drm_device *dev)
+{
+ struct drm_client_dev *client, *tmp;
+
+ if (!drm_core_check_feature(dev, DRIVER_MODESET))
+ return;
+
+ mutex_lock(&dev->clientlist_mutex);
+ list_for_each_entry_safe(client, tmp, &dev->clientlist, list) {
+ list_del(&client->list);
+ if (client->funcs && client->funcs->unregister) {
+ client->funcs->unregister(client);
+ } else {
+ drm_client_release(client);
+ kfree(client);
+ }
+ }
+ mutex_unlock(&dev->clientlist_mutex);
+}
+
+void drm_client_dev_hotplug(struct drm_device *dev)
+{
+ struct drm_client_dev *client;
+ int ret;
+
+ if (!drm_core_check_feature(dev, DRIVER_MODESET))
+ return;
+
+ mutex_lock(&dev->clientlist_mutex);
+ list_for_each_entry(client, &dev->clientlist, list) {
+ if (!client->funcs || !client->funcs->hotplug)
+ continue;
+
+ ret = client->funcs->hotplug(client);
+ DRM_DEV_DEBUG_KMS(dev->dev, "%s: ret=%d\n", client->name, ret);
+ }
+ mutex_unlock(&dev->clientlist_mutex);
+}
+EXPORT_SYMBOL(drm_client_dev_hotplug);
+
+void drm_client_dev_restore(struct drm_device *dev)
+{
+ struct drm_client_dev *client;
+ int ret;
+
+ if (!drm_core_check_feature(dev, DRIVER_MODESET))
+ return;
+
+ mutex_lock(&dev->clientlist_mutex);
+ list_for_each_entry(client, &dev->clientlist, list) {
+ if (!client->funcs || !client->funcs->restore)
+ continue;
+
+ ret = client->funcs->restore(client);
+ DRM_DEV_DEBUG_KMS(dev->dev, "%s: ret=%d\n", client->name, ret);
+ if (!ret) /* The first one to return zero gets the privilege to restore */
+ break;
+ }
+ mutex_unlock(&dev->clientlist_mutex);
+}
+
static void drm_client_buffer_delete(struct drm_client_buffer *buffer)
{
struct drm_device *dev = buffer->client->dev;
diff --git a/drivers/gpu/drm/drm_drv.c b/drivers/gpu/drm/drm_drv.c
index e7ff0b03328b..6eb935bb2f92 100644
--- a/drivers/gpu/drm/drm_drv.c
+++ b/drivers/gpu/drm/drm_drv.c
@@ -34,6 +34,7 @@
#include <linux/slab.h>
#include <linux/srcu.h>
+#include <drm/drm_client.h>
#include <drm/drm_drv.h>
#include <drm/drmP.h>
@@ -506,6 +507,7 @@ int drm_dev_init(struct drm_device *dev,
INIT_LIST_HEAD(&dev->filelist);
INIT_LIST_HEAD(&dev->filelist_internal);
+ INIT_LIST_HEAD(&dev->clientlist);
INIT_LIST_HEAD(&dev->ctxlist);
INIT_LIST_HEAD(&dev->vmalist);
INIT_LIST_HEAD(&dev->maplist);
@@ -515,6 +517,7 @@ int drm_dev_init(struct drm_device *dev,
spin_lock_init(&dev->event_lock);
mutex_init(&dev->struct_mutex);
mutex_init(&dev->filelist_mutex);
+ mutex_init(&dev->clientlist_mutex);
mutex_init(&dev->ctxlist_mutex);
mutex_init(&dev->master_mutex);
@@ -570,6 +573,7 @@ int drm_dev_init(struct drm_device *dev,
err_free:
mutex_destroy(&dev->master_mutex);
mutex_destroy(&dev->ctxlist_mutex);
+ mutex_destroy(&dev->clientlist_mutex);
mutex_destroy(&dev->filelist_mutex);
mutex_destroy(&dev->struct_mutex);
return ret;
@@ -604,6 +608,7 @@ void drm_dev_fini(struct drm_device *dev)
mutex_destroy(&dev->master_mutex);
mutex_destroy(&dev->ctxlist_mutex);
+ mutex_destroy(&dev->clientlist_mutex);
mutex_destroy(&dev->filelist_mutex);
mutex_destroy(&dev->struct_mutex);
kfree(dev->unique);
@@ -859,6 +864,8 @@ void drm_dev_unregister(struct drm_device *dev)
dev->registered = false;
+ drm_client_dev_unregister(dev);
+
if (drm_core_check_feature(dev, DRIVER_MODESET))
drm_modeset_unregister_all(dev);
diff --git a/drivers/gpu/drm/drm_fb_cma_helper.c b/drivers/gpu/drm/drm_fb_cma_helper.c
index 5762a7c441e9..718c7f961d8a 100644
--- a/drivers/gpu/drm/drm_fb_cma_helper.c
+++ b/drivers/gpu/drm/drm_fb_cma_helper.c
@@ -181,7 +181,7 @@ struct drm_fbdev_cma *drm_fbdev_cma_init(struct drm_device *dev,
fb_helper = &fbdev_cma->fb_helper;
- ret = drm_client_new(dev, &fb_helper->client, "fbdev");
+ ret = drm_client_new(dev, &fb_helper->client, "fbdev", NULL);
if (ret)
goto err_free;
diff --git a/drivers/gpu/drm/drm_fb_helper.c b/drivers/gpu/drm/drm_fb_helper.c
index 0a0a577ebc3c..bea3a0cb324a 100644
--- a/drivers/gpu/drm/drm_fb_helper.c
+++ b/drivers/gpu/drm/drm_fb_helper.c
@@ -2989,8 +2989,15 @@ static void drm_fbdev_fb_destroy(struct fb_info *info)
}
drm_client_framebuffer_delete(fb_helper->buffer);
- drm_client_release(&fb_helper->client);
- kfree(fb_helper);
+ /*
+ * FIXME:
+ * Remove conditional when all CMA drivers have been moved over to using
+ * drm_fbdev_generic_setup().
+ */
+ if (fb_helper->client.funcs) {
+ drm_client_release(&fb_helper->client);
+ kfree(fb_helper);
+ }
}
static int drm_fbdev_fb_mmap(struct fb_info *info, struct vm_area_struct *vma)
diff --git a/drivers/gpu/drm/drm_file.c b/drivers/gpu/drm/drm_file.c
index 66bb403dc8ab..ffa8dc35515f 100644
--- a/drivers/gpu/drm/drm_file.c
+++ b/drivers/gpu/drm/drm_file.c
@@ -35,6 +35,7 @@
#include <linux/slab.h>
#include <linux/module.h>
+#include <drm/drm_client.h>
#include <drm/drm_file.h>
#include <drm/drmP.h>
@@ -444,6 +445,8 @@ void drm_lastclose(struct drm_device * dev)
if (drm_core_check_feature(dev, DRIVER_LEGACY))
drm_legacy_dev_reinit(dev);
+
+ drm_client_dev_restore(dev);
}
/**
diff --git a/drivers/gpu/drm/drm_probe_helper.c b/drivers/gpu/drm/drm_probe_helper.c
index 527743394150..26be57e28a9d 100644
--- a/drivers/gpu/drm/drm_probe_helper.c
+++ b/drivers/gpu/drm/drm_probe_helper.c
@@ -33,6 +33,7 @@
#include <linux/moduleparam.h>
#include <drm/drmP.h>
+#include <drm/drm_client.h>
#include <drm/drm_crtc.h>
#include <drm/drm_fourcc.h>
#include <drm/drm_crtc_helper.h>
@@ -563,6 +564,8 @@ void drm_kms_helper_hotplug_event(struct drm_device *dev)
drm_sysfs_hotplug_event(dev);
if (dev->mode_config.funcs->output_poll_changed)
dev->mode_config.funcs->output_poll_changed(dev);
+
+ drm_client_dev_hotplug(dev);
}
EXPORT_SYMBOL(drm_kms_helper_hotplug_event);
diff --git a/include/drm/drm_client.h b/include/drm/drm_client.h
index e366f95d4414..02cbb02714d8 100644
--- a/include/drm/drm_client.h
+++ b/include/drm/drm_client.h
@@ -5,10 +5,66 @@
#include <linux/types.h>
+struct drm_client_dev;
struct drm_device;
struct drm_file;
struct drm_framebuffer;
struct drm_gem_object;
+struct module;
+
+/**
+ * struct drm_client_funcs - DRM client callbacks
+ */
+struct drm_client_funcs {
+ /**
+ * @owner: The module owner
+ */
+ struct module *owner;
+
+ /**
+ * @release:
+ *
+ * Called when the reference count is dropped to zero. Users of this
+ * callback is responsible for calling drm_client_close() and freeing
+ * the client structure.
+ *
+ * This callback is optional.
+ */
+ void (*release)(struct drm_client_dev *client);
+
+ /**
+ * @unregister:
+ *
+ * Called when &drm_device is unregistered. The client should respond by
+ * releasing it's resources using drm_client_put(). If it can't do so
+ * due to resoruces being tied up, like fbdev with open file handles,
+ * it should release it's resources as soon as possible.
+ *
+ * This callback is optional.
+ */
+ void (*unregister)(struct drm_client_dev *client);
+
+ /**
+ * @restore:
+ *
+ * Called on drm_lastclose(). The first client instance in the list that
+ * returns zero gets the privilege to restore and no more clients are
+ * called. This callback is not called after @unregister has been called.
+ *
+ * This callback is optional.
+ */
+ int (*restore)(struct drm_client_dev *client);
+
+ /**
+ * @hotplug:
+ *
+ * Called on drm_kms_helper_hotplug_event().
+ * This callback is not called after @unregister has been called.
+ *
+ * This callback is optional.
+ */
+ int (*hotplug)(struct drm_client_dev *client);
+};
/**
* struct drm_client_dev - DRM client instance
@@ -24,6 +80,19 @@ struct drm_client_dev {
*/
const char *name;
+ /**
+ * @list:
+ *
+ * List of all clients of a DRM device, linked into
+ * &drm_device.clientlist. Protected by &drm_device.clientlist_mutex.
+ */
+ struct list_head list;
+
+ /**
+ * @funcs: DRM client functions (optional)
+ */
+ const struct drm_client_funcs *funcs;
+
/**
* @file: DRM file
*/
@@ -31,9 +100,13 @@ struct drm_client_dev {
};
int drm_client_new(struct drm_device *dev, struct drm_client_dev *client,
- const char *name);
+ const char *name, const struct drm_client_funcs *funcs);
void drm_client_release(struct drm_client_dev *client);
+void drm_client_dev_unregister(struct drm_device *dev);
+void drm_client_dev_hotplug(struct drm_device *dev);
+void drm_client_dev_restore(struct drm_device *dev);
+
/**
* struct drm_client_buffer - DRM client buffer
*/
diff --git a/include/drm/drm_device.h b/include/drm/drm_device.h
index 9e29976d4e98..f9c6e0e3aec7 100644
--- a/include/drm/drm_device.h
+++ b/include/drm/drm_device.h
@@ -81,6 +81,20 @@ struct drm_device {
*/
struct list_head filelist_internal;
+ /**
+ * @clientlist_mutex:
+ *
+ * Protects @clientlist access.
+ */
+ struct mutex clientlist_mutex;
+
+ /**
+ * @clientlist:
+ *
+ * List of in-kernel clients. Protected by @clientlist_mutex.
+ */
+ struct list_head clientlist;
+
/** \name Memory management */
/*@{ */
struct list_head maplist; /**< Linked list of regions */
--
2.15.1
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel
^ permalink raw reply related [flat|nested] 24+ messages in thread
* [PATCH v4 6/9] drm/debugfs: Add internal client debugfs file
2018-07-02 13:54 [PATCH v4 0/9] drm: Add generic fbdev emulation Noralf Trønnes
` (4 preceding siblings ...)
2018-07-02 13:54 ` [PATCH v4 5/9] drm/client: Add client callbacks Noralf Trønnes
@ 2018-07-02 13:54 ` Noralf Trønnes
2018-07-02 13:54 ` [PATCH v4 7/9] drm/fb-helper: Finish the generic fbdev emulation Noralf Trønnes
` (6 subsequent siblings)
12 siblings, 0 replies; 24+ messages in thread
From: Noralf Trønnes @ 2018-07-02 13:54 UTC (permalink / raw)
To: dri-devel; +Cc: intel-gfx, laurent.pinchart, david
Print the names of the internal clients currently attached.
Reviewed-by: Daniel Vetter <daniel.vetter@ffwll.ch>
Signed-off-by: Noralf Trønnes <noralf@tronnes.org>
---
drivers/gpu/drm/drm_client.c | 28 ++++++++++++++++++++++++++++
drivers/gpu/drm/drm_debugfs.c | 7 +++++++
include/drm/drm_client.h | 3 +++
3 files changed, 38 insertions(+)
diff --git a/drivers/gpu/drm/drm_client.c b/drivers/gpu/drm/drm_client.c
index f05ee98bd10c..e8d7b259ff22 100644
--- a/drivers/gpu/drm/drm_client.c
+++ b/drivers/gpu/drm/drm_client.c
@@ -375,3 +375,31 @@ void drm_client_framebuffer_delete(struct drm_client_buffer *buffer)
drm_client_buffer_delete(buffer);
}
EXPORT_SYMBOL(drm_client_framebuffer_delete);
+
+#ifdef CONFIG_DEBUG_FS
+static int drm_client_debugfs_internal_clients(struct seq_file *m, void *data)
+{
+ struct drm_info_node *node = m->private;
+ struct drm_device *dev = node->minor->dev;
+ struct drm_printer p = drm_seq_file_printer(m);
+ struct drm_client_dev *client;
+
+ mutex_lock(&dev->clientlist_mutex);
+ list_for_each_entry(client, &dev->clientlist, list)
+ drm_printf(&p, "%s\n", client->name);
+ mutex_unlock(&dev->clientlist_mutex);
+
+ return 0;
+}
+
+static const struct drm_info_list drm_client_debugfs_list[] = {
+ { "internal_clients", drm_client_debugfs_internal_clients, 0 },
+};
+
+int drm_client_debugfs_init(struct drm_minor *minor)
+{
+ return drm_debugfs_create_files(drm_client_debugfs_list,
+ ARRAY_SIZE(drm_client_debugfs_list),
+ minor->debugfs_root, minor);
+}
+#endif
diff --git a/drivers/gpu/drm/drm_debugfs.c b/drivers/gpu/drm/drm_debugfs.c
index b2482818fee8..50a20bfc07ea 100644
--- a/drivers/gpu/drm/drm_debugfs.c
+++ b/drivers/gpu/drm/drm_debugfs.c
@@ -28,6 +28,7 @@
#include <linux/slab.h>
#include <linux/export.h>
+#include <drm/drm_client.h>
#include <drm/drm_debugfs.h>
#include <drm/drm_edid.h>
#include <drm/drm_atomic.h>
@@ -164,6 +165,12 @@ int drm_debugfs_init(struct drm_minor *minor, int minor_id,
DRM_ERROR("Failed to create framebuffer debugfs file\n");
return ret;
}
+
+ ret = drm_client_debugfs_init(minor);
+ if (ret) {
+ DRM_ERROR("Failed to create client debugfs file\n");
+ return ret;
+ }
}
if (dev->driver->debugfs_init) {
diff --git a/include/drm/drm_client.h b/include/drm/drm_client.h
index 02cbb02714d8..e03ac786b0e1 100644
--- a/include/drm/drm_client.h
+++ b/include/drm/drm_client.h
@@ -10,6 +10,7 @@ struct drm_device;
struct drm_file;
struct drm_framebuffer;
struct drm_gem_object;
+struct drm_minor;
struct module;
/**
@@ -146,4 +147,6 @@ struct drm_client_buffer *
drm_client_framebuffer_create(struct drm_client_dev *client, u32 width, u32 height, u32 format);
void drm_client_framebuffer_delete(struct drm_client_buffer *buffer);
+int drm_client_debugfs_init(struct drm_minor *minor);
+
#endif
--
2.15.1
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel
^ permalink raw reply related [flat|nested] 24+ messages in thread
* [PATCH v4 7/9] drm/fb-helper: Finish the generic fbdev emulation
2018-07-02 13:54 [PATCH v4 0/9] drm: Add generic fbdev emulation Noralf Trønnes
` (5 preceding siblings ...)
2018-07-02 13:54 ` [PATCH v4 6/9] drm/debugfs: Add internal client debugfs file Noralf Trønnes
@ 2018-07-02 13:54 ` Noralf Trønnes
2018-07-02 13:54 ` [PATCH v4 8/9] drm/tinydrm: Use drm_fbdev_generic_setup() Noralf Trønnes
` (5 subsequent siblings)
12 siblings, 0 replies; 24+ messages in thread
From: Noralf Trønnes @ 2018-07-02 13:54 UTC (permalink / raw)
To: dri-devel; +Cc: intel-gfx, Noralf Trønnes, laurent.pinchart, david
This adds a drm_fbdev_generic_setup() function that sets up generic
fbdev emulation with client callbacks for restore, hotplug and
unregister.
Signed-off-by: Noralf Trønnes <noralf@tronnes.org>
---
drivers/gpu/drm/drm_fb_helper.c | 117 ++++++++++++++++++++++++++++++++++++++++
include/drm/drm_fb_helper.h | 7 +++
2 files changed, 124 insertions(+)
diff --git a/drivers/gpu/drm/drm_fb_helper.c b/drivers/gpu/drm/drm_fb_helper.c
index bea3a0cb324a..e2f0db1432aa 100644
--- a/drivers/gpu/drm/drm_fb_helper.c
+++ b/drivers/gpu/drm/drm_fb_helper.c
@@ -67,6 +67,9 @@ static DEFINE_MUTEX(kernel_fb_helper_lock);
* helper functions used by many drivers to implement the kernel mode setting
* interfaces.
*
+ * Drivers that support a dumb buffer with a virtual address and mmap support,
+ * should try out the generic fbdev emulation using drm_fbdev_generic_setup().
+ *
* Setup fbdev emulation by calling drm_fb_helper_fbdev_setup() and tear it
* down by calling drm_fb_helper_fbdev_teardown().
*
@@ -3118,6 +3121,120 @@ int drm_fb_helper_generic_probe(struct drm_fb_helper *fb_helper,
}
EXPORT_SYMBOL(drm_fb_helper_generic_probe);
+static const struct drm_fb_helper_funcs drm_fb_helper_generic_funcs = {
+ .fb_probe = drm_fb_helper_generic_probe,
+};
+
+static void drm_fbdev_client_unregister(struct drm_client_dev *client)
+{
+ struct drm_fb_helper *fb_helper = drm_fb_helper_from_client(client);
+
+ if (fb_helper->fbdev) {
+ drm_fb_helper_unregister_fbi(fb_helper);
+ /* drm_fbdev_fb_destroy() takes care of cleanup */
+ return;
+ }
+
+ /* Did drm_fb_helper_fbdev_setup() run? */
+ if (fb_helper->dev)
+ drm_fb_helper_fini(fb_helper);
+
+ drm_client_release(client);
+ kfree(fb_helper);
+}
+
+static int drm_fbdev_client_restore(struct drm_client_dev *client)
+{
+ struct drm_fb_helper *fb_helper = drm_fb_helper_from_client(client);
+
+ drm_fb_helper_restore_fbdev_mode_unlocked(fb_helper);
+
+ return 0;
+}
+
+static int drm_fbdev_client_hotplug(struct drm_client_dev *client)
+{
+ struct drm_fb_helper *fb_helper = drm_fb_helper_from_client(client);
+ struct drm_device *dev = client->dev;
+ int ret;
+
+ /* If drm_fb_helper_fbdev_setup() failed, we only try once */
+ if (!fb_helper->dev && fb_helper->funcs)
+ return 0;
+
+ if (dev->fb_helper)
+ return drm_fb_helper_hotplug_event(dev->fb_helper);
+
+ if (!dev->mode_config.num_connector)
+ return 0;
+
+ ret = drm_fb_helper_fbdev_setup(dev, fb_helper, &drm_fb_helper_generic_funcs,
+ fb_helper->preferred_bpp, 0);
+ if (ret) {
+ fb_helper->dev = NULL;
+ fb_helper->fbdev = NULL;
+ return ret;
+ }
+
+ return 0;
+}
+
+static const struct drm_client_funcs drm_fbdev_client_funcs = {
+ .owner = THIS_MODULE,
+ .unregister = drm_fbdev_client_unregister,
+ .restore = drm_fbdev_client_restore,
+ .hotplug = drm_fbdev_client_hotplug,
+};
+
+/**
+ * drm_fb_helper_generic_fbdev_setup() - Setup generic fbdev emulation
+ * @dev: DRM device
+ * @preferred_bpp: Preferred bits per pixel for the device.
+ * @dev->mode_config.preferred_depth is used if this is zero.
+ *
+ * This function sets up generic fbdev emulation for drivers that supports
+ * dumb buffers with a virtual address and that can be mmap'ed.
+ *
+ * Restore, hotplug events and teardown are all taken care of. Drivers that do
+ * suspend/resume need to call drm_fb_helper_set_suspend_unlocked() themselves.
+ * Simple drivers might use drm_mode_config_helper_suspend().
+ *
+ * Drivers that set the dirty callback on their framebuffer will get a shadow
+ * fbdev buffer that is blitted onto the real buffer. This is done in order to
+ * make deferred I/O work with all kinds of buffers.
+ *
+ * This function is safe to call even when there are no connectors present.
+ * Setup will be retried on the next hotplug event.
+ *
+ * Returns:
+ * Zero on success or negative error code on failure.
+ */
+int drm_fbdev_generic_setup(struct drm_device *dev, unsigned int preferred_bpp)
+{
+ struct drm_fb_helper *fb_helper;
+ int ret;
+
+ if (!drm_fbdev_emulation)
+ return 0;
+
+ fb_helper = kzalloc(sizeof(*fb_helper), GFP_KERNEL);
+ if (!fb_helper)
+ return -ENOMEM;
+
+ ret = drm_client_new(dev, &fb_helper->client, "fbdev", &drm_fbdev_client_funcs);
+ if (ret) {
+ kfree(fb_helper);
+ return ret;
+ }
+
+ fb_helper->preferred_bpp = preferred_bpp;
+
+ drm_fbdev_client_hotplug(&fb_helper->client);
+
+ return 0;
+}
+EXPORT_SYMBOL(drm_fbdev_generic_setup);
+
/* The Kconfig DRM_KMS_HELPER selects FRAMEBUFFER_CONSOLE (if !EXPERT)
* but the module doesn't depend on any fb console symbols. At least
* attempt to load fbcon to avoid leaving the system without a usable console.
diff --git a/include/drm/drm_fb_helper.h b/include/drm/drm_fb_helper.h
index c134bbcfd2e9..5db08c8f1d25 100644
--- a/include/drm/drm_fb_helper.h
+++ b/include/drm/drm_fb_helper.h
@@ -354,6 +354,7 @@ void drm_fb_helper_output_poll_changed(struct drm_device *dev);
int drm_fb_helper_generic_probe(struct drm_fb_helper *fb_helper,
struct drm_fb_helper_surface_size *sizes);
+int drm_fbdev_generic_setup(struct drm_device *dev, unsigned int preferred_bpp);
#else
static inline void drm_fb_helper_prepare(struct drm_device *dev,
struct drm_fb_helper *helper,
@@ -595,6 +596,12 @@ drm_fb_helper_generic_probe(struct drm_fb_helper *fb_helper,
return 0;
}
+static inline int
+drm_fbdev_generic_setup(struct drm_device *dev, unsigned int preferred_bpp)
+{
+ return 0;
+}
+
#endif
static inline int
--
2.15.1
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx
^ permalink raw reply related [flat|nested] 24+ messages in thread
* [PATCH v4 8/9] drm/tinydrm: Use drm_fbdev_generic_setup()
2018-07-02 13:54 [PATCH v4 0/9] drm: Add generic fbdev emulation Noralf Trønnes
` (6 preceding siblings ...)
2018-07-02 13:54 ` [PATCH v4 7/9] drm/fb-helper: Finish the generic fbdev emulation Noralf Trønnes
@ 2018-07-02 13:54 ` Noralf Trønnes
2018-07-02 15:52 ` David Lechner
2018-07-02 13:54 ` [PATCH v4 9/9] drm/cma-helper: Remove drm_fb_cma_fbdev_init_with_funcs() Noralf Trønnes
` (4 subsequent siblings)
12 siblings, 1 reply; 24+ messages in thread
From: Noralf Trønnes @ 2018-07-02 13:54 UTC (permalink / raw)
To: dri-devel; +Cc: intel-gfx, laurent.pinchart, david
Make full use of the generic fbdev client.
Cc: David Lechner <david@lechnology.com>
Signed-off-by: Noralf Trønnes <noralf@tronnes.org>
---
drivers/gpu/drm/tinydrm/core/tinydrm-core.c | 3 +--
drivers/gpu/drm/tinydrm/ili9225.c | 1 -
drivers/gpu/drm/tinydrm/ili9341.c | 1 -
drivers/gpu/drm/tinydrm/mi0283qt.c | 1 -
drivers/gpu/drm/tinydrm/st7586.c | 1 -
drivers/gpu/drm/tinydrm/st7735r.c | 1 -
6 files changed, 1 insertion(+), 7 deletions(-)
diff --git a/drivers/gpu/drm/tinydrm/core/tinydrm-core.c b/drivers/gpu/drm/tinydrm/core/tinydrm-core.c
index 24a33bf862fa..19c7f70adfa5 100644
--- a/drivers/gpu/drm/tinydrm/core/tinydrm-core.c
+++ b/drivers/gpu/drm/tinydrm/core/tinydrm-core.c
@@ -204,7 +204,7 @@ static int tinydrm_register(struct tinydrm_device *tdev)
if (ret)
return ret;
- ret = drm_fb_cma_fbdev_init_with_funcs(drm, 0, 0, tdev->fb_funcs);
+ ret = drm_fbdev_generic_setup(drm, 0);
if (ret)
DRM_ERROR("Failed to initialize fbdev: %d\n", ret);
@@ -214,7 +214,6 @@ static int tinydrm_register(struct tinydrm_device *tdev)
static void tinydrm_unregister(struct tinydrm_device *tdev)
{
drm_atomic_helper_shutdown(tdev->drm);
- drm_fb_cma_fbdev_fini(tdev->drm);
drm_dev_unregister(tdev->drm);
}
diff --git a/drivers/gpu/drm/tinydrm/ili9225.c b/drivers/gpu/drm/tinydrm/ili9225.c
index 841c69aba059..455fefe012f5 100644
--- a/drivers/gpu/drm/tinydrm/ili9225.c
+++ b/drivers/gpu/drm/tinydrm/ili9225.c
@@ -368,7 +368,6 @@ static struct drm_driver ili9225_driver = {
DRIVER_ATOMIC,
.fops = &ili9225_fops,
TINYDRM_GEM_DRIVER_OPS,
- .lastclose = drm_fb_helper_lastclose,
.name = "ili9225",
.desc = "Ilitek ILI9225",
.date = "20171106",
diff --git a/drivers/gpu/drm/tinydrm/ili9341.c b/drivers/gpu/drm/tinydrm/ili9341.c
index 8864dcde6edc..6701037749a7 100644
--- a/drivers/gpu/drm/tinydrm/ili9341.c
+++ b/drivers/gpu/drm/tinydrm/ili9341.c
@@ -145,7 +145,6 @@ static struct drm_driver ili9341_driver = {
.driver_features = DRIVER_GEM | DRIVER_MODESET | DRIVER_PRIME | DRIVER_ATOMIC,
.fops = &ili9341_fops,
TINYDRM_GEM_DRIVER_OPS,
- .lastclose = drm_fb_helper_lastclose,
.debugfs_init = mipi_dbi_debugfs_init,
.name = "ili9341",
.desc = "Ilitek ILI9341",
diff --git a/drivers/gpu/drm/tinydrm/mi0283qt.c b/drivers/gpu/drm/tinydrm/mi0283qt.c
index 015d03f2acba..d7bb4c5e6657 100644
--- a/drivers/gpu/drm/tinydrm/mi0283qt.c
+++ b/drivers/gpu/drm/tinydrm/mi0283qt.c
@@ -154,7 +154,6 @@ static struct drm_driver mi0283qt_driver = {
DRIVER_ATOMIC,
.fops = &mi0283qt_fops,
TINYDRM_GEM_DRIVER_OPS,
- .lastclose = drm_fb_helper_lastclose,
.debugfs_init = mipi_dbi_debugfs_init,
.name = "mi0283qt",
.desc = "Multi-Inno MI0283QT",
diff --git a/drivers/gpu/drm/tinydrm/st7586.c b/drivers/gpu/drm/tinydrm/st7586.c
index 5c29e3803ecb..2fcbc3067d71 100644
--- a/drivers/gpu/drm/tinydrm/st7586.c
+++ b/drivers/gpu/drm/tinydrm/st7586.c
@@ -304,7 +304,6 @@ static struct drm_driver st7586_driver = {
DRIVER_ATOMIC,
.fops = &st7586_fops,
TINYDRM_GEM_DRIVER_OPS,
- .lastclose = drm_fb_helper_lastclose,
.debugfs_init = mipi_dbi_debugfs_init,
.name = "st7586",
.desc = "Sitronix ST7586",
diff --git a/drivers/gpu/drm/tinydrm/st7735r.c b/drivers/gpu/drm/tinydrm/st7735r.c
index 6c7b15c9da4f..3081bc57c116 100644
--- a/drivers/gpu/drm/tinydrm/st7735r.c
+++ b/drivers/gpu/drm/tinydrm/st7735r.c
@@ -120,7 +120,6 @@ static struct drm_driver st7735r_driver = {
DRIVER_ATOMIC,
.fops = &st7735r_fops,
TINYDRM_GEM_DRIVER_OPS,
- .lastclose = drm_fb_helper_lastclose,
.debugfs_init = mipi_dbi_debugfs_init,
.name = "st7735r",
.desc = "Sitronix ST7735R",
--
2.15.1
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel
^ permalink raw reply related [flat|nested] 24+ messages in thread
* [PATCH v4 9/9] drm/cma-helper: Remove drm_fb_cma_fbdev_init_with_funcs()
2018-07-02 13:54 [PATCH v4 0/9] drm: Add generic fbdev emulation Noralf Trønnes
` (7 preceding siblings ...)
2018-07-02 13:54 ` [PATCH v4 8/9] drm/tinydrm: Use drm_fbdev_generic_setup() Noralf Trønnes
@ 2018-07-02 13:54 ` Noralf Trønnes
2018-07-02 15:57 ` David Lechner
2018-07-02 14:13 ` ✗ Fi.CI.CHECKPATCH: warning for drm: Add generic fbdev emulation Patchwork
` (3 subsequent siblings)
12 siblings, 1 reply; 24+ messages in thread
From: Noralf Trønnes @ 2018-07-02 13:54 UTC (permalink / raw)
To: dri-devel; +Cc: intel-gfx, laurent.pinchart, david
Remove drm_fb_cma_fbdev_init_with_funcs(), its only user tinydrm has
moved to drm_fbdev_generic_setup().
Cc: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Signed-off-by: Noralf Trønnes <noralf@tronnes.org>
---
drivers/gpu/drm/drm_fb_cma_helper.c | 21 ---------------------
include/drm/drm_fb_cma_helper.h | 3 ---
2 files changed, 24 deletions(-)
diff --git a/drivers/gpu/drm/drm_fb_cma_helper.c b/drivers/gpu/drm/drm_fb_cma_helper.c
index 718c7f961d8a..9da36a6271d3 100644
--- a/drivers/gpu/drm/drm_fb_cma_helper.c
+++ b/drivers/gpu/drm/drm_fb_cma_helper.c
@@ -99,27 +99,6 @@ dma_addr_t drm_fb_cma_get_gem_addr(struct drm_framebuffer *fb,
}
EXPORT_SYMBOL_GPL(drm_fb_cma_get_gem_addr);
-/**
- * drm_fb_cma_fbdev_init_with_funcs() - Allocate and initialize fbdev emulation
- * @dev: DRM device
- * @preferred_bpp: Preferred bits per pixel for the device.
- * @dev->mode_config.preferred_depth is used if this is zero.
- * @max_conn_count: Maximum number of connectors.
- * @dev->mode_config.num_connector is used if this is zero.
- * @funcs: Framebuffer functions, in particular a custom dirty() callback.
- * Can be NULL.
- *
- * Returns:
- * Zero on success or negative error code on failure.
- */
-int drm_fb_cma_fbdev_init_with_funcs(struct drm_device *dev,
- unsigned int preferred_bpp, unsigned int max_conn_count,
- const struct drm_framebuffer_funcs *funcs)
-{
- return drm_fb_cma_fbdev_init(dev, preferred_bpp, max_conn_count);
-}
-EXPORT_SYMBOL_GPL(drm_fb_cma_fbdev_init_with_funcs);
-
/**
* drm_fb_cma_fbdev_init() - Allocate and initialize fbdev emulation
* @dev: DRM device
diff --git a/include/drm/drm_fb_cma_helper.h b/include/drm/drm_fb_cma_helper.h
index a0546c3451f9..96e26e3b9a0c 100644
--- a/include/drm/drm_fb_cma_helper.h
+++ b/include/drm/drm_fb_cma_helper.h
@@ -16,9 +16,6 @@ struct drm_mode_fb_cmd2;
struct drm_plane;
struct drm_plane_state;
-int drm_fb_cma_fbdev_init_with_funcs(struct drm_device *dev,
- unsigned int preferred_bpp, unsigned int max_conn_count,
- const struct drm_framebuffer_funcs *funcs);
int drm_fb_cma_fbdev_init(struct drm_device *dev, unsigned int preferred_bpp,
unsigned int max_conn_count);
void drm_fb_cma_fbdev_fini(struct drm_device *dev);
--
2.15.1
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel
^ permalink raw reply related [flat|nested] 24+ messages in thread
* ✗ Fi.CI.CHECKPATCH: warning for drm: Add generic fbdev emulation
2018-07-02 13:54 [PATCH v4 0/9] drm: Add generic fbdev emulation Noralf Trønnes
` (8 preceding siblings ...)
2018-07-02 13:54 ` [PATCH v4 9/9] drm/cma-helper: Remove drm_fb_cma_fbdev_init_with_funcs() Noralf Trønnes
@ 2018-07-02 14:13 ` Patchwork
2018-07-02 14:17 ` ✗ Fi.CI.SPARSE: " Patchwork
` (2 subsequent siblings)
12 siblings, 0 replies; 24+ messages in thread
From: Patchwork @ 2018-07-02 14:13 UTC (permalink / raw)
To: Noralf Trønnes; +Cc: intel-gfx
== Series Details ==
Series: drm: Add generic fbdev emulation
URL : https://patchwork.freedesktop.org/series/45777/
State : warning
== Summary ==
$ dim checkpatch origin/drm-tip
44cb6f91d1db drm: Begin an API for in-kernel clients
-:26: WARNING:FILE_PATH_CHANGES: added, moved or deleted file(s), does MAINTAINERS need updating?
#26:
new file mode 100644
-:31: WARNING:SPDX_LICENSE_TAG: Missing or malformed SPDX-License-Identifier tag in line 1
#31: FILE: Documentation/gpu/drm-client.rst:1:
+=================
total: 0 errors, 2 warnings, 0 checks, 412 lines checked
5c343c927656 drm/fb-helper: Add generic fbdev emulation .fb_probe function
8aa54780abbc drm/pl111: Set .gem_prime_vmap and .gem_prime_mmap
3f78d617c951 drm/cma-helper: Use the generic fbdev emulation
-:359: CHECK:PARENTHESIS_ALIGNMENT: Alignment should match open parenthesis
#359: FILE: drivers/gpu/drm/drm_fb_cma_helper.c:172:
+struct drm_fbdev_cma *drm_fbdev_cma_init(struct drm_device *dev,
+ unsigned int preferred_bpp, unsigned int max_conn_count)
total: 0 errors, 0 warnings, 1 checks, 425 lines checked
03ee165264d0 drm/client: Add client callbacks
10fdb59e4e4a drm/debugfs: Add internal client debugfs file
5d0b6c2e1752 drm/fb-helper: Finish the generic fbdev emulation
1decaf928232 drm/tinydrm: Use drm_fbdev_generic_setup()
8c681fb6ac51 drm/cma-helper: Remove drm_fb_cma_fbdev_init_with_funcs()
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx
^ permalink raw reply [flat|nested] 24+ messages in thread
* ✗ Fi.CI.SPARSE: warning for drm: Add generic fbdev emulation
2018-07-02 13:54 [PATCH v4 0/9] drm: Add generic fbdev emulation Noralf Trønnes
` (9 preceding siblings ...)
2018-07-02 14:13 ` ✗ Fi.CI.CHECKPATCH: warning for drm: Add generic fbdev emulation Patchwork
@ 2018-07-02 14:17 ` Patchwork
2018-07-02 14:28 ` ✓ Fi.CI.BAT: success " Patchwork
2018-07-02 15:40 ` ✓ Fi.CI.IGT: " Patchwork
12 siblings, 0 replies; 24+ messages in thread
From: Patchwork @ 2018-07-02 14:17 UTC (permalink / raw)
To: Noralf Trønnes; +Cc: intel-gfx
== Series Details ==
Series: drm: Add generic fbdev emulation
URL : https://patchwork.freedesktop.org/series/45777/
State : warning
== Summary ==
$ dim sparse origin/drm-tip
Commit: drm: Begin an API for in-kernel clients
Okay!
Commit: drm/fb-helper: Add generic fbdev emulation .fb_probe function
+drivers/gpu/drm/drm_fb_helper.c:1006:20: warning: expression using sizeof(void)
+drivers/gpu/drm/drm_fb_helper.c:1006:20: warning: expression using sizeof(void)
+drivers/gpu/drm/drm_fb_helper.c:1007:20: warning: expression using sizeof(void)
+drivers/gpu/drm/drm_fb_helper.c:1007:20: warning: expression using sizeof(void)
+drivers/gpu/drm/drm_fb_helper.c:1008:20: warning: expression using sizeof(void)
+drivers/gpu/drm/drm_fb_helper.c:1008:20: warning: expression using sizeof(void)
+drivers/gpu/drm/drm_fb_helper.c:1009:20: warning: expression using sizeof(void)
+drivers/gpu/drm/drm_fb_helper.c:1009:20: warning: expression using sizeof(void)
-drivers/gpu/drm/drm_fb_helper.c:1006:20: warning: expression using sizeof(void)
-drivers/gpu/drm/drm_fb_helper.c:1006:20: warning: expression using sizeof(void)
-drivers/gpu/drm/drm_fb_helper.c:1007:20: warning: expression using sizeof(void)
-drivers/gpu/drm/drm_fb_helper.c:1007:20: warning: expression using sizeof(void)
-drivers/gpu/drm/drm_fb_helper.c:1008:20: warning: expression using sizeof(void)
-drivers/gpu/drm/drm_fb_helper.c:1008:20: warning: expression using sizeof(void)
-drivers/gpu/drm/drm_fb_helper.c:1009:20: warning: expression using sizeof(void)
-drivers/gpu/drm/drm_fb_helper.c:1009:20: warning: expression using sizeof(void)
Commit: drm/pl111: Set .gem_prime_vmap and .gem_prime_mmap
Okay!
Commit: drm/cma-helper: Use the generic fbdev emulation
Okay!
Commit: drm/client: Add client callbacks
Okay!
Commit: drm/debugfs: Add internal client debugfs file
Okay!
Commit: drm/fb-helper: Finish the generic fbdev emulation
Okay!
Commit: drm/tinydrm: Use drm_fbdev_generic_setup()
Okay!
Commit: drm/cma-helper: Remove drm_fb_cma_fbdev_init_with_funcs()
Okay!
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx
^ permalink raw reply [flat|nested] 24+ messages in thread
* ✓ Fi.CI.BAT: success for drm: Add generic fbdev emulation
2018-07-02 13:54 [PATCH v4 0/9] drm: Add generic fbdev emulation Noralf Trønnes
` (10 preceding siblings ...)
2018-07-02 14:17 ` ✗ Fi.CI.SPARSE: " Patchwork
@ 2018-07-02 14:28 ` Patchwork
2018-07-02 15:40 ` ✓ Fi.CI.IGT: " Patchwork
12 siblings, 0 replies; 24+ messages in thread
From: Patchwork @ 2018-07-02 14:28 UTC (permalink / raw)
To: Noralf Trønnes; +Cc: intel-gfx
== Series Details ==
Series: drm: Add generic fbdev emulation
URL : https://patchwork.freedesktop.org/series/45777/
State : success
== Summary ==
= CI Bug Log - changes from CI_DRM_4412 -> Patchwork_9497 =
== Summary - SUCCESS ==
No regressions found.
External URL: https://patchwork.freedesktop.org/api/1.0/series/45777/revisions/1/mbox/
== Known issues ==
Here are the changes found in Patchwork_9497 that come from known issues:
=== IGT changes ===
==== Possible fixes ====
igt@gem_exec_suspend@basic-s4-devices:
fi-kbl-7500u: DMESG-WARN (fdo#105128) -> PASS
igt@kms_pipe_crc_basic@suspend-read-crc-pipe-b:
fi-snb-2520m: INCOMPLETE (fdo#103713) -> PASS
igt@prime_vgem@basic-fence-flip:
fi-ilk-650: FAIL (fdo#104008) -> PASS
fdo#103713 https://bugs.freedesktop.org/show_bug.cgi?id=103713
fdo#104008 https://bugs.freedesktop.org/show_bug.cgi?id=104008
fdo#105128 https://bugs.freedesktop.org/show_bug.cgi?id=105128
== Participating hosts (43 -> 40) ==
Additional (1): fi-byt-j1900
Missing (4): fi-ctg-p8600 fi-ilk-m540 fi-bsw-cyan fi-hsw-4200u
== Build changes ==
* Linux: CI_DRM_4412 -> Patchwork_9497
CI_DRM_4412: 3cd46a79b208e82ba0b2da4282e59312a79d29cc @ git://anongit.freedesktop.org/gfx-ci/linux
IGT_4532: 840d12e2f050b784552197403d6575a57b6e896d @ git://anongit.freedesktop.org/xorg/app/intel-gpu-tools
Patchwork_9497: 8c681fb6ac510d791eeaee34a1fdc3508c79067c @ git://anongit.freedesktop.org/gfx-ci/linux
== Linux commits ==
8c681fb6ac51 drm/cma-helper: Remove drm_fb_cma_fbdev_init_with_funcs()
1decaf928232 drm/tinydrm: Use drm_fbdev_generic_setup()
5d0b6c2e1752 drm/fb-helper: Finish the generic fbdev emulation
10fdb59e4e4a drm/debugfs: Add internal client debugfs file
03ee165264d0 drm/client: Add client callbacks
3f78d617c951 drm/cma-helper: Use the generic fbdev emulation
8aa54780abbc drm/pl111: Set .gem_prime_vmap and .gem_prime_mmap
5c343c927656 drm/fb-helper: Add generic fbdev emulation .fb_probe function
44cb6f91d1db drm: Begin an API for in-kernel clients
== Logs ==
For more details see: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_9497/issues.html
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx
^ permalink raw reply [flat|nested] 24+ messages in thread
* ✓ Fi.CI.IGT: success for drm: Add generic fbdev emulation
2018-07-02 13:54 [PATCH v4 0/9] drm: Add generic fbdev emulation Noralf Trønnes
` (11 preceding siblings ...)
2018-07-02 14:28 ` ✓ Fi.CI.BAT: success " Patchwork
@ 2018-07-02 15:40 ` Patchwork
12 siblings, 0 replies; 24+ messages in thread
From: Patchwork @ 2018-07-02 15:40 UTC (permalink / raw)
To: Noralf Trønnes; +Cc: intel-gfx
== Series Details ==
Series: drm: Add generic fbdev emulation
URL : https://patchwork.freedesktop.org/series/45777/
State : success
== Summary ==
= CI Bug Log - changes from CI_DRM_4412_full -> Patchwork_9497_full =
== Summary - WARNING ==
Minor unknown changes coming with Patchwork_9497_full need to be verified
manually.
If you think the reported changes have nothing to do with the changes
introduced in Patchwork_9497_full, please notify your bug team to allow them
to document this new failure mode, which will reduce false positives in CI.
== Possible new issues ==
Here are the unknown changes that may have been introduced in Patchwork_9497_full:
=== IGT changes ===
==== Warnings ====
igt@gem_exec_schedule@deep-vebox:
shard-kbl: PASS -> SKIP
== Known issues ==
Here are the changes found in Patchwork_9497_full that come from known issues:
=== IGT changes ===
==== Issues hit ====
igt@gem_exec_schedule@pi-ringfull-render:
shard-kbl: NOTRUN -> FAIL (fdo#103158)
igt@gem_tiled_fence_blits@normal:
shard-snb: NOTRUN -> INCOMPLETE (fdo#105411)
igt@kms_flip_tiling@flip-to-y-tiled:
shard-glk: PASS -> FAIL (fdo#104724, fdo#103822)
igt@kms_flip_tiling@flip-x-tiled:
shard-glk: PASS -> FAIL (fdo#104724)
igt@kms_setmode@basic:
shard-kbl: PASS -> FAIL (fdo#99912)
==== Possible fixes ====
igt@drv_suspend@shrink:
shard-glk: FAIL (fdo#106886) -> PASS
igt@kms_flip@2x-flip-vs-expired-vblank-interruptible:
shard-glk: FAIL (fdo#105189) -> PASS
igt@kms_flip@flip-vs-expired-vblank:
shard-glk: FAIL (fdo#102887, fdo#105363) -> PASS
igt@kms_flip_tiling@flip-y-tiled:
shard-glk: FAIL (fdo#104724) -> PASS
igt@perf_pmu@busy-idle-no-semaphores-vecs0:
shard-snb: INCOMPLETE (fdo#105411) -> SKIP
==== Warnings ====
igt@drv_selftest@live_gtt:
shard-glk: INCOMPLETE (fdo#103359, k.org#198133) -> FAIL (fdo#105347)
fdo#102887 https://bugs.freedesktop.org/show_bug.cgi?id=102887
fdo#103158 https://bugs.freedesktop.org/show_bug.cgi?id=103158
fdo#103359 https://bugs.freedesktop.org/show_bug.cgi?id=103359
fdo#103822 https://bugs.freedesktop.org/show_bug.cgi?id=103822
fdo#104724 https://bugs.freedesktop.org/show_bug.cgi?id=104724
fdo#105189 https://bugs.freedesktop.org/show_bug.cgi?id=105189
fdo#105347 https://bugs.freedesktop.org/show_bug.cgi?id=105347
fdo#105363 https://bugs.freedesktop.org/show_bug.cgi?id=105363
fdo#105411 https://bugs.freedesktop.org/show_bug.cgi?id=105411
fdo#106886 https://bugs.freedesktop.org/show_bug.cgi?id=106886
fdo#99912 https://bugs.freedesktop.org/show_bug.cgi?id=99912
k.org#198133 https://bugzilla.kernel.org/show_bug.cgi?id=198133
== Participating hosts (5 -> 5) ==
No changes in participating hosts
== Build changes ==
* Linux: CI_DRM_4412 -> Patchwork_9497
CI_DRM_4412: 3cd46a79b208e82ba0b2da4282e59312a79d29cc @ git://anongit.freedesktop.org/gfx-ci/linux
IGT_4532: 840d12e2f050b784552197403d6575a57b6e896d @ git://anongit.freedesktop.org/xorg/app/intel-gpu-tools
Patchwork_9497: 8c681fb6ac510d791eeaee34a1fdc3508c79067c @ git://anongit.freedesktop.org/gfx-ci/linux
piglit_4509: fdc5a4ca11124ab8413c7988896eec4c97336694 @ git://anongit.freedesktop.org/piglit
== Logs ==
For more details see: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_9497/shards.html
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx
^ permalink raw reply [flat|nested] 24+ messages in thread
* Re: [PATCH v4 8/9] drm/tinydrm: Use drm_fbdev_generic_setup()
2018-07-02 13:54 ` [PATCH v4 8/9] drm/tinydrm: Use drm_fbdev_generic_setup() Noralf Trønnes
@ 2018-07-02 15:52 ` David Lechner
0 siblings, 0 replies; 24+ messages in thread
From: David Lechner @ 2018-07-02 15:52 UTC (permalink / raw)
To: Noralf Trønnes, dri-devel; +Cc: intel-gfx, laurent.pinchart
On 07/02/2018 08:54 AM, Noralf Trønnes wrote:
> Make full use of the generic fbdev client.
>
> Cc: David Lechner <david@lechnology.com>
> Signed-off-by: Noralf Trønnes <noralf@tronnes.org>
> ---
Reviewed-by: David Lechner <david@lechnology.com>
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel
^ permalink raw reply [flat|nested] 24+ messages in thread
* Re: [PATCH v4 9/9] drm/cma-helper: Remove drm_fb_cma_fbdev_init_with_funcs()
2018-07-02 13:54 ` [PATCH v4 9/9] drm/cma-helper: Remove drm_fb_cma_fbdev_init_with_funcs() Noralf Trønnes
@ 2018-07-02 15:57 ` David Lechner
0 siblings, 0 replies; 24+ messages in thread
From: David Lechner @ 2018-07-02 15:57 UTC (permalink / raw)
To: Noralf Trønnes, dri-devel; +Cc: intel-gfx, laurent.pinchart
On 07/02/2018 08:54 AM, Noralf Trønnes wrote:
> Remove drm_fb_cma_fbdev_init_with_funcs(), its only user tinydrm has
> moved to drm_fbdev_generic_setup().
>
> Cc: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> Signed-off-by: Noralf Trønnes <noralf@tronnes.org>
> ---
Reviewed-by: David Lechner <david@lechnology.com>
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel
^ permalink raw reply [flat|nested] 24+ messages in thread
* Re: [PATCH v4 1/9] drm: Begin an API for in-kernel clients
2018-07-02 13:54 ` [PATCH v4 1/9] drm: Begin an API for in-kernel clients Noralf Trønnes
@ 2018-07-03 7:43 ` Daniel Vetter
0 siblings, 0 replies; 24+ messages in thread
From: Daniel Vetter @ 2018-07-03 7:43 UTC (permalink / raw)
To: Noralf Trønnes; +Cc: intel-gfx, laurent.pinchart, dri-devel, david
On Mon, Jul 02, 2018 at 03:54:25PM +0200, Noralf Trønnes wrote:
> This the beginning of an API for in-kernel clients.
> First out is a way to get a framebuffer backed by a dumb buffer.
>
> Only GEM drivers are supported.
> The original idea of using an exported dma-buf was dropped because it
> also creates an anonomous file descriptor which doesn't work when the
> buffer is created from a kernel thread. The easy way out is to use
> drm_driver.gem_prime_vmap to get the virtual address, which requires a
> GEM object. This excludes the vmwgfx driver which is the only non-GEM
> driver apart from the legacy ones. A solution for vmwgfx will have to be
> worked out later if it wants to support the client API which it probably
> will when we have a bootsplash client.
>
> Signed-off-by: Noralf Trønnes <noralf@tronnes.org>
> Reviewed-by: Daniel Vetter <daniel.vetter@ffwll.ch>
> ---
> Documentation/gpu/drm-client.rst | 12 ++
> Documentation/gpu/index.rst | 1 +
> drivers/gpu/drm/Makefile | 2 +-
> drivers/gpu/drm/drm_client.c | 289 +++++++++++++++++++++++++++++++++++++++
> drivers/gpu/drm/drm_drv.c | 1 +
> include/drm/drm_client.h | 76 ++++++++++
> include/drm/drm_device.h | 7 +
> 7 files changed, 387 insertions(+), 1 deletion(-)
> create mode 100644 Documentation/gpu/drm-client.rst
> create mode 100644 drivers/gpu/drm/drm_client.c
> create mode 100644 include/drm/drm_client.h
>
> diff --git a/Documentation/gpu/drm-client.rst b/Documentation/gpu/drm-client.rst
> new file mode 100644
> index 000000000000..7e672063e7eb
> --- /dev/null
> +++ b/Documentation/gpu/drm-client.rst
> @@ -0,0 +1,12 @@
> +=================
> +Kernel clients
> +=================
> +
> +.. kernel-doc:: drivers/gpu/drm/drm_client.c
> + :doc: overview
> +
> +.. kernel-doc:: include/drm/drm_client.h
> + :internal:
> +
> +.. kernel-doc:: drivers/gpu/drm/drm_client.c
> + :export:
> diff --git a/Documentation/gpu/index.rst b/Documentation/gpu/index.rst
> index 00288f34c5a6..1fcf8e851e15 100644
> --- a/Documentation/gpu/index.rst
> +++ b/Documentation/gpu/index.rst
> @@ -10,6 +10,7 @@ Linux GPU Driver Developer's Guide
> drm-kms
> drm-kms-helpers
> drm-uapi
> + drm-client
> drivers
> vga-switcheroo
> vgaarbiter
> diff --git a/drivers/gpu/drm/Makefile b/drivers/gpu/drm/Makefile
> index 69c13517ea3a..d6657a61d037 100644
> --- a/drivers/gpu/drm/Makefile
> +++ b/drivers/gpu/drm/Makefile
> @@ -18,7 +18,7 @@ drm-y := drm_auth.o drm_bufs.o drm_cache.o \
> drm_encoder.o drm_mode_object.o drm_property.o \
> drm_plane.o drm_color_mgmt.o drm_print.o \
> drm_dumb_buffers.o drm_mode_config.o drm_vblank.o \
> - drm_syncobj.o drm_lease.o drm_writeback.o
> + drm_syncobj.o drm_lease.o drm_writeback.o drm_client.o
>
> drm-$(CONFIG_DRM_LIB_RANDOM) += lib/drm_random.o
> drm-$(CONFIG_DRM_VM) += drm_vm.o
> diff --git a/drivers/gpu/drm/drm_client.c b/drivers/gpu/drm/drm_client.c
> new file mode 100644
> index 000000000000..9c9b8ac7aea3
> --- /dev/null
> +++ b/drivers/gpu/drm/drm_client.c
> @@ -0,0 +1,289 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * Copyright 2018 Noralf Trønnes
> + */
> +
> +#include <linux/list.h>
> +#include <linux/mutex.h>
> +#include <linux/seq_file.h>
> +#include <linux/slab.h>
> +
> +#include <drm/drm_client.h>
> +#include <drm/drm_debugfs.h>
> +#include <drm/drm_device.h>
> +#include <drm/drm_drv.h>
> +#include <drm/drm_file.h>
> +#include <drm/drm_fourcc.h>
> +#include <drm/drm_gem.h>
> +#include <drm/drm_mode.h>
> +#include <drm/drm_print.h>
> +#include <drm/drmP.h>
> +
> +#include "drm_crtc_internal.h"
> +#include "drm_internal.h"
> +
> +/**
> + * DOC: overview
> + *
> + * This library provides support for clients running in the kernel like fbdev and bootsplash.
> + * Currently it's only partially implemented, just enough to support fbdev.
> + *
> + * GEM drivers which provide a GEM based dumb buffer with a virtual address are supported.
> + */
> +
> +static int drm_client_open(struct drm_client_dev *client)
> +{
> + struct drm_device *dev = client->dev;
> + struct drm_file *file;
> +
> + file = drm_file_alloc(dev->primary);
> + if (IS_ERR(file))
> + return PTR_ERR(file);
> +
> + mutex_lock(&dev->filelist_mutex);
> + list_add(&file->lhead, &dev->filelist_internal);
> + mutex_unlock(&dev->filelist_mutex);
> +
> + client->file = file;
> +
> + return 0;
> +}
> +
> +static void drm_client_close(struct drm_client_dev *client)
> +{
> + struct drm_device *dev = client->dev;
> +
> + mutex_lock(&dev->filelist_mutex);
> + list_del(&client->file->lhead);
> + mutex_unlock(&dev->filelist_mutex);
> +
> + drm_file_free(client->file);
> +}
> +EXPORT_SYMBOL(drm_client_close);
> +
> +/**
> + * drm_client_new - Create a DRM client
> + * @dev: DRM device
> + * @client: DRM client
> + * @name: Client name
> + *
> + * Use drm_client_put() to free the client.
s/_put/_release/ ... spotted while reviewing the 2nd client library patch.
-Daniel
> + *
> + * Returns:
> + * Zero on success or negative error code on failure.
> + */
> +int drm_client_new(struct drm_device *dev, struct drm_client_dev *client,
> + const char *name)
> +{
> + int ret;
> +
> + if (!drm_core_check_feature(dev, DRIVER_MODESET) ||
> + !dev->driver->dumb_create || !dev->driver->gem_prime_vmap)
> + return -ENOTSUPP;
> +
> + client->dev = dev;
> + client->name = name;
> +
> + ret = drm_client_open(client);
> + if (ret)
> + return ret;
> +
> + drm_dev_get(dev);
> +
> + return 0;
> +}
> +EXPORT_SYMBOL(drm_client_new);
> +
> +/**
> + * drm_client_release - Release DRM client resources
> + * @client: DRM client
> + *
> + * Releases resources by closing the &drm_file that was opened by drm_client_new().
> + * It is called automatically if the &drm_client_funcs.unregister callback is _not_ set.
> + *
> + * This function should only be called from the unregister callback. An exception
> + * is fbdev which cannot free the buffer if userspace has open file descriptors.
> + *
> + * Note:
> + * Clients cannot initiate a release by themselves. This is done to keep the code simple.
> + * The driver has to be unloaded before the client can be unloaded.
> + */
> +void drm_client_release(struct drm_client_dev *client)
> +{
> + struct drm_device *dev = client->dev;
> +
> + DRM_DEV_DEBUG_KMS(dev->dev, "%s\n", client->name);
> +
> + drm_client_close(client);
> + drm_dev_put(dev);
> +}
> +EXPORT_SYMBOL(drm_client_release);
> +
> +static void drm_client_buffer_delete(struct drm_client_buffer *buffer)
> +{
> + struct drm_device *dev = buffer->client->dev;
> +
> + if (buffer->vaddr && dev->driver->gem_prime_vunmap)
> + dev->driver->gem_prime_vunmap(buffer->gem, buffer->vaddr);
> +
> + if (buffer->gem)
> + drm_gem_object_put_unlocked(buffer->gem);
> +
> + drm_mode_destroy_dumb(dev, buffer->handle, buffer->client->file);
> + kfree(buffer);
> +}
> +
> +static struct drm_client_buffer *
> +drm_client_buffer_create(struct drm_client_dev *client, u32 width, u32 height, u32 format)
> +{
> + struct drm_mode_create_dumb dumb_args = { };
> + struct drm_device *dev = client->dev;
> + struct drm_client_buffer *buffer;
> + struct drm_gem_object *obj;
> + void *vaddr;
> + int ret;
> +
> + buffer = kzalloc(sizeof(*buffer), GFP_KERNEL);
> + if (!buffer)
> + return ERR_PTR(-ENOMEM);
> +
> + buffer->client = client;
> +
> + dumb_args.width = width;
> + dumb_args.height = height;
> + dumb_args.bpp = drm_format_plane_cpp(format, 0) * 8;
> + ret = drm_mode_create_dumb(dev, &dumb_args, client->file);
> + if (ret)
> + goto err_free;
> +
> + buffer->handle = dumb_args.handle;
> + buffer->pitch = dumb_args.pitch;
> +
> + obj = drm_gem_object_lookup(client->file, dumb_args.handle);
> + if (!obj) {
> + ret = -ENOENT;
> + goto err_delete;
> + }
> +
> + buffer->gem = obj;
> +
> + /*
> + * FIXME: The dependency on GEM here isn't required, we could
> + * convert the driver handle to a dma-buf instead and use the
> + * backend-agnostic dma-buf vmap support instead. This would
> + * require that the handle2fd prime ioctl is reworked to pull the
> + * fd_install step out of the driver backend hooks, to make that
> + * final step optional for internal users.
> + */
> + vaddr = dev->driver->gem_prime_vmap(obj);
> + if (!vaddr) {
> + ret = -ENOMEM;
> + goto err_delete;
> + }
> +
> + buffer->vaddr = vaddr;
> +
> + return buffer;
> +
> +err_delete:
> + drm_client_buffer_delete(buffer);
> +err_free:
> + kfree(buffer);
> +
> + return ERR_PTR(ret);
> +}
> +
> +static void drm_client_buffer_rmfb(struct drm_client_buffer *buffer)
> +{
> + int ret;
> +
> + if (!buffer->fb)
> + return;
> +
> + ret = drm_mode_rmfb(buffer->client->dev, buffer->fb->base.id, buffer->client->file);
> + if (ret)
> + DRM_DEV_ERROR(buffer->client->dev->dev,
> + "Error removing FB:%u (%d)\n", buffer->fb->base.id, ret);
> +
> + buffer->fb = NULL;
> +}
> +
> +static int drm_client_buffer_addfb(struct drm_client_buffer *buffer,
> + u32 width, u32 height, u32 format)
> +{
> + struct drm_client_dev *client = buffer->client;
> + struct drm_mode_fb_cmd fb_req = { };
> + const struct drm_format_info *info;
> + int ret;
> +
> + info = drm_format_info(format);
> + fb_req.bpp = info->cpp[0] * 8;
> + fb_req.depth = info->depth;
> + fb_req.width = width;
> + fb_req.height = height;
> + fb_req.handle = buffer->handle;
> + fb_req.pitch = buffer->pitch;
> +
> + ret = drm_mode_addfb(client->dev, &fb_req, client->file);
> + if (ret)
> + return ret;
> +
> + buffer->fb = drm_framebuffer_lookup(client->dev, buffer->client->file, fb_req.fb_id);
> + if (WARN_ON(!buffer->fb))
> + return -ENOENT;
> +
> + /* drop the reference we picked up in framebuffer lookup */
> + drm_framebuffer_put(buffer->fb);
> +
> + strscpy(buffer->fb->comm, client->name, TASK_COMM_LEN);
> +
> + return 0;
> +}
> +
> +/**
> + * drm_client_framebuffer_create - Create a client framebuffer
> + * @client: DRM client
> + * @width: Framebuffer width
> + * @height: Framebuffer height
> + * @format: Buffer format
> + *
> + * This function creates a &drm_client_buffer which consists of a
> + * &drm_framebuffer backed by a dumb buffer.
> + * Call drm_client_framebuffer_delete() to free the buffer.
> + *
> + * Returns:
> + * Pointer to a client buffer or an error pointer on failure.
> + */
> +struct drm_client_buffer *
> +drm_client_framebuffer_create(struct drm_client_dev *client, u32 width, u32 height, u32 format)
> +{
> + struct drm_client_buffer *buffer;
> + int ret;
> +
> + buffer = drm_client_buffer_create(client, width, height, format);
> + if (IS_ERR(buffer))
> + return buffer;
> +
> + ret = drm_client_buffer_addfb(buffer, width, height, format);
> + if (ret) {
> + drm_client_buffer_delete(buffer);
> + return ERR_PTR(ret);
> + }
> +
> + return buffer;
> +}
> +EXPORT_SYMBOL(drm_client_framebuffer_create);
> +
> +/**
> + * drm_client_framebuffer_delete - Delete a client framebuffer
> + * @buffer: DRM client buffer (can be NULL)
> + */
> +void drm_client_framebuffer_delete(struct drm_client_buffer *buffer)
> +{
> + if (!buffer)
> + return;
> +
> + drm_client_buffer_rmfb(buffer);
> + drm_client_buffer_delete(buffer);
> +}
> +EXPORT_SYMBOL(drm_client_framebuffer_delete);
> diff --git a/drivers/gpu/drm/drm_drv.c b/drivers/gpu/drm/drm_drv.c
> index 7af748ed1c58..e7ff0b03328b 100644
> --- a/drivers/gpu/drm/drm_drv.c
> +++ b/drivers/gpu/drm/drm_drv.c
> @@ -505,6 +505,7 @@ int drm_dev_init(struct drm_device *dev,
> dev->driver = driver;
>
> INIT_LIST_HEAD(&dev->filelist);
> + INIT_LIST_HEAD(&dev->filelist_internal);
> INIT_LIST_HEAD(&dev->ctxlist);
> INIT_LIST_HEAD(&dev->vmalist);
> INIT_LIST_HEAD(&dev->maplist);
> diff --git a/include/drm/drm_client.h b/include/drm/drm_client.h
> new file mode 100644
> index 000000000000..e366f95d4414
> --- /dev/null
> +++ b/include/drm/drm_client.h
> @@ -0,0 +1,76 @@
> +/* SPDX-License-Identifier: GPL-2.0 */
> +
> +#ifndef _DRM_CLIENT_H_
> +#define _DRM_CLIENT_H_
> +
> +#include <linux/types.h>
> +
> +struct drm_device;
> +struct drm_file;
> +struct drm_framebuffer;
> +struct drm_gem_object;
> +
> +/**
> + * struct drm_client_dev - DRM client instance
> + */
> +struct drm_client_dev {
> + /**
> + * @dev: DRM device
> + */
> + struct drm_device *dev;
> +
> + /**
> + * @name: Name of the client.
> + */
> + const char *name;
> +
> + /**
> + * @file: DRM file
> + */
> + struct drm_file *file;
> +};
> +
> +int drm_client_new(struct drm_device *dev, struct drm_client_dev *client,
> + const char *name);
> +void drm_client_release(struct drm_client_dev *client);
> +
> +/**
> + * struct drm_client_buffer - DRM client buffer
> + */
> +struct drm_client_buffer {
> + /**
> + * @client: DRM client
> + */
> + struct drm_client_dev *client;
> +
> + /**
> + * @handle: Buffer handle
> + */
> + u32 handle;
> +
> + /**
> + * @pitch: Buffer pitch
> + */
> + u32 pitch;
> +
> + /**
> + * @gem: GEM object backing this buffer
> + */
> + struct drm_gem_object *gem;
> +
> + /**
> + * @vaddr: Virtual address for the buffer
> + */
> + void *vaddr;
> +
> + /**
> + * @fb: DRM framebuffer
> + */
> + struct drm_framebuffer *fb;
> +};
> +
> +struct drm_client_buffer *
> +drm_client_framebuffer_create(struct drm_client_dev *client, u32 width, u32 height, u32 format);
> +void drm_client_framebuffer_delete(struct drm_client_buffer *buffer);
> +
> +#endif
> diff --git a/include/drm/drm_device.h b/include/drm/drm_device.h
> index 858ba19a3e29..9e29976d4e98 100644
> --- a/include/drm/drm_device.h
> +++ b/include/drm/drm_device.h
> @@ -74,6 +74,13 @@ struct drm_device {
> struct mutex filelist_mutex;
> struct list_head filelist;
>
> + /**
> + * @filelist_internal:
> + *
> + * List of open DRM files for in-kernel clients. Protected by @filelist_mutex.
> + */
> + struct list_head filelist_internal;
> +
> /** \name Memory management */
> /*@{ */
> struct list_head maplist; /**< Linked list of regions */
> --
> 2.15.1
>
> _______________________________________________
> dri-devel mailing list
> dri-devel@lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/dri-devel
--
Daniel Vetter
Software Engineer, Intel Corporation
http://blog.ffwll.ch
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx
^ permalink raw reply [flat|nested] 24+ messages in thread
* Re: [PATCH v4 5/9] drm/client: Add client callbacks
2018-07-02 13:54 ` [PATCH v4 5/9] drm/client: Add client callbacks Noralf Trønnes
@ 2018-07-03 7:46 ` Daniel Vetter
2018-07-03 13:07 ` Noralf Trønnes
0 siblings, 1 reply; 24+ messages in thread
From: Daniel Vetter @ 2018-07-03 7:46 UTC (permalink / raw)
To: Noralf Trønnes; +Cc: intel-gfx, laurent.pinchart, dri-devel, david
On Mon, Jul 02, 2018 at 03:54:29PM +0200, Noralf Trønnes wrote:
> Add client callbacks and hook them up.
> Add a list of clients per drm_device.
>
> Signed-off-by: Noralf Trønnes <noralf@tronnes.org>
btw for reviewing it'd be simpler if you merge the 2 patches that add the
client library, avoids me having to jump back&forth ..
Bunch of comments below still.
-Daniel
> ---
> drivers/gpu/drm/drm_client.c | 92 ++++++++++++++++++++++++++++++++++++-
> drivers/gpu/drm/drm_drv.c | 7 +++
> drivers/gpu/drm/drm_fb_cma_helper.c | 2 +-
> drivers/gpu/drm/drm_fb_helper.c | 11 ++++-
> drivers/gpu/drm/drm_file.c | 3 ++
> drivers/gpu/drm/drm_probe_helper.c | 3 ++
> include/drm/drm_client.h | 75 +++++++++++++++++++++++++++++-
> include/drm/drm_device.h | 14 ++++++
> 8 files changed, 201 insertions(+), 6 deletions(-)
>
> diff --git a/drivers/gpu/drm/drm_client.c b/drivers/gpu/drm/drm_client.c
> index 9c9b8ac7aea3..f05ee98bd10c 100644
> --- a/drivers/gpu/drm/drm_client.c
> +++ b/drivers/gpu/drm/drm_client.c
> @@ -4,6 +4,7 @@
> */
>
> #include <linux/list.h>
> +#include <linux/module.h>
> #include <linux/mutex.h>
> #include <linux/seq_file.h>
> #include <linux/slab.h>
> @@ -66,6 +67,7 @@ EXPORT_SYMBOL(drm_client_close);
> * @dev: DRM device
> * @client: DRM client
> * @name: Client name
> + * @funcs: DRM client functions (optional)
> *
> * Use drm_client_put() to free the client.
> *
> @@ -73,24 +75,47 @@ EXPORT_SYMBOL(drm_client_close);
> * Zero on success or negative error code on failure.
> */
> int drm_client_new(struct drm_device *dev, struct drm_client_dev *client,
> - const char *name)
> + const char *name, const struct drm_client_funcs *funcs)
> {
> + bool registered;
> int ret;
>
> if (!drm_core_check_feature(dev, DRIVER_MODESET) ||
> !dev->driver->dumb_create || !dev->driver->gem_prime_vmap)
> return -ENOTSUPP;
>
> + if (funcs && !try_module_get(funcs->owner))
> + return -ENODEV;
> +
> client->dev = dev;
> client->name = name;
> + client->funcs = funcs;
>
> ret = drm_client_open(client);
> if (ret)
> - return ret;
> + goto err_put_module;
> +
> + mutex_lock(&dev->clientlist_mutex);
> + registered = dev->registered;
> + if (registered)
> + list_add(&client->list, &dev->clientlist);
> + mutex_unlock(&dev->clientlist_mutex);
> + if (!registered) {
> + ret = -ENODEV;
> + goto err_close;
> + }
>
> drm_dev_get(dev);
This only works if the caller holds a reference for us on dev already, or
has some other guarantee that it won't disappear. Would be good to mention
this in the kerneldoc.
> return 0;
> +
> +err_close:
> + drm_client_close(client);
> +err_put_module:
> + if (funcs)
> + module_put(funcs->owner);
> +
> + return ret;
> }
> EXPORT_SYMBOL(drm_client_new);
>
> @@ -116,9 +141,72 @@ void drm_client_release(struct drm_client_dev *client)
>
> drm_client_close(client);
> drm_dev_put(dev);
> + if (client->funcs)
> + module_put(client->funcs->owner);
> }
> EXPORT_SYMBOL(drm_client_release);
>
> +void drm_client_dev_unregister(struct drm_device *dev)
> +{
> + struct drm_client_dev *client, *tmp;
> +
> + if (!drm_core_check_feature(dev, DRIVER_MODESET))
> + return;
> +
> + mutex_lock(&dev->clientlist_mutex);
> + list_for_each_entry_safe(client, tmp, &dev->clientlist, list) {
> + list_del(&client->list);
> + if (client->funcs && client->funcs->unregister) {
> + client->funcs->unregister(client);
Hm, not ->unregister is called while holding the lock. I thought that
blows up for you?
> + } else {
> + drm_client_release(client);
> + kfree(client);
> + }
> + }
> + mutex_unlock(&dev->clientlist_mutex);
> +}
> +
Needs a bit of kerneldoc here since exported function. Drivers might also
want to call this from their own hotplug handling.
> +void drm_client_dev_hotplug(struct drm_device *dev)
> +{
> + struct drm_client_dev *client;
> + int ret;
> +
> + if (!drm_core_check_feature(dev, DRIVER_MODESET))
> + return;
> +
> + mutex_lock(&dev->clientlist_mutex);
> + list_for_each_entry(client, &dev->clientlist, list) {
> + if (!client->funcs || !client->funcs->hotplug)
> + continue;
> +
> + ret = client->funcs->hotplug(client);
> + DRM_DEV_DEBUG_KMS(dev->dev, "%s: ret=%d\n", client->name, ret);
> + }
> + mutex_unlock(&dev->clientlist_mutex);
> +}
> +EXPORT_SYMBOL(drm_client_dev_hotplug);
> +
> +void drm_client_dev_restore(struct drm_device *dev)
> +{
> + struct drm_client_dev *client;
> + int ret;
> +
> + if (!drm_core_check_feature(dev, DRIVER_MODESET))
> + return;
> +
> + mutex_lock(&dev->clientlist_mutex);
> + list_for_each_entry(client, &dev->clientlist, list) {
> + if (!client->funcs || !client->funcs->restore)
> + continue;
> +
> + ret = client->funcs->restore(client);
> + DRM_DEV_DEBUG_KMS(dev->dev, "%s: ret=%d\n", client->name, ret);
> + if (!ret) /* The first one to return zero gets the privilege to restore */
> + break;
> + }
> + mutex_unlock(&dev->clientlist_mutex);
> +}
> +
> static void drm_client_buffer_delete(struct drm_client_buffer *buffer)
> {
> struct drm_device *dev = buffer->client->dev;
> diff --git a/drivers/gpu/drm/drm_drv.c b/drivers/gpu/drm/drm_drv.c
> index e7ff0b03328b..6eb935bb2f92 100644
> --- a/drivers/gpu/drm/drm_drv.c
> +++ b/drivers/gpu/drm/drm_drv.c
> @@ -34,6 +34,7 @@
> #include <linux/slab.h>
> #include <linux/srcu.h>
>
> +#include <drm/drm_client.h>
> #include <drm/drm_drv.h>
> #include <drm/drmP.h>
>
> @@ -506,6 +507,7 @@ int drm_dev_init(struct drm_device *dev,
>
> INIT_LIST_HEAD(&dev->filelist);
> INIT_LIST_HEAD(&dev->filelist_internal);
> + INIT_LIST_HEAD(&dev->clientlist);
> INIT_LIST_HEAD(&dev->ctxlist);
> INIT_LIST_HEAD(&dev->vmalist);
> INIT_LIST_HEAD(&dev->maplist);
> @@ -515,6 +517,7 @@ int drm_dev_init(struct drm_device *dev,
> spin_lock_init(&dev->event_lock);
> mutex_init(&dev->struct_mutex);
> mutex_init(&dev->filelist_mutex);
> + mutex_init(&dev->clientlist_mutex);
> mutex_init(&dev->ctxlist_mutex);
> mutex_init(&dev->master_mutex);
>
> @@ -570,6 +573,7 @@ int drm_dev_init(struct drm_device *dev,
> err_free:
> mutex_destroy(&dev->master_mutex);
> mutex_destroy(&dev->ctxlist_mutex);
> + mutex_destroy(&dev->clientlist_mutex);
> mutex_destroy(&dev->filelist_mutex);
> mutex_destroy(&dev->struct_mutex);
> return ret;
> @@ -604,6 +608,7 @@ void drm_dev_fini(struct drm_device *dev)
>
> mutex_destroy(&dev->master_mutex);
> mutex_destroy(&dev->ctxlist_mutex);
> + mutex_destroy(&dev->clientlist_mutex);
> mutex_destroy(&dev->filelist_mutex);
> mutex_destroy(&dev->struct_mutex);
> kfree(dev->unique);
> @@ -859,6 +864,8 @@ void drm_dev_unregister(struct drm_device *dev)
>
> dev->registered = false;
>
> + drm_client_dev_unregister(dev);
> +
> if (drm_core_check_feature(dev, DRIVER_MODESET))
> drm_modeset_unregister_all(dev);
>
> diff --git a/drivers/gpu/drm/drm_fb_cma_helper.c b/drivers/gpu/drm/drm_fb_cma_helper.c
> index 5762a7c441e9..718c7f961d8a 100644
> --- a/drivers/gpu/drm/drm_fb_cma_helper.c
> +++ b/drivers/gpu/drm/drm_fb_cma_helper.c
> @@ -181,7 +181,7 @@ struct drm_fbdev_cma *drm_fbdev_cma_init(struct drm_device *dev,
>
> fb_helper = &fbdev_cma->fb_helper;
>
> - ret = drm_client_new(dev, &fb_helper->client, "fbdev");
> + ret = drm_client_new(dev, &fb_helper->client, "fbdev", NULL);
> if (ret)
> goto err_free;
>
> diff --git a/drivers/gpu/drm/drm_fb_helper.c b/drivers/gpu/drm/drm_fb_helper.c
> index 0a0a577ebc3c..bea3a0cb324a 100644
> --- a/drivers/gpu/drm/drm_fb_helper.c
> +++ b/drivers/gpu/drm/drm_fb_helper.c
> @@ -2989,8 +2989,15 @@ static void drm_fbdev_fb_destroy(struct fb_info *info)
> }
>
> drm_client_framebuffer_delete(fb_helper->buffer);
> - drm_client_release(&fb_helper->client);
> - kfree(fb_helper);
> + /*
> + * FIXME:
> + * Remove conditional when all CMA drivers have been moved over to using
> + * drm_fbdev_generic_setup().
> + */
> + if (fb_helper->client.funcs) {
> + drm_client_release(&fb_helper->client);
> + kfree(fb_helper);
> + }
> }
>
> static int drm_fbdev_fb_mmap(struct fb_info *info, struct vm_area_struct *vma)
> diff --git a/drivers/gpu/drm/drm_file.c b/drivers/gpu/drm/drm_file.c
> index 66bb403dc8ab..ffa8dc35515f 100644
> --- a/drivers/gpu/drm/drm_file.c
> +++ b/drivers/gpu/drm/drm_file.c
> @@ -35,6 +35,7 @@
> #include <linux/slab.h>
> #include <linux/module.h>
>
> +#include <drm/drm_client.h>
> #include <drm/drm_file.h>
> #include <drm/drmP.h>
>
> @@ -444,6 +445,8 @@ void drm_lastclose(struct drm_device * dev)
>
> if (drm_core_check_feature(dev, DRIVER_LEGACY))
> drm_legacy_dev_reinit(dev);
> +
> + drm_client_dev_restore(dev);
> }
>
> /**
> diff --git a/drivers/gpu/drm/drm_probe_helper.c b/drivers/gpu/drm/drm_probe_helper.c
> index 527743394150..26be57e28a9d 100644
> --- a/drivers/gpu/drm/drm_probe_helper.c
> +++ b/drivers/gpu/drm/drm_probe_helper.c
> @@ -33,6 +33,7 @@
> #include <linux/moduleparam.h>
>
> #include <drm/drmP.h>
> +#include <drm/drm_client.h>
> #include <drm/drm_crtc.h>
> #include <drm/drm_fourcc.h>
> #include <drm/drm_crtc_helper.h>
> @@ -563,6 +564,8 @@ void drm_kms_helper_hotplug_event(struct drm_device *dev)
> drm_sysfs_hotplug_event(dev);
> if (dev->mode_config.funcs->output_poll_changed)
> dev->mode_config.funcs->output_poll_changed(dev);
> +
> + drm_client_dev_hotplug(dev);
> }
> EXPORT_SYMBOL(drm_kms_helper_hotplug_event);
>
> diff --git a/include/drm/drm_client.h b/include/drm/drm_client.h
> index e366f95d4414..02cbb02714d8 100644
> --- a/include/drm/drm_client.h
> +++ b/include/drm/drm_client.h
> @@ -5,10 +5,66 @@
>
> #include <linux/types.h>
>
> +struct drm_client_dev;
> struct drm_device;
> struct drm_file;
> struct drm_framebuffer;
> struct drm_gem_object;
> +struct module;
> +
> +/**
> + * struct drm_client_funcs - DRM client callbacks
> + */
> +struct drm_client_funcs {
> + /**
> + * @owner: The module owner
> + */
> + struct module *owner;
> +
> + /**
> + * @release:
> + *
> + * Called when the reference count is dropped to zero. Users of this
> + * callback is responsible for calling drm_client_close() and freeing
> + * the client structure.
> + *
> + * This callback is optional.
> + */
> + void (*release)(struct drm_client_dev *client);
Hm, is this no longer in use?
> +
> + /**
> + * @unregister:
> + *
> + * Called when &drm_device is unregistered. The client should respond by
> + * releasing it's resources using drm_client_put(). If it can't do so
> + * due to resoruces being tied up, like fbdev with open file handles,
> + * it should release it's resources as soon as possible.
This still talks about refcounting and _put ... needs a refresher.
> + *
> + * This callback is optional.
> + */
> + void (*unregister)(struct drm_client_dev *client);
> +
> + /**
> + * @restore:
> + *
> + * Called on drm_lastclose(). The first client instance in the list that
> + * returns zero gets the privilege to restore and no more clients are
> + * called. This callback is not called after @unregister has been called.
> + *
> + * This callback is optional.
> + */
> + int (*restore)(struct drm_client_dev *client);
> +
> + /**
> + * @hotplug:
> + *
> + * Called on drm_kms_helper_hotplug_event().
> + * This callback is not called after @unregister has been called.
> + *
> + * This callback is optional.
> + */
> + int (*hotplug)(struct drm_client_dev *client);
> +};
>
> /**
> * struct drm_client_dev - DRM client instance
> @@ -24,6 +80,19 @@ struct drm_client_dev {
> */
> const char *name;
>
> + /**
> + * @list:
> + *
> + * List of all clients of a DRM device, linked into
> + * &drm_device.clientlist. Protected by &drm_device.clientlist_mutex.
> + */
> + struct list_head list;
> +
> + /**
> + * @funcs: DRM client functions (optional)
> + */
> + const struct drm_client_funcs *funcs;
> +
> /**
> * @file: DRM file
> */
> @@ -31,9 +100,13 @@ struct drm_client_dev {
> };
>
> int drm_client_new(struct drm_device *dev, struct drm_client_dev *client,
> - const char *name);
> + const char *name, const struct drm_client_funcs *funcs);
> void drm_client_release(struct drm_client_dev *client);
>
> +void drm_client_dev_unregister(struct drm_device *dev);
> +void drm_client_dev_hotplug(struct drm_device *dev);
> +void drm_client_dev_restore(struct drm_device *dev);
> +
> /**
> * struct drm_client_buffer - DRM client buffer
> */
> diff --git a/include/drm/drm_device.h b/include/drm/drm_device.h
> index 9e29976d4e98..f9c6e0e3aec7 100644
> --- a/include/drm/drm_device.h
> +++ b/include/drm/drm_device.h
> @@ -81,6 +81,20 @@ struct drm_device {
> */
> struct list_head filelist_internal;
>
> + /**
> + * @clientlist_mutex:
> + *
> + * Protects @clientlist access.
> + */
> + struct mutex clientlist_mutex;
> +
> + /**
> + * @clientlist:
> + *
> + * List of in-kernel clients. Protected by @clientlist_mutex.
> + */
> + struct list_head clientlist;
> +
> /** \name Memory management */
> /*@{ */
> struct list_head maplist; /**< Linked list of regions */
> --
> 2.15.1
>
> _______________________________________________
> dri-devel mailing list
> dri-devel@lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/dri-devel
--
Daniel Vetter
Software Engineer, Intel Corporation
http://blog.ffwll.ch
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel
^ permalink raw reply [flat|nested] 24+ messages in thread
* Re: [PATCH v4 5/9] drm/client: Add client callbacks
2018-07-03 7:46 ` Daniel Vetter
@ 2018-07-03 13:07 ` Noralf Trønnes
2018-07-03 13:18 ` Daniel Vetter
0 siblings, 1 reply; 24+ messages in thread
From: Noralf Trønnes @ 2018-07-03 13:07 UTC (permalink / raw)
To: Daniel Vetter; +Cc: intel-gfx, laurent.pinchart, dri-devel, david
Den 03.07.2018 09.46, skrev Daniel Vetter:
> On Mon, Jul 02, 2018 at 03:54:29PM +0200, Noralf Trønnes wrote:
>> Add client callbacks and hook them up.
>> Add a list of clients per drm_device.
>>
>> Signed-off-by: Noralf Trønnes <noralf@tronnes.org>
> btw for reviewing it'd be simpler if you merge the 2 patches that add the
> client library, avoids me having to jump back&forth ..
>
> Bunch of comments below still.
> -Daniel
>
>> ---
>> drivers/gpu/drm/drm_client.c | 92 ++++++++++++++++++++++++++++++++++++-
>> drivers/gpu/drm/drm_drv.c | 7 +++
>> drivers/gpu/drm/drm_fb_cma_helper.c | 2 +-
>> drivers/gpu/drm/drm_fb_helper.c | 11 ++++-
>> drivers/gpu/drm/drm_file.c | 3 ++
>> drivers/gpu/drm/drm_probe_helper.c | 3 ++
>> include/drm/drm_client.h | 75 +++++++++++++++++++++++++++++-
>> include/drm/drm_device.h | 14 ++++++
>> 8 files changed, 201 insertions(+), 6 deletions(-)
>>
>> diff --git a/drivers/gpu/drm/drm_client.c b/drivers/gpu/drm/drm_client.c
>> index 9c9b8ac7aea3..f05ee98bd10c 100644
>> --- a/drivers/gpu/drm/drm_client.c
>> +++ b/drivers/gpu/drm/drm_client.c
>> @@ -4,6 +4,7 @@
>> */
>>
>> #include <linux/list.h>
>> +#include <linux/module.h>
>> #include <linux/mutex.h>
>> #include <linux/seq_file.h>
>> #include <linux/slab.h>
>> @@ -66,6 +67,7 @@ EXPORT_SYMBOL(drm_client_close);
>> * @dev: DRM device
>> * @client: DRM client
>> * @name: Client name
>> + * @funcs: DRM client functions (optional)
>> *
>> * Use drm_client_put() to free the client.
>> *
>> @@ -73,24 +75,47 @@ EXPORT_SYMBOL(drm_client_close);
>> * Zero on success or negative error code on failure.
>> */
>> int drm_client_new(struct drm_device *dev, struct drm_client_dev *client,
>> - const char *name)
>> + const char *name, const struct drm_client_funcs *funcs)
>> {
>> + bool registered;
>> int ret;
>>
>> if (!drm_core_check_feature(dev, DRIVER_MODESET) ||
>> !dev->driver->dumb_create || !dev->driver->gem_prime_vmap)
>> return -ENOTSUPP;
>>
>> + if (funcs && !try_module_get(funcs->owner))
>> + return -ENODEV;
>> +
>> client->dev = dev;
>> client->name = name;
>> + client->funcs = funcs;
>>
>> ret = drm_client_open(client);
>> if (ret)
>> - return ret;
>> + goto err_put_module;
>> +
>> + mutex_lock(&dev->clientlist_mutex);
>> + registered = dev->registered;
>> + if (registered)
>> + list_add(&client->list, &dev->clientlist);
>> + mutex_unlock(&dev->clientlist_mutex);
>> + if (!registered) {
>> + ret = -ENODEV;
>> + goto err_close;
>> + }
>>
>> drm_dev_get(dev);
> This only works if the caller holds a reference for us on dev already, or
> has some other guarantee that it won't disappear. Would be good to mention
> this in the kerneldoc.
>
>> return 0;
>> +
>> +err_close:
>> + drm_client_close(client);
>> +err_put_module:
>> + if (funcs)
>> + module_put(funcs->owner);
>> +
>> + return ret;
>> }
>> EXPORT_SYMBOL(drm_client_new);
>>
>> @@ -116,9 +141,72 @@ void drm_client_release(struct drm_client_dev *client)
>>
>> drm_client_close(client);
>> drm_dev_put(dev);
>> + if (client->funcs)
>> + module_put(client->funcs->owner);
>> }
>> EXPORT_SYMBOL(drm_client_release);
>>
>> +void drm_client_dev_unregister(struct drm_device *dev)
>> +{
>> + struct drm_client_dev *client, *tmp;
>> +
>> + if (!drm_core_check_feature(dev, DRIVER_MODESET))
>> + return;
>> +
>> + mutex_lock(&dev->clientlist_mutex);
>> + list_for_each_entry_safe(client, tmp, &dev->clientlist, list) {
>> + list_del(&client->list);
>> + if (client->funcs && client->funcs->unregister) {
>> + client->funcs->unregister(client);
> Hm, not ->unregister is called while holding the lock. I thought that
> blows up for you?
It is fine now that we decided that the client can't remove itself.
Only the driver can do it on drm_dev_unregister().
>> + } else {
>> + drm_client_release(client);
>> + kfree(client);
>> + }
>> + }
>> + mutex_unlock(&dev->clientlist_mutex);
>> +}
>> +
> Needs a bit of kerneldoc here since exported function. Drivers might also
> want to call this from their own hotplug handling.
drm_client_dev_hotplug() is only called by drm_kms_helper_hotplug_event().
The reason it's exported is because the helper can be built as a module.
Noralf.
>> +void drm_client_dev_hotplug(struct drm_device *dev)
>> +{
>> + struct drm_client_dev *client;
>> + int ret;
>> +
>> + if (!drm_core_check_feature(dev, DRIVER_MODESET))
>> + return;
>> +
>> + mutex_lock(&dev->clientlist_mutex);
>> + list_for_each_entry(client, &dev->clientlist, list) {
>> + if (!client->funcs || !client->funcs->hotplug)
>> + continue;
>> +
>> + ret = client->funcs->hotplug(client);
>> + DRM_DEV_DEBUG_KMS(dev->dev, "%s: ret=%d\n", client->name, ret);
>> + }
>> + mutex_unlock(&dev->clientlist_mutex);
>> +}
>> +EXPORT_SYMBOL(drm_client_dev_hotplug);
>> +
>> +void drm_client_dev_restore(struct drm_device *dev)
>> +{
>> + struct drm_client_dev *client;
>> + int ret;
>> +
>> + if (!drm_core_check_feature(dev, DRIVER_MODESET))
>> + return;
>> +
>> + mutex_lock(&dev->clientlist_mutex);
>> + list_for_each_entry(client, &dev->clientlist, list) {
>> + if (!client->funcs || !client->funcs->restore)
>> + continue;
>> +
>> + ret = client->funcs->restore(client);
>> + DRM_DEV_DEBUG_KMS(dev->dev, "%s: ret=%d\n", client->name, ret);
>> + if (!ret) /* The first one to return zero gets the privilege to restore */
>> + break;
>> + }
>> + mutex_unlock(&dev->clientlist_mutex);
>> +}
>> +
>> static void drm_client_buffer_delete(struct drm_client_buffer *buffer)
>> {
>> struct drm_device *dev = buffer->client->dev;
>> diff --git a/drivers/gpu/drm/drm_drv.c b/drivers/gpu/drm/drm_drv.c
>> index e7ff0b03328b..6eb935bb2f92 100644
>> --- a/drivers/gpu/drm/drm_drv.c
>> +++ b/drivers/gpu/drm/drm_drv.c
>> @@ -34,6 +34,7 @@
>> #include <linux/slab.h>
>> #include <linux/srcu.h>
>>
>> +#include <drm/drm_client.h>
>> #include <drm/drm_drv.h>
>> #include <drm/drmP.h>
>>
>> @@ -506,6 +507,7 @@ int drm_dev_init(struct drm_device *dev,
>>
>> INIT_LIST_HEAD(&dev->filelist);
>> INIT_LIST_HEAD(&dev->filelist_internal);
>> + INIT_LIST_HEAD(&dev->clientlist);
>> INIT_LIST_HEAD(&dev->ctxlist);
>> INIT_LIST_HEAD(&dev->vmalist);
>> INIT_LIST_HEAD(&dev->maplist);
>> @@ -515,6 +517,7 @@ int drm_dev_init(struct drm_device *dev,
>> spin_lock_init(&dev->event_lock);
>> mutex_init(&dev->struct_mutex);
>> mutex_init(&dev->filelist_mutex);
>> + mutex_init(&dev->clientlist_mutex);
>> mutex_init(&dev->ctxlist_mutex);
>> mutex_init(&dev->master_mutex);
>>
>> @@ -570,6 +573,7 @@ int drm_dev_init(struct drm_device *dev,
>> err_free:
>> mutex_destroy(&dev->master_mutex);
>> mutex_destroy(&dev->ctxlist_mutex);
>> + mutex_destroy(&dev->clientlist_mutex);
>> mutex_destroy(&dev->filelist_mutex);
>> mutex_destroy(&dev->struct_mutex);
>> return ret;
>> @@ -604,6 +608,7 @@ void drm_dev_fini(struct drm_device *dev)
>>
>> mutex_destroy(&dev->master_mutex);
>> mutex_destroy(&dev->ctxlist_mutex);
>> + mutex_destroy(&dev->clientlist_mutex);
>> mutex_destroy(&dev->filelist_mutex);
>> mutex_destroy(&dev->struct_mutex);
>> kfree(dev->unique);
>> @@ -859,6 +864,8 @@ void drm_dev_unregister(struct drm_device *dev)
>>
>> dev->registered = false;
>>
>> + drm_client_dev_unregister(dev);
>> +
>> if (drm_core_check_feature(dev, DRIVER_MODESET))
>> drm_modeset_unregister_all(dev);
>>
>> diff --git a/drivers/gpu/drm/drm_fb_cma_helper.c b/drivers/gpu/drm/drm_fb_cma_helper.c
>> index 5762a7c441e9..718c7f961d8a 100644
>> --- a/drivers/gpu/drm/drm_fb_cma_helper.c
>> +++ b/drivers/gpu/drm/drm_fb_cma_helper.c
>> @@ -181,7 +181,7 @@ struct drm_fbdev_cma *drm_fbdev_cma_init(struct drm_device *dev,
>>
>> fb_helper = &fbdev_cma->fb_helper;
>>
>> - ret = drm_client_new(dev, &fb_helper->client, "fbdev");
>> + ret = drm_client_new(dev, &fb_helper->client, "fbdev", NULL);
>> if (ret)
>> goto err_free;
>>
>> diff --git a/drivers/gpu/drm/drm_fb_helper.c b/drivers/gpu/drm/drm_fb_helper.c
>> index 0a0a577ebc3c..bea3a0cb324a 100644
>> --- a/drivers/gpu/drm/drm_fb_helper.c
>> +++ b/drivers/gpu/drm/drm_fb_helper.c
>> @@ -2989,8 +2989,15 @@ static void drm_fbdev_fb_destroy(struct fb_info *info)
>> }
>>
>> drm_client_framebuffer_delete(fb_helper->buffer);
>> - drm_client_release(&fb_helper->client);
>> - kfree(fb_helper);
>> + /*
>> + * FIXME:
>> + * Remove conditional when all CMA drivers have been moved over to using
>> + * drm_fbdev_generic_setup().
>> + */
>> + if (fb_helper->client.funcs) {
>> + drm_client_release(&fb_helper->client);
>> + kfree(fb_helper);
>> + }
>> }
>>
>> static int drm_fbdev_fb_mmap(struct fb_info *info, struct vm_area_struct *vma)
>> diff --git a/drivers/gpu/drm/drm_file.c b/drivers/gpu/drm/drm_file.c
>> index 66bb403dc8ab..ffa8dc35515f 100644
>> --- a/drivers/gpu/drm/drm_file.c
>> +++ b/drivers/gpu/drm/drm_file.c
>> @@ -35,6 +35,7 @@
>> #include <linux/slab.h>
>> #include <linux/module.h>
>>
>> +#include <drm/drm_client.h>
>> #include <drm/drm_file.h>
>> #include <drm/drmP.h>
>>
>> @@ -444,6 +445,8 @@ void drm_lastclose(struct drm_device * dev)
>>
>> if (drm_core_check_feature(dev, DRIVER_LEGACY))
>> drm_legacy_dev_reinit(dev);
>> +
>> + drm_client_dev_restore(dev);
>> }
>>
>> /**
>> diff --git a/drivers/gpu/drm/drm_probe_helper.c b/drivers/gpu/drm/drm_probe_helper.c
>> index 527743394150..26be57e28a9d 100644
>> --- a/drivers/gpu/drm/drm_probe_helper.c
>> +++ b/drivers/gpu/drm/drm_probe_helper.c
>> @@ -33,6 +33,7 @@
>> #include <linux/moduleparam.h>
>>
>> #include <drm/drmP.h>
>> +#include <drm/drm_client.h>
>> #include <drm/drm_crtc.h>
>> #include <drm/drm_fourcc.h>
>> #include <drm/drm_crtc_helper.h>
>> @@ -563,6 +564,8 @@ void drm_kms_helper_hotplug_event(struct drm_device *dev)
>> drm_sysfs_hotplug_event(dev);
>> if (dev->mode_config.funcs->output_poll_changed)
>> dev->mode_config.funcs->output_poll_changed(dev);
>> +
>> + drm_client_dev_hotplug(dev);
>> }
>> EXPORT_SYMBOL(drm_kms_helper_hotplug_event);
>>
>> diff --git a/include/drm/drm_client.h b/include/drm/drm_client.h
>> index e366f95d4414..02cbb02714d8 100644
>> --- a/include/drm/drm_client.h
>> +++ b/include/drm/drm_client.h
>> @@ -5,10 +5,66 @@
>>
>> #include <linux/types.h>
>>
>> +struct drm_client_dev;
>> struct drm_device;
>> struct drm_file;
>> struct drm_framebuffer;
>> struct drm_gem_object;
>> +struct module;
>> +
>> +/**
>> + * struct drm_client_funcs - DRM client callbacks
>> + */
>> +struct drm_client_funcs {
>> + /**
>> + * @owner: The module owner
>> + */
>> + struct module *owner;
>> +
>> + /**
>> + * @release:
>> + *
>> + * Called when the reference count is dropped to zero. Users of this
>> + * callback is responsible for calling drm_client_close() and freeing
>> + * the client structure.
>> + *
>> + * This callback is optional.
>> + */
>> + void (*release)(struct drm_client_dev *client);
> Hm, is this no longer in use?
>
>> +
>> + /**
>> + * @unregister:
>> + *
>> + * Called when &drm_device is unregistered. The client should respond by
>> + * releasing it's resources using drm_client_put(). If it can't do so
>> + * due to resoruces being tied up, like fbdev with open file handles,
>> + * it should release it's resources as soon as possible.
> This still talks about refcounting and _put ... needs a refresher.
>
>> + *
>> + * This callback is optional.
>> + */
>> + void (*unregister)(struct drm_client_dev *client);
>> +
>> + /**
>> + * @restore:
>> + *
>> + * Called on drm_lastclose(). The first client instance in the list that
>> + * returns zero gets the privilege to restore and no more clients are
>> + * called. This callback is not called after @unregister has been called.
>> + *
>> + * This callback is optional.
>> + */
>> + int (*restore)(struct drm_client_dev *client);
>> +
>> + /**
>> + * @hotplug:
>> + *
>> + * Called on drm_kms_helper_hotplug_event().
>> + * This callback is not called after @unregister has been called.
>> + *
>> + * This callback is optional.
>> + */
>> + int (*hotplug)(struct drm_client_dev *client);
>> +};
>>
>> /**
>> * struct drm_client_dev - DRM client instance
>> @@ -24,6 +80,19 @@ struct drm_client_dev {
>> */
>> const char *name;
>>
>> + /**
>> + * @list:
>> + *
>> + * List of all clients of a DRM device, linked into
>> + * &drm_device.clientlist. Protected by &drm_device.clientlist_mutex.
>> + */
>> + struct list_head list;
>> +
>> + /**
>> + * @funcs: DRM client functions (optional)
>> + */
>> + const struct drm_client_funcs *funcs;
>> +
>> /**
>> * @file: DRM file
>> */
>> @@ -31,9 +100,13 @@ struct drm_client_dev {
>> };
>>
>> int drm_client_new(struct drm_device *dev, struct drm_client_dev *client,
>> - const char *name);
>> + const char *name, const struct drm_client_funcs *funcs);
>> void drm_client_release(struct drm_client_dev *client);
>>
>> +void drm_client_dev_unregister(struct drm_device *dev);
>> +void drm_client_dev_hotplug(struct drm_device *dev);
>> +void drm_client_dev_restore(struct drm_device *dev);
>> +
>> /**
>> * struct drm_client_buffer - DRM client buffer
>> */
>> diff --git a/include/drm/drm_device.h b/include/drm/drm_device.h
>> index 9e29976d4e98..f9c6e0e3aec7 100644
>> --- a/include/drm/drm_device.h
>> +++ b/include/drm/drm_device.h
>> @@ -81,6 +81,20 @@ struct drm_device {
>> */
>> struct list_head filelist_internal;
>>
>> + /**
>> + * @clientlist_mutex:
>> + *
>> + * Protects @clientlist access.
>> + */
>> + struct mutex clientlist_mutex;
>> +
>> + /**
>> + * @clientlist:
>> + *
>> + * List of in-kernel clients. Protected by @clientlist_mutex.
>> + */
>> + struct list_head clientlist;
>> +
>> /** \name Memory management */
>> /*@{ */
>> struct list_head maplist; /**< Linked list of regions */
>> --
>> 2.15.1
>>
>> _______________________________________________
>> dri-devel mailing list
>> dri-devel@lists.freedesktop.org
>> https://lists.freedesktop.org/mailman/listinfo/dri-devel
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx
^ permalink raw reply [flat|nested] 24+ messages in thread
* Re: [PATCH v4 5/9] drm/client: Add client callbacks
2018-07-03 13:07 ` Noralf Trønnes
@ 2018-07-03 13:18 ` Daniel Vetter
0 siblings, 0 replies; 24+ messages in thread
From: Daniel Vetter @ 2018-07-03 13:18 UTC (permalink / raw)
To: Noralf Trønnes; +Cc: david, intel-gfx, dri-devel, laurent.pinchart
On Tue, Jul 03, 2018 at 03:07:50PM +0200, Noralf Trønnes wrote:
>
> Den 03.07.2018 09.46, skrev Daniel Vetter:
> > On Mon, Jul 02, 2018 at 03:54:29PM +0200, Noralf Trønnes wrote:
> > > Add client callbacks and hook them up.
> > > Add a list of clients per drm_device.
> > >
> > > Signed-off-by: Noralf Trønnes <noralf@tronnes.org>
> > btw for reviewing it'd be simpler if you merge the 2 patches that add the
> > client library, avoids me having to jump back&forth ..
> >
> > Bunch of comments below still.
> > -Daniel
> >
> > > ---
> > > drivers/gpu/drm/drm_client.c | 92 ++++++++++++++++++++++++++++++++++++-
> > > drivers/gpu/drm/drm_drv.c | 7 +++
> > > drivers/gpu/drm/drm_fb_cma_helper.c | 2 +-
> > > drivers/gpu/drm/drm_fb_helper.c | 11 ++++-
> > > drivers/gpu/drm/drm_file.c | 3 ++
> > > drivers/gpu/drm/drm_probe_helper.c | 3 ++
> > > include/drm/drm_client.h | 75 +++++++++++++++++++++++++++++-
> > > include/drm/drm_device.h | 14 ++++++
> > > 8 files changed, 201 insertions(+), 6 deletions(-)
> > >
> > > diff --git a/drivers/gpu/drm/drm_client.c b/drivers/gpu/drm/drm_client.c
> > > index 9c9b8ac7aea3..f05ee98bd10c 100644
> > > --- a/drivers/gpu/drm/drm_client.c
> > > +++ b/drivers/gpu/drm/drm_client.c
> > > @@ -4,6 +4,7 @@
> > > */
> > > #include <linux/list.h>
> > > +#include <linux/module.h>
> > > #include <linux/mutex.h>
> > > #include <linux/seq_file.h>
> > > #include <linux/slab.h>
> > > @@ -66,6 +67,7 @@ EXPORT_SYMBOL(drm_client_close);
> > > * @dev: DRM device
> > > * @client: DRM client
> > > * @name: Client name
> > > + * @funcs: DRM client functions (optional)
> > > *
> > > * Use drm_client_put() to free the client.
> > > *
> > > @@ -73,24 +75,47 @@ EXPORT_SYMBOL(drm_client_close);
> > > * Zero on success or negative error code on failure.
> > > */
> > > int drm_client_new(struct drm_device *dev, struct drm_client_dev *client,
> > > - const char *name)
> > > + const char *name, const struct drm_client_funcs *funcs)
> > > {
> > > + bool registered;
> > > int ret;
> > > if (!drm_core_check_feature(dev, DRIVER_MODESET) ||
> > > !dev->driver->dumb_create || !dev->driver->gem_prime_vmap)
> > > return -ENOTSUPP;
> > > + if (funcs && !try_module_get(funcs->owner))
> > > + return -ENODEV;
> > > +
> > > client->dev = dev;
> > > client->name = name;
> > > + client->funcs = funcs;
> > > ret = drm_client_open(client);
> > > if (ret)
> > > - return ret;
> > > + goto err_put_module;
> > > +
> > > + mutex_lock(&dev->clientlist_mutex);
> > > + registered = dev->registered;
> > > + if (registered)
> > > + list_add(&client->list, &dev->clientlist);
> > > + mutex_unlock(&dev->clientlist_mutex);
> > > + if (!registered) {
> > > + ret = -ENODEV;
> > > + goto err_close;
> > > + }
> > > drm_dev_get(dev);
> > This only works if the caller holds a reference for us on dev already, or
> > has some other guarantee that it won't disappear. Would be good to mention
> > this in the kerneldoc.
> >
> > > return 0;
> > > +
> > > +err_close:
> > > + drm_client_close(client);
> > > +err_put_module:
> > > + if (funcs)
> > > + module_put(funcs->owner);
> > > +
> > > + return ret;
> > > }
> > > EXPORT_SYMBOL(drm_client_new);
> > > @@ -116,9 +141,72 @@ void drm_client_release(struct drm_client_dev *client)
> > > drm_client_close(client);
> > > drm_dev_put(dev);
> > > + if (client->funcs)
> > > + module_put(client->funcs->owner);
> > > }
> > > EXPORT_SYMBOL(drm_client_release);
> > > +void drm_client_dev_unregister(struct drm_device *dev)
> > > +{
> > > + struct drm_client_dev *client, *tmp;
> > > +
> > > + if (!drm_core_check_feature(dev, DRIVER_MODESET))
> > > + return;
> > > +
> > > + mutex_lock(&dev->clientlist_mutex);
> > > + list_for_each_entry_safe(client, tmp, &dev->clientlist, list) {
> > > + list_del(&client->list);
> > > + if (client->funcs && client->funcs->unregister) {
> > > + client->funcs->unregister(client);
> > Hm, not ->unregister is called while holding the lock. I thought that
> > blows up for you?
>
> It is fine now that we decided that the client can't remove itself.
> Only the driver can do it on drm_dev_unregister().
I was more wondering about creating an unecessary locking hierarchy
complication. But through the ->hotplug and ->restore callbacks we already
require that all client locks (which will also include anything related to
fbdev and fbcon, hence also console_lock) must nest within
dev->clientlist_mutex. That's the part I was worried about, but that's not
a good concern really.
So all fine for me on 2nd thought.
>
> > > + } else {
> > > + drm_client_release(client);
> > > + kfree(client);
> > > + }
> > > + }
> > > + mutex_unlock(&dev->clientlist_mutex);
> > > +}
> > > +
> > Needs a bit of kerneldoc here since exported function. Drivers might also
> > want to call this from their own hotplug handling.
>
> drm_client_dev_hotplug() is only called by drm_kms_helper_hotplug_event().
> The reason it's exported is because the helper can be built as a module.
Anything helpers do drivers should be able to override. Anything drivers
should be able to use should have docs.
And e.g. drm_sysfs_hotplug_event is actually called by a driver namely
vmwgfx, and I think these two functions are pretty much equivalent - one
informs userspace clients about a hotplug, the other kernel clients about
a hotplug.
Anyway, since my only major concern (the locking question) is cleared up
after a bit more think I think this is good for an r-b, once the kerneldoc
is all fixed up and the ->release callback gone:
Reviewed-by: Daniel Vetter <daniel.vetter@ffwll.ch>
Cheers, Daniel
>
> Noralf.
>
> > > +void drm_client_dev_hotplug(struct drm_device *dev)
> > > +{
> > > + struct drm_client_dev *client;
> > > + int ret;
> > > +
> > > + if (!drm_core_check_feature(dev, DRIVER_MODESET))
> > > + return;
> > > +
> > > + mutex_lock(&dev->clientlist_mutex);
> > > + list_for_each_entry(client, &dev->clientlist, list) {
> > > + if (!client->funcs || !client->funcs->hotplug)
> > > + continue;
> > > +
> > > + ret = client->funcs->hotplug(client);
> > > + DRM_DEV_DEBUG_KMS(dev->dev, "%s: ret=%d\n", client->name, ret);
> > > + }
> > > + mutex_unlock(&dev->clientlist_mutex);
> > > +}
> > > +EXPORT_SYMBOL(drm_client_dev_hotplug);
> > > +
> > > +void drm_client_dev_restore(struct drm_device *dev)
> > > +{
> > > + struct drm_client_dev *client;
> > > + int ret;
> > > +
> > > + if (!drm_core_check_feature(dev, DRIVER_MODESET))
> > > + return;
> > > +
> > > + mutex_lock(&dev->clientlist_mutex);
> > > + list_for_each_entry(client, &dev->clientlist, list) {
> > > + if (!client->funcs || !client->funcs->restore)
> > > + continue;
> > > +
> > > + ret = client->funcs->restore(client);
> > > + DRM_DEV_DEBUG_KMS(dev->dev, "%s: ret=%d\n", client->name, ret);
> > > + if (!ret) /* The first one to return zero gets the privilege to restore */
> > > + break;
> > > + }
> > > + mutex_unlock(&dev->clientlist_mutex);
> > > +}
> > > +
> > > static void drm_client_buffer_delete(struct drm_client_buffer *buffer)
> > > {
> > > struct drm_device *dev = buffer->client->dev;
> > > diff --git a/drivers/gpu/drm/drm_drv.c b/drivers/gpu/drm/drm_drv.c
> > > index e7ff0b03328b..6eb935bb2f92 100644
> > > --- a/drivers/gpu/drm/drm_drv.c
> > > +++ b/drivers/gpu/drm/drm_drv.c
> > > @@ -34,6 +34,7 @@
> > > #include <linux/slab.h>
> > > #include <linux/srcu.h>
> > > +#include <drm/drm_client.h>
> > > #include <drm/drm_drv.h>
> > > #include <drm/drmP.h>
> > > @@ -506,6 +507,7 @@ int drm_dev_init(struct drm_device *dev,
> > > INIT_LIST_HEAD(&dev->filelist);
> > > INIT_LIST_HEAD(&dev->filelist_internal);
> > > + INIT_LIST_HEAD(&dev->clientlist);
> > > INIT_LIST_HEAD(&dev->ctxlist);
> > > INIT_LIST_HEAD(&dev->vmalist);
> > > INIT_LIST_HEAD(&dev->maplist);
> > > @@ -515,6 +517,7 @@ int drm_dev_init(struct drm_device *dev,
> > > spin_lock_init(&dev->event_lock);
> > > mutex_init(&dev->struct_mutex);
> > > mutex_init(&dev->filelist_mutex);
> > > + mutex_init(&dev->clientlist_mutex);
> > > mutex_init(&dev->ctxlist_mutex);
> > > mutex_init(&dev->master_mutex);
> > > @@ -570,6 +573,7 @@ int drm_dev_init(struct drm_device *dev,
> > > err_free:
> > > mutex_destroy(&dev->master_mutex);
> > > mutex_destroy(&dev->ctxlist_mutex);
> > > + mutex_destroy(&dev->clientlist_mutex);
> > > mutex_destroy(&dev->filelist_mutex);
> > > mutex_destroy(&dev->struct_mutex);
> > > return ret;
> > > @@ -604,6 +608,7 @@ void drm_dev_fini(struct drm_device *dev)
> > > mutex_destroy(&dev->master_mutex);
> > > mutex_destroy(&dev->ctxlist_mutex);
> > > + mutex_destroy(&dev->clientlist_mutex);
> > > mutex_destroy(&dev->filelist_mutex);
> > > mutex_destroy(&dev->struct_mutex);
> > > kfree(dev->unique);
> > > @@ -859,6 +864,8 @@ void drm_dev_unregister(struct drm_device *dev)
> > > dev->registered = false;
> > > + drm_client_dev_unregister(dev);
> > > +
> > > if (drm_core_check_feature(dev, DRIVER_MODESET))
> > > drm_modeset_unregister_all(dev);
> > > diff --git a/drivers/gpu/drm/drm_fb_cma_helper.c b/drivers/gpu/drm/drm_fb_cma_helper.c
> > > index 5762a7c441e9..718c7f961d8a 100644
> > > --- a/drivers/gpu/drm/drm_fb_cma_helper.c
> > > +++ b/drivers/gpu/drm/drm_fb_cma_helper.c
> > > @@ -181,7 +181,7 @@ struct drm_fbdev_cma *drm_fbdev_cma_init(struct drm_device *dev,
> > > fb_helper = &fbdev_cma->fb_helper;
> > > - ret = drm_client_new(dev, &fb_helper->client, "fbdev");
> > > + ret = drm_client_new(dev, &fb_helper->client, "fbdev", NULL);
> > > if (ret)
> > > goto err_free;
> > > diff --git a/drivers/gpu/drm/drm_fb_helper.c b/drivers/gpu/drm/drm_fb_helper.c
> > > index 0a0a577ebc3c..bea3a0cb324a 100644
> > > --- a/drivers/gpu/drm/drm_fb_helper.c
> > > +++ b/drivers/gpu/drm/drm_fb_helper.c
> > > @@ -2989,8 +2989,15 @@ static void drm_fbdev_fb_destroy(struct fb_info *info)
> > > }
> > > drm_client_framebuffer_delete(fb_helper->buffer);
> > > - drm_client_release(&fb_helper->client);
> > > - kfree(fb_helper);
> > > + /*
> > > + * FIXME:
> > > + * Remove conditional when all CMA drivers have been moved over to using
> > > + * drm_fbdev_generic_setup().
> > > + */
> > > + if (fb_helper->client.funcs) {
> > > + drm_client_release(&fb_helper->client);
> > > + kfree(fb_helper);
> > > + }
> > > }
> > > static int drm_fbdev_fb_mmap(struct fb_info *info, struct vm_area_struct *vma)
> > > diff --git a/drivers/gpu/drm/drm_file.c b/drivers/gpu/drm/drm_file.c
> > > index 66bb403dc8ab..ffa8dc35515f 100644
> > > --- a/drivers/gpu/drm/drm_file.c
> > > +++ b/drivers/gpu/drm/drm_file.c
> > > @@ -35,6 +35,7 @@
> > > #include <linux/slab.h>
> > > #include <linux/module.h>
> > > +#include <drm/drm_client.h>
> > > #include <drm/drm_file.h>
> > > #include <drm/drmP.h>
> > > @@ -444,6 +445,8 @@ void drm_lastclose(struct drm_device * dev)
> > > if (drm_core_check_feature(dev, DRIVER_LEGACY))
> > > drm_legacy_dev_reinit(dev);
> > > +
> > > + drm_client_dev_restore(dev);
> > > }
> > > /**
> > > diff --git a/drivers/gpu/drm/drm_probe_helper.c b/drivers/gpu/drm/drm_probe_helper.c
> > > index 527743394150..26be57e28a9d 100644
> > > --- a/drivers/gpu/drm/drm_probe_helper.c
> > > +++ b/drivers/gpu/drm/drm_probe_helper.c
> > > @@ -33,6 +33,7 @@
> > > #include <linux/moduleparam.h>
> > > #include <drm/drmP.h>
> > > +#include <drm/drm_client.h>
> > > #include <drm/drm_crtc.h>
> > > #include <drm/drm_fourcc.h>
> > > #include <drm/drm_crtc_helper.h>
> > > @@ -563,6 +564,8 @@ void drm_kms_helper_hotplug_event(struct drm_device *dev)
> > > drm_sysfs_hotplug_event(dev);
> > > if (dev->mode_config.funcs->output_poll_changed)
> > > dev->mode_config.funcs->output_poll_changed(dev);
> > > +
> > > + drm_client_dev_hotplug(dev);
> > > }
> > > EXPORT_SYMBOL(drm_kms_helper_hotplug_event);
> > > diff --git a/include/drm/drm_client.h b/include/drm/drm_client.h
> > > index e366f95d4414..02cbb02714d8 100644
> > > --- a/include/drm/drm_client.h
> > > +++ b/include/drm/drm_client.h
> > > @@ -5,10 +5,66 @@
> > > #include <linux/types.h>
> > > +struct drm_client_dev;
> > > struct drm_device;
> > > struct drm_file;
> > > struct drm_framebuffer;
> > > struct drm_gem_object;
> > > +struct module;
> > > +
> > > +/**
> > > + * struct drm_client_funcs - DRM client callbacks
> > > + */
> > > +struct drm_client_funcs {
> > > + /**
> > > + * @owner: The module owner
> > > + */
> > > + struct module *owner;
> > > +
> > > + /**
> > > + * @release:
> > > + *
> > > + * Called when the reference count is dropped to zero. Users of this
> > > + * callback is responsible for calling drm_client_close() and freeing
> > > + * the client structure.
> > > + *
> > > + * This callback is optional.
> > > + */
> > > + void (*release)(struct drm_client_dev *client);
> > Hm, is this no longer in use?
> >
> > > +
> > > + /**
> > > + * @unregister:
> > > + *
> > > + * Called when &drm_device is unregistered. The client should respond by
> > > + * releasing it's resources using drm_client_put(). If it can't do so
> > > + * due to resoruces being tied up, like fbdev with open file handles,
> > > + * it should release it's resources as soon as possible.
> > This still talks about refcounting and _put ... needs a refresher.
> >
> > > + *
> > > + * This callback is optional.
> > > + */
> > > + void (*unregister)(struct drm_client_dev *client);
> > > +
> > > + /**
> > > + * @restore:
> > > + *
> > > + * Called on drm_lastclose(). The first client instance in the list that
> > > + * returns zero gets the privilege to restore and no more clients are
> > > + * called. This callback is not called after @unregister has been called.
> > > + *
> > > + * This callback is optional.
> > > + */
> > > + int (*restore)(struct drm_client_dev *client);
> > > +
> > > + /**
> > > + * @hotplug:
> > > + *
> > > + * Called on drm_kms_helper_hotplug_event().
> > > + * This callback is not called after @unregister has been called.
> > > + *
> > > + * This callback is optional.
> > > + */
> > > + int (*hotplug)(struct drm_client_dev *client);
> > > +};
> > > /**
> > > * struct drm_client_dev - DRM client instance
> > > @@ -24,6 +80,19 @@ struct drm_client_dev {
> > > */
> > > const char *name;
> > > + /**
> > > + * @list:
> > > + *
> > > + * List of all clients of a DRM device, linked into
> > > + * &drm_device.clientlist. Protected by &drm_device.clientlist_mutex.
> > > + */
> > > + struct list_head list;
> > > +
> > > + /**
> > > + * @funcs: DRM client functions (optional)
> > > + */
> > > + const struct drm_client_funcs *funcs;
> > > +
> > > /**
> > > * @file: DRM file
> > > */
> > > @@ -31,9 +100,13 @@ struct drm_client_dev {
> > > };
> > > int drm_client_new(struct drm_device *dev, struct drm_client_dev *client,
> > > - const char *name);
> > > + const char *name, const struct drm_client_funcs *funcs);
> > > void drm_client_release(struct drm_client_dev *client);
> > > +void drm_client_dev_unregister(struct drm_device *dev);
> > > +void drm_client_dev_hotplug(struct drm_device *dev);
> > > +void drm_client_dev_restore(struct drm_device *dev);
> > > +
> > > /**
> > > * struct drm_client_buffer - DRM client buffer
> > > */
> > > diff --git a/include/drm/drm_device.h b/include/drm/drm_device.h
> > > index 9e29976d4e98..f9c6e0e3aec7 100644
> > > --- a/include/drm/drm_device.h
> > > +++ b/include/drm/drm_device.h
> > > @@ -81,6 +81,20 @@ struct drm_device {
> > > */
> > > struct list_head filelist_internal;
> > > + /**
> > > + * @clientlist_mutex:
> > > + *
> > > + * Protects @clientlist access.
> > > + */
> > > + struct mutex clientlist_mutex;
> > > +
> > > + /**
> > > + * @clientlist:
> > > + *
> > > + * List of in-kernel clients. Protected by @clientlist_mutex.
> > > + */
> > > + struct list_head clientlist;
> > > +
> > > /** \name Memory management */
> > > /*@{ */
> > > struct list_head maplist; /**< Linked list of regions */
> > > --
> > > 2.15.1
> > >
> > > _______________________________________________
> > > dri-devel mailing list
> > > dri-devel@lists.freedesktop.org
> > > https://lists.freedesktop.org/mailman/listinfo/dri-devel
>
--
Daniel Vetter
Software Engineer, Intel Corporation
http://blog.ffwll.ch
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx
^ permalink raw reply [flat|nested] 24+ messages in thread
* ✗ Fi.CI.SPARSE: warning for drm: Add generic fbdev emulation
2018-07-03 16:03 [PATCH v5 0/8] " Noralf Trønnes
@ 2018-07-03 16:18 ` Patchwork
0 siblings, 0 replies; 24+ messages in thread
From: Patchwork @ 2018-07-03 16:18 UTC (permalink / raw)
To: Noralf Trønnes; +Cc: intel-gfx
== Series Details ==
Series: drm: Add generic fbdev emulation
URL : https://patchwork.freedesktop.org/series/45848/
State : warning
== Summary ==
$ dim sparse origin/drm-tip
Commit: drm: Begin an API for in-kernel clients
Okay!
Commit: drm/fb-helper: Add generic fbdev emulation .fb_probe function
+drivers/gpu/drm/drm_fb_helper.c:1006:20: warning: expression using sizeof(void)
+drivers/gpu/drm/drm_fb_helper.c:1006:20: warning: expression using sizeof(void)
+drivers/gpu/drm/drm_fb_helper.c:1007:20: warning: expression using sizeof(void)
+drivers/gpu/drm/drm_fb_helper.c:1007:20: warning: expression using sizeof(void)
+drivers/gpu/drm/drm_fb_helper.c:1008:20: warning: expression using sizeof(void)
+drivers/gpu/drm/drm_fb_helper.c:1008:20: warning: expression using sizeof(void)
+drivers/gpu/drm/drm_fb_helper.c:1009:20: warning: expression using sizeof(void)
+drivers/gpu/drm/drm_fb_helper.c:1009:20: warning: expression using sizeof(void)
-drivers/gpu/drm/drm_fb_helper.c:1006:20: warning: expression using sizeof(void)
-drivers/gpu/drm/drm_fb_helper.c:1006:20: warning: expression using sizeof(void)
-drivers/gpu/drm/drm_fb_helper.c:1007:20: warning: expression using sizeof(void)
-drivers/gpu/drm/drm_fb_helper.c:1007:20: warning: expression using sizeof(void)
-drivers/gpu/drm/drm_fb_helper.c:1008:20: warning: expression using sizeof(void)
-drivers/gpu/drm/drm_fb_helper.c:1008:20: warning: expression using sizeof(void)
-drivers/gpu/drm/drm_fb_helper.c:1009:20: warning: expression using sizeof(void)
-drivers/gpu/drm/drm_fb_helper.c:1009:20: warning: expression using sizeof(void)
Commit: drm/pl111: Set .gem_prime_vmap and .gem_prime_mmap
Okay!
Commit: drm/cma-helper: Use the generic fbdev emulation
Okay!
Commit: drm/debugfs: Add internal client debugfs file
Okay!
Commit: drm/fb-helper: Finish the generic fbdev emulation
Okay!
Commit: drm/tinydrm: Use drm_fbdev_generic_setup()
Okay!
Commit: drm/cma-helper: Remove drm_fb_cma_fbdev_init_with_funcs()
Okay!
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx
^ permalink raw reply [flat|nested] 24+ messages in thread
* ✗ Fi.CI.SPARSE: warning for drm: Add generic fbdev emulation
2018-06-27 13:08 [PATCH v3 0/9] " Noralf Trønnes
@ 2018-06-27 16:53 ` Patchwork
0 siblings, 0 replies; 24+ messages in thread
From: Patchwork @ 2018-06-27 16:53 UTC (permalink / raw)
To: Noralf Trønnes; +Cc: intel-gfx
== Series Details ==
Series: drm: Add generic fbdev emulation
URL : https://patchwork.freedesktop.org/series/45488/
State : warning
== Summary ==
$ dim sparse origin/drm-tip
Commit: drm: Begin an API for in-kernel clients
Okay!
Commit: drm/fb-helper: Add generic fbdev emulation .fb_probe function
+drivers/gpu/drm/drm_fb_helper.c:1006:20: warning: expression using sizeof(void)
+drivers/gpu/drm/drm_fb_helper.c:1006:20: warning: expression using sizeof(void)
+drivers/gpu/drm/drm_fb_helper.c:1007:20: warning: expression using sizeof(void)
+drivers/gpu/drm/drm_fb_helper.c:1007:20: warning: expression using sizeof(void)
+drivers/gpu/drm/drm_fb_helper.c:1008:20: warning: expression using sizeof(void)
+drivers/gpu/drm/drm_fb_helper.c:1008:20: warning: expression using sizeof(void)
+drivers/gpu/drm/drm_fb_helper.c:1009:20: warning: expression using sizeof(void)
+drivers/gpu/drm/drm_fb_helper.c:1009:20: warning: expression using sizeof(void)
-drivers/gpu/drm/drm_fb_helper.c:1006:20: warning: expression using sizeof(void)
-drivers/gpu/drm/drm_fb_helper.c:1006:20: warning: expression using sizeof(void)
-drivers/gpu/drm/drm_fb_helper.c:1007:20: warning: expression using sizeof(void)
-drivers/gpu/drm/drm_fb_helper.c:1007:20: warning: expression using sizeof(void)
-drivers/gpu/drm/drm_fb_helper.c:1008:20: warning: expression using sizeof(void)
-drivers/gpu/drm/drm_fb_helper.c:1008:20: warning: expression using sizeof(void)
-drivers/gpu/drm/drm_fb_helper.c:1009:20: warning: expression using sizeof(void)
-drivers/gpu/drm/drm_fb_helper.c:1009:20: warning: expression using sizeof(void)
Commit: drm/pl111: Set .gem_prime_vmap and .gem_prime_mmap
Okay!
Commit: drm/cma-helper: Use the generic fbdev emulation
Okay!
Commit: drm/client: Add client callbacks
Okay!
Commit: drm/debugfs: Add internal client debugfs file
Okay!
Commit: drm/fb-helper: Finish the generic fbdev emulation
Okay!
Commit: drm/tinydrm: Use drm_fbdev_generic_setup()
Okay!
Commit: drm/cma-helper: Remove drm_fb_cma_fbdev_init_with_funcs()
Okay!
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx
^ permalink raw reply [flat|nested] 24+ messages in thread
* ✗ Fi.CI.SPARSE: warning for drm: Add generic fbdev emulation
2018-06-18 14:17 [PATCH v2 00/12] " Noralf Trønnes
@ 2018-06-18 15:09 ` Patchwork
0 siblings, 0 replies; 24+ messages in thread
From: Patchwork @ 2018-06-18 15:09 UTC (permalink / raw)
To: Noralf Trønnes; +Cc: intel-gfx
== Series Details ==
Series: drm: Add generic fbdev emulation
URL : https://patchwork.freedesktop.org/series/44952/
State : warning
== Summary ==
$ dim sparse origin/drm-tip
Commit: drm: provide management functions for drm_file
Okay!
Commit: drm/file: Don't set master on in-kernel clients
Okay!
Commit: drm: Make ioctls available for in-kernel clients
Okay!
Commit: drm: Begin an API for in-kernel clients
Okay!
Commit: drm/fb-helper: Add generic fbdev emulation .fb_probe function
+ ^~~~~~~~~~~~
+ ^~~~~~~~~~~~~
+ ^~~~~~
+ ^~~~~
+drivers/gpu/drm/drm_fb_helper.c:1005:20: warning: expression using sizeof(void)
+drivers/gpu/drm/drm_fb_helper.c:1005:20: warning: expression using sizeof(void)
+drivers/gpu/drm/drm_fb_helper.c:1006:20: warning: expression using sizeof(void)
+drivers/gpu/drm/drm_fb_helper.c:1006:20: warning: expression using sizeof(void)
+drivers/gpu/drm/drm_fb_helper.c:1007:20: warning: expression using sizeof(void)
+drivers/gpu/drm/drm_fb_helper.c:1007:20: warning: expression using sizeof(void)
+drivers/gpu/drm/drm_fb_helper.c:1008:20: warning: expression using sizeof(void)
+drivers/gpu/drm/drm_fb_helper.c:1008:20: warning: expression using sizeof(void)
-drivers/gpu/drm/drm_fb_helper.c:1005:20: warning: expression using sizeof(void)
-drivers/gpu/drm/drm_fb_helper.c:1005:20: warning: expression using sizeof(void)
-drivers/gpu/drm/drm_fb_helper.c:1006:20: warning: expression using sizeof(void)
-drivers/gpu/drm/drm_fb_helper.c:1006:20: warning: expression using sizeof(void)
-drivers/gpu/drm/drm_fb_helper.c:1007:20: warning: expression using sizeof(void)
-drivers/gpu/drm/drm_fb_helper.c:1007:20: warning: expression using sizeof(void)
-drivers/gpu/drm/drm_fb_helper.c:1008:20: warning: expression using sizeof(void)
-drivers/gpu/drm/drm_fb_helper.c:1008:20: warning: expression using sizeof(void)
+drivers/gpu/drm/drm_fb_helper.c:2976:17: note: ‘fbops’ was declared here
+drivers/gpu/drm/drm_fb_helper.c:2977:8: note: ‘shadow’ was declared here
+drivers/gpu/drm/drm_fb_helper.c:2988:3: warning: ‘fbops’ may be used uninitialized in this function [-Wmaybe-uninitialized]
+drivers/gpu/drm/drm_fb_helper.c:2989:3: warning: ‘shadow’ may be used uninitialized in this function [-Wmaybe-uninitialized]
+drivers/gpu/drm/drm_fb_helper.c: In function ‘drm_fbdev_fb_destroy’:
+ kfree(fbops);
+ struct fb_ops *fbops;
+ vfree(shadow);
+ void *shadow;
Commit: drm/pl111: Set .gem_prime_vmap and .gem_prime_mmap
Okay!
Commit: drm/cma-helper: Use the generic fbdev emulation
Okay!
Commit: drm/client: Add client callbacks
Okay!
Commit: drm/debugfs: Add internal client debugfs file
Okay!
Commit: drm/fb-helper: Finish the generic fbdev emulation
- ^~~~~~
- ^~~~~
-drivers/gpu/drm/drm_fb_helper.c:2979:17: note: ‘fbops’ was declared here
-drivers/gpu/drm/drm_fb_helper.c:2980:8: note: ‘shadow’ was declared here
-drivers/gpu/drm/drm_fb_helper.c: In function ‘drm_fbdev_fb_destroy’:
+drivers/gpu/drm/drm_fb_helper.c: In function ‘drm_fbdev_generic_client_release_do’:
- struct fb_ops *fbops;
- void *shadow;
Commit: drm/tinydrm: Use drm_fbdev_generic_setup()
Okay!
Commit: drm/cma-helper: Remove drm_fb_cma_fbdev_init_with_funcs()
Okay!
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx
^ permalink raw reply [flat|nested] 24+ messages in thread
* ✗ Fi.CI.SPARSE: warning for drm: Add generic fbdev emulation
2018-04-14 11:52 [RFC v4 00/25] " Noralf Trønnes
@ 2018-04-14 15:36 ` Patchwork
0 siblings, 0 replies; 24+ messages in thread
From: Patchwork @ 2018-04-14 15:36 UTC (permalink / raw)
To: Noralf Trønnes; +Cc: intel-gfx
== Series Details ==
Series: drm: Add generic fbdev emulation
URL : https://patchwork.freedesktop.org/series/41713/
State : warning
== Summary ==
$ dim sparse origin/drm-tip
Commit: drm: provide management functions for drm_file
Okay!
Commit: drm/file: Don't set master on in-kernel clients
Okay!
Commit: drm/fb-helper: No need to cache rotation and sw_rotations
Okay!
Commit: drm/fb-helper: Remove drm_fb_helper_debug_enter/leave()
Okay!
Commit: drm/fb-helper: dpms_legacy(): Only set on connectors in use
Okay!
Commit: drm/atomic: Move __drm_atomic_helper_disable_plane/set_config()
Okay!
Commit: drm: Begin an API for in-kernel clients
Okay!
Commit: drm/fb-helper: Use struct drm_client_display
Okay!
Commit: drm/fb-helper: Move modeset commit code to drm_client
Okay!
Commit: drm/connector: Add drm_connector_has_preferred_mode/pick_cmdline_mode()
Okay!
Commit: drm/connector: Add connector array functions
Okay!
Commit: drm/i915: Add drm_driver->initial_client_display callback
Okay!
Commit: drm/fb-helper: Remove struct drm_fb_helper_crtc
Okay!
Commit: drm/fb-helper: Remove struct drm_fb_helper_connector
Okay!
Commit: drm/fb-helper: Move modeset config code to drm_client
Okay!
Commit: drm: Make ioctls available for in-kernel clients
Okay!
Commit: drm/client: Bail out if there's a DRM master
Okay!
Commit: drm/client: Make the display modes available to clients
Okay!
Commit: drm/client: Finish the in-kernel client API
Okay!
Commit: drm/prime: Don't pin module on export for in-kernel clients
Okay!
Commit: drm/fb-helper: Add drm_fb_helper_fb_open/release()
Okay!
Commit: drm/fb-helper: Add generic fbdev emulation
Okay!
Commit: drm: Add DRM device registered notifier
Okay!
Commit: drm/client: Hack: Add bootsplash
+Error in reading or end of file.
Commit: drm/client: Hack: Add DRM VT console client
+Error in reading or end of file.
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx
^ permalink raw reply [flat|nested] 24+ messages in thread
end of thread, other threads:[~2018-07-03 16:18 UTC | newest]
Thread overview: 24+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-07-02 13:54 [PATCH v4 0/9] drm: Add generic fbdev emulation Noralf Trønnes
2018-07-02 13:54 ` [PATCH v4 1/9] drm: Begin an API for in-kernel clients Noralf Trønnes
2018-07-03 7:43 ` Daniel Vetter
2018-07-02 13:54 ` [PATCH v4 2/9] drm/fb-helper: Add generic fbdev emulation .fb_probe function Noralf Trønnes
2018-07-02 13:54 ` [PATCH v4 3/9] drm/pl111: Set .gem_prime_vmap and .gem_prime_mmap Noralf Trønnes
2018-07-02 13:54 ` [PATCH v4 4/9] drm/cma-helper: Use the generic fbdev emulation Noralf Trønnes
2018-07-02 13:54 ` [PATCH v4 5/9] drm/client: Add client callbacks Noralf Trønnes
2018-07-03 7:46 ` Daniel Vetter
2018-07-03 13:07 ` Noralf Trønnes
2018-07-03 13:18 ` Daniel Vetter
2018-07-02 13:54 ` [PATCH v4 6/9] drm/debugfs: Add internal client debugfs file Noralf Trønnes
2018-07-02 13:54 ` [PATCH v4 7/9] drm/fb-helper: Finish the generic fbdev emulation Noralf Trønnes
2018-07-02 13:54 ` [PATCH v4 8/9] drm/tinydrm: Use drm_fbdev_generic_setup() Noralf Trønnes
2018-07-02 15:52 ` David Lechner
2018-07-02 13:54 ` [PATCH v4 9/9] drm/cma-helper: Remove drm_fb_cma_fbdev_init_with_funcs() Noralf Trønnes
2018-07-02 15:57 ` David Lechner
2018-07-02 14:13 ` ✗ Fi.CI.CHECKPATCH: warning for drm: Add generic fbdev emulation Patchwork
2018-07-02 14:17 ` ✗ Fi.CI.SPARSE: " Patchwork
2018-07-02 14:28 ` ✓ Fi.CI.BAT: success " Patchwork
2018-07-02 15:40 ` ✓ Fi.CI.IGT: " Patchwork
-- strict thread matches above, loose matches on Subject: below --
2018-07-03 16:03 [PATCH v5 0/8] " Noralf Trønnes
2018-07-03 16:18 ` ✗ Fi.CI.SPARSE: warning for " Patchwork
2018-06-27 13:08 [PATCH v3 0/9] " Noralf Trønnes
2018-06-27 16:53 ` ✗ Fi.CI.SPARSE: warning for " Patchwork
2018-06-18 14:17 [PATCH v2 00/12] " Noralf Trønnes
2018-06-18 15:09 ` ✗ Fi.CI.SPARSE: warning for " Patchwork
2018-04-14 11:52 [RFC v4 00/25] " Noralf Trønnes
2018-04-14 15:36 ` ✗ Fi.CI.SPARSE: warning for " Patchwork
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.