All of lore.kernel.org
 help / color / mirror / Atom feed
* [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; 25+ 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] 25+ 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; 25+ 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] 25+ 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; 25+ 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] 25+ 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; 25+ 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] 25+ 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; 25+ 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] 25+ 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; 25+ 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] 25+ 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; 25+ 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] 25+ 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; 25+ 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] 25+ 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; 25+ 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] 25+ 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; 25+ 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] 25+ 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; 25+ 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] 25+ 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; 25+ 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] 25+ 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; 25+ 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] 25+ 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; 25+ 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] 25+ 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; 25+ 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] 25+ 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; 25+ 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] 25+ 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; 25+ 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] 25+ 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; 25+ 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] 25+ 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; 25+ 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] 25+ 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; 25+ 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] 25+ messages in thread

* ✗ Fi.CI.CHECKPATCH: warning for drm: Add generic fbdev emulation
  2018-07-03 16:03 [PATCH v5 0/8] " Noralf Trønnes
@ 2018-07-03 16:15 ` Patchwork
  0 siblings, 0 replies; 25+ messages in thread
From: Patchwork @ 2018-07-03 16:15 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 checkpatch origin/drm-tip
ad434a5a0dae drm: Begin an API for in-kernel clients
-:27: WARNING:FILE_PATH_CHANGES: added, moved or deleted file(s), does MAINTAINERS need updating?
#27: 
new file mode 100644

-:32: WARNING:SPDX_LICENSE_TAG: Missing or malformed SPDX-License-Identifier tag in line 1
#32: FILE: Documentation/gpu/drm-client.rst:1:
+=================

total: 0 errors, 2 warnings, 0 checks, 651 lines checked
781f36c686a2 drm/fb-helper: Add generic fbdev emulation .fb_probe function
05745c28977b drm/pl111: Set .gem_prime_vmap and .gem_prime_mmap
da8e3c4bb5c4 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
a5580869f41f drm/debugfs: Add internal client debugfs file
c62fda127952 drm/fb-helper: Finish the generic fbdev emulation
41a2c1ca0b18 drm/tinydrm: Use drm_fbdev_generic_setup()
5b9c5070474f 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] 25+ messages in thread

* ✗ Fi.CI.CHECKPATCH: warning for drm: Add generic fbdev emulation
  2018-06-27 13:08 [PATCH v3 0/9] " Noralf Trønnes
@ 2018-06-27 16:50 ` Patchwork
  0 siblings, 0 replies; 25+ messages in thread
From: Patchwork @ 2018-06-27 16:50 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 checkpatch origin/drm-tip
b94e8e78c556 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
b405648a927c drm/fb-helper: Add generic fbdev emulation .fb_probe function
6b6b258ed3ef drm/pl111: Set .gem_prime_vmap and .gem_prime_mmap
6e28794b79ab 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, 426 lines checked
4c842b91d792 drm/client: Add client callbacks
31ff61ad53c0 drm/debugfs: Add internal client debugfs file
06da1c06d25e drm/fb-helper: Finish the generic fbdev emulation
0cf48089f8dd drm/tinydrm: Use drm_fbdev_generic_setup()
c240e5f96c88 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] 25+ messages in thread

* ✗ Fi.CI.CHECKPATCH: warning for drm: Add generic fbdev emulation
  2018-06-18 14:17 [PATCH v2 00/12] " Noralf Trønnes
@ 2018-06-18 15:05 ` Patchwork
  0 siblings, 0 replies; 25+ messages in thread
From: Patchwork @ 2018-06-18 15:05 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 checkpatch origin/drm-tip
59e39279c0f6 drm: provide management functions for drm_file
edfcad58ba6d drm/file: Don't set master on in-kernel clients
b60d5cacea01 drm: Make ioctls available for in-kernel clients
58174cc2f73a 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, 450 lines checked
31fdd3b6e524 drm/fb-helper: Add generic fbdev emulation .fb_probe function
2cb53d805040 drm/pl111: Set .gem_prime_vmap and .gem_prime_mmap
6987226752e9 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, 426 lines checked
1b2f56748578 drm/client: Add client callbacks
b41445462f13 drm/debugfs: Add internal client debugfs file
520a6c2e290e drm/fb-helper: Finish the generic fbdev emulation
4cab6cf795bb drm/tinydrm: Use drm_fbdev_generic_setup()
9f2ddc3cbcc0 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] 25+ messages in thread

* ✗ Fi.CI.CHECKPATCH: warning for drm: Add generic fbdev emulation
  2018-05-23 14:34 [PATCH 0/9] " Noralf Trønnes
@ 2018-05-23 15:20 ` Patchwork
  0 siblings, 0 replies; 25+ messages in thread
From: Patchwork @ 2018-05-23 15:20 UTC (permalink / raw)
  To: Noralf Trønnes; +Cc: intel-gfx

== Series Details ==

Series: drm: Add generic fbdev emulation
URL   : https://patchwork.freedesktop.org/series/43638/
State : warning

== Summary ==

$ dim checkpatch origin/drm-tip
abc90d1666f9 drm: provide management functions for drm_file
148aad6128c8 drm/file: Don't set master on in-kernel clients
1843c1bf6fae drm: Make ioctls available for in-kernel clients
ac381c45d81c drm: Begin an API for in-kernel clients
-:25: WARNING:FILE_PATH_CHANGES: added, moved or deleted file(s), does MAINTAINERS need updating?
#25: 
new file mode 100644

-:30: WARNING:SPDX_LICENSE_TAG: Missing or malformed SPDX-License-Identifier tag in line 1
#30: FILE: Documentation/gpu/drm-client.rst:1:
+=================

total: 0 errors, 2 warnings, 0 checks, 397 lines checked
28bc4dff4637 drm/fb-helper: Add generic fbdev emulation .fb_probe function
1c01b1e8884b drm/pl111: Set .gem_prime_vmap and .gem_prime_mmap
48b6f475bcf6 drm/cma-helper: Use the generic fbdev emulation
-:358: CHECK:PARENTHESIS_ALIGNMENT: Alignment should match open parenthesis
#358: 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, 429 lines checked
4b49053e090b drm/client: Add client callbacks
cf058dd0dc67 drm/fb-helper: Finish the generic fbdev emulation

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 25+ messages in thread

* ✗ Fi.CI.CHECKPATCH: warning for drm: Add generic fbdev emulation
  2018-04-14 11:52 [RFC v4 00/25] " Noralf Trønnes
@ 2018-04-14 15:30 ` Patchwork
  0 siblings, 0 replies; 25+ messages in thread
From: Patchwork @ 2018-04-14 15:30 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 checkpatch origin/drm-tip
81446b0d0a5c drm: provide management functions for drm_file
60830bd79f28 drm/file: Don't set master on in-kernel clients
cc4b5605be11 drm/fb-helper: No need to cache rotation and sw_rotations
714bf7eb3f72 drm/fb-helper: Remove drm_fb_helper_debug_enter/leave()
a9fd09042c1e drm/fb-helper: dpms_legacy(): Only set on connectors in use
a3df7c91a4e7 drm/atomic: Move __drm_atomic_helper_disable_plane/set_config()
-:84: CHECK:PARENTHESIS_ALIGNMENT: Alignment should match open parenthesis
#84: FILE: drivers/gpu/drm/drm_atomic.c:2122:
+		new_conn_state = drm_atomic_get_connector_state(state,
+							    set->connectors[i]);

total: 0 errors, 0 warnings, 1 checks, 413 lines checked
2c5762e457a0 drm: Begin an API for in-kernel clients
-:29: WARNING:FILE_PATH_CHANGES: added, moved or deleted file(s), does MAINTAINERS need updating?
#29: 
new file mode 100644

-:199: CHECK:MACRO_ARG_REUSE: Macro argument reuse 'modeset' - possible side-effects?
#199: FILE: include/drm/drm_client.h:41:
+#define drm_client_display_for_each_modeset(modeset, display) \
+	for (modeset = display->modesets; modeset->crtc; modeset++)

total: 0 errors, 1 warnings, 1 checks, 171 lines checked
71f15d3943b3 drm/fb-helper: Use struct drm_client_display
89961006fcc4 drm/fb-helper: Move modeset commit code to drm_client
-:132: WARNING:LONG_LINE: line over 100 characters
#132: FILE: drivers/gpu/drm/drm_client.c:224:
+		if (drm_client_display_panel_rotation(mode_set->connectors[0], primary, &rotation)) {

-:148: WARNING:LONG_LINE: line over 100 characters
#148: FILE: drivers/gpu/drm/drm_client.c:240:
+			struct drm_crtc_state *crtc_state = drm_atomic_get_new_crtc_state(state, crtc);

-:251: CHECK:PARENTHESIS_ALIGNMENT: Alignment should match open parenthesis
#251: FILE: drivers/gpu/drm/drm_client.c:343:
+			drm_object_property_set_value(&connector->base,
+				dev->mode_config.dpms_property, dpms_mode);

total: 0 errors, 2 warnings, 1 checks, 506 lines checked
719d6d0d7abf drm/connector: Add drm_connector_has_preferred_mode/pick_cmdline_mode()
-:218: WARNING:LONG_LINE: line over 100 characters
#218: FILE: drivers/gpu/drm/drm_fb_helper.c:1980:
+			modes[i] = drm_connector_has_preferred_mode(fb_helper_conn->connector, width, height);

total: 0 errors, 1 warnings, 0 checks, 263 lines checked
44ea371420ed drm/connector: Add connector array functions
2713f41fa8a7 drm/i915: Add drm_driver->initial_client_display callback
-:359: CHECK:PARENTHESIS_ALIGNMENT: Alignment should match open parenthesis
#359: FILE: include/drm/drm_drv.h:575:
+	struct drm_client_display *(*initial_client_display)(struct drm_device *dev,
+					unsigned int width, unsigned int height);

total: 0 errors, 0 warnings, 1 checks, 309 lines checked
2ba3ab46560f drm/fb-helper: Remove struct drm_fb_helper_crtc
85e36ecc105f drm/fb-helper: Remove struct drm_fb_helper_connector
-:485: WARNING:LONG_LINE: line over 100 characters
#485: FILE: drivers/gpu/drm/drm_fb_helper.c:1735:
+				      connector->base.id, connector->tile_group ? connector->tile_group->id : 0);

-:494: WARNING:LONG_LINE: line over 100 characters
#494: FILE: drivers/gpu/drm/drm_fb_helper.c:1740:
+			modes[i] = list_first_entry_or_null(&connector->modes, struct drm_display_mode, head);

total: 0 errors, 2 warnings, 0 checks, 662 lines checked
96d053114bea drm/fb-helper: Move modeset config code to drm_client
b5e0fd91d06a drm: Make ioctls available for in-kernel clients
-:265: CHECK:PARENTHESIS_ALIGNMENT: Alignment should match open parenthesis
#265: FILE: drivers/gpu/drm/drm_ioc32.c:888:
+	err = drm_ioctl_kernel(file, drm_mode_addfb2_ioctl, &req64,
 				DRM_CONTROL_ALLOW|DRM_UNLOCKED);

-:278: CHECK:SPACING: spaces preferred around that '|' (ctx:VxV)
#278: FILE: drivers/gpu/drm/drm_ioctl.c:638:
+	DRM_IOCTL_DEF(DRM_IOCTL_MODE_ADDFB2, drm_mode_addfb2_ioctl, DRM_CONTROL_ALLOW|DRM_UNLOCKED),
 	                                                                             ^

-:279: CHECK:SPACING: spaces preferred around that '|' (ctx:VxV)
#279: FILE: drivers/gpu/drm/drm_ioctl.c:639:
+	DRM_IOCTL_DEF(DRM_IOCTL_MODE_RMFB, drm_mode_rmfb_ioctl, DRM_CONTROL_ALLOW|DRM_UNLOCKED),
 	                                                                         ^

total: 0 errors, 0 warnings, 3 checks, 250 lines checked
485cb25f026f drm/client: Bail out if there's a DRM master
ef429a8df150 drm/client: Make the display modes available to clients
c68e1bc590f2 drm/client: Finish the in-kernel client API
-:943: CHECK:UNCOMMENTED_DEFINITION: struct mutex definition without comment
#943: FILE: include/drm/drm_device.h:79:
+	struct mutex clientlist_mutex;

total: 0 errors, 0 warnings, 1 checks, 879 lines checked
9f9e987688eb drm/prime: Don't pin module on export for in-kernel clients
63ae31620111 drm/fb-helper: Add drm_fb_helper_fb_open/release()
312ecf074c7e drm/fb-helper: Add generic fbdev emulation
0d0077bf0537 drm: Add DRM device registered notifier
5cd701e1286b drm/client: Hack: Add bootsplash
-:39: WARNING:FILE_PATH_CHANGES: added, moved or deleted file(s), does MAINTAINERS need updating?
#39: 
new file mode 100644

-:94: CHECK:PARENTHESIS_ALIGNMENT: Alignment should match open parenthesis
#94: FILE: drivers/gpu/drm/client/drm_bootsplash.c:36:
+static int drm_bootsplash_keyboard_notifier_call(struct notifier_block *blk,
+				  unsigned long code, void *_param)

total: 0 errors, 1 warnings, 1 checks, 311 lines checked
50d6c1c0bbaa drm/client: Hack: Add DRM VT console client
-:40: WARNING:FILE_PATH_CHANGES: added, moved or deleted file(s), does MAINTAINERS need updating?
#40: 
new file mode 100644

-:93: CHECK:UNCOMMENTED_DEFINITION: struct mutex definition without comment
#93: FILE: drivers/gpu/drm/client/drm_vtcon.c:40:
+	struct mutex lock;

-:541: WARNING:LONG_LINE: line over 100 characters
#541: FILE: drivers/gpu/drm/client/drm_vtcon.c:488:
+		memmove(drm_vtcon_vc->text_buf, drm_vtcon_vc->text_buf + vc->vc_cols, count * sizeof(u16));

total: 0 errors, 2 warnings, 1 checks, 804 lines checked

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 25+ messages in thread

end of thread, other threads:[~2018-07-03 16:15 UTC | newest]

Thread overview: 25+ 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:15 ` ✗ Fi.CI.CHECKPATCH: warning for " Patchwork
2018-06-27 13:08 [PATCH v3 0/9] " Noralf Trønnes
2018-06-27 16:50 ` ✗ Fi.CI.CHECKPATCH: warning for " Patchwork
2018-06-18 14:17 [PATCH v2 00/12] " Noralf Trønnes
2018-06-18 15:05 ` ✗ Fi.CI.CHECKPATCH: warning for " Patchwork
2018-05-23 14:34 [PATCH 0/9] " Noralf Trønnes
2018-05-23 15:20 ` ✗ Fi.CI.CHECKPATCH: warning for " Patchwork
2018-04-14 11:52 [RFC v4 00/25] " Noralf Trønnes
2018-04-14 15:30 ` ✗ Fi.CI.CHECKPATCH: 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.