Re: [PATCH v2 01/22] drm: Add GEM backed framebuffer library

2017-08-11 Thread Daniel Vetter
On Thu, Aug 10, 2017 at 08:55:59PM +0200, Noralf Trønnes wrote:
> 
> Den 09.08.2017 22.04, skrev Daniel Vetter:
> > On Wed, Aug 09, 2017 at 12:11:04PM +0200, Noralf Trønnes wrote:
> > > This library provides helpers for drivers that don't subclass
> > > drm_framebuffer and are backed by drm_gem_object. The code is
> > > taken from drm_fb_cma_helper.
> > > 
> > > Signed-off-by: Noralf Trønnes 
> > lgtm, a few nits below to polish the documentation. With those addressed:
> > 
> > Reviewed-by: Daniel Vetter 
> 
> [...]
> 
> > > +/**
> > > + * drm_gem_fb_alloc - Allocate GEM backed framebuffer
> > > + * @dev: DRM device
> > > + * @mode_cmd: metadata from the userspace fb creation request
> > > + * @obj: GEM object(s) backing the framebuffer
> > > + * @num_planes: Number of planes
> > > + * @funcs: vtable to be used for the new framebuffer object
> > This kinda puts all the warnings from drm_framebuffer_init() under the
> > rug, so not enough text for such a tricky function. Proposal
> > 
> > "This allocates a  drm_framebuffer and publishes it by calling
> > drm_framebuffer_init().
> > 
> > IMPORTANT:
> > All checking and validation must be done before calling this function.
> > Framebuffers are supposed to be invariant over their lifetime, which means
> > evil userspace could otherwise trick the kernel into using unvalidated
> > framebuffer objects."
> > 
> > Not sure whether that kills your use-cases for this, in which case we
> > probably need to open-code this in all callers. Or remove the call to
> > drm_framebuffer_init() and place the driver's validation code between the
> > call to _alloc() and _init().
> > 
> > Maybe we should even change _init() to be called _register() to avoid this
> > bug in the future.
> 
> The only reason drm_gem_fb_alloc() is exported is to add framebuffers
> for fbdev emulation. So maybe it's better to hide that function and make
> an explicit one:

Yeah if you can just use this one here instead of the other, that looks
like the safer interface.

Aside: Do we really need to export this if it's only used for fbdev
allocation? Or is your plan that drivers will call this (like the cma
helpers already do)?

Anyway, my r-b stands if you add this function and unexport the alloc one
(and then I don't think it needs kerneldoc).
-Daniel

> 
> /**
>  * drm_gem_fbdev_fb_create - Create a drm_framebuffer for fbdev emulation
>  * @dev: DRM device
>  * @sizes: fbdev size description
>  * @pitch_align: optional pitch alignment
>  * @obj: GEM object backing the framebuffer
>  * @funcs: vtable to be used for the new framebuffer object
>  *
>  * This function creates a framebuffer for use with fbdev emulation.
>  *
>  * Returns:
>  * Pointer to a drm_framebuffer on success or an error pointer on failure.
>  */
> struct drm_framebuffer *
> drm_gem_fbdev_fb_create(struct drm_device *dev,
> struct drm_fb_helper_surface_size *sizes,
> unsigned int pitch_align, struct drm_gem_object *obj,
> const struct drm_framebuffer_funcs *funcs)
> {
> struct drm_mode_fb_cmd2 mode_cmd = { 0 };
> 
> mode_cmd.width = sizes->surface_width;
> mode_cmd.height = sizes->surface_height;
> mode_cmd.pitches[0] = sizes->surface_width *
>   DIV_ROUND_UP(sizes->surface_bpp, 8);
> if (pitch_align)
> mode_cmd.pitches[0] = roundup(mode_cmd.pitches[0],
>   pitch_align);
> mode_cmd.pixel_format = drm_mode_legacy_fb_format(sizes->surface_bpp,
> sizes->surface_depth);
> if (obj->size < mode_cmd.pitches[0] * mode_cmd.height)
> return ERR_PTR(-EINVAL);
> 
> return drm_gem_fb_alloc(dev, _cmd, , 1, funcs);
> }
> EXPORT_SYMBOL(drm_gem_fbdev_fb_create);
> 
> 
> Noralf.
> 
> > But that's just all aside, from your create_with_funcs example below it
> > all looks good.
> > 
> > > + *
> > > + * Returns:
> > > + * Allocated struct drm_framebuffer * or error encoded pointer.
> > > + */
> > > +struct drm_framebuffer *
> > > +drm_gem_fb_alloc(struct drm_device *dev,
> > > +  const struct drm_mode_fb_cmd2 *mode_cmd,
> > > +  struct drm_gem_object **obj, unsigned int num_planes,
> > > +  const struct drm_framebuffer_funcs *funcs)
> > > +{
> > > + struct drm_framebuffer *fb;
> > > + int ret, i;
> > > +
> > > + fb = kzalloc(sizeof(*fb), GFP_KERNEL);
> > > + if (!fb)
> > > + return ERR_PTR(-ENOMEM);
> > > +
> > > + drm_helper_mode_fill_fb_struct(dev, fb, mode_cmd);
> > > +
> > > + for (i = 0; i < num_planes; i++)
> > > + fb->obj[i] = obj[i];
> > > +
> > > + ret = drm_framebuffer_init(dev, fb, funcs);
> > > + if (ret) {
> > > + DRM_DEV_ERROR(dev->dev, "Failed to init framebuffer: %d\n",
> > > +   ret);
> > > + kfree(fb);
> > > + return ERR_PTR(ret);
> > > + }
> > > +
> > > + return fb;
> > > +}
> > > +EXPORT_SYMBOL(drm_gem_fb_alloc);
> > > +
> > > +/**
> > > + * 

Re: [PATCH v2 01/22] drm: Add GEM backed framebuffer library

2017-08-10 Thread Noralf Trønnes


Den 09.08.2017 22.04, skrev Daniel Vetter:

On Wed, Aug 09, 2017 at 12:11:04PM +0200, Noralf Trønnes wrote:

This library provides helpers for drivers that don't subclass
drm_framebuffer and are backed by drm_gem_object. The code is
taken from drm_fb_cma_helper.

Signed-off-by: Noralf Trønnes 

lgtm, a few nits below to polish the documentation. With those addressed:

Reviewed-by: Daniel Vetter 


[...]


+/**
+ * drm_gem_fb_alloc - Allocate GEM backed framebuffer
+ * @dev: DRM device
+ * @mode_cmd: metadata from the userspace fb creation request
+ * @obj: GEM object(s) backing the framebuffer
+ * @num_planes: Number of planes
+ * @funcs: vtable to be used for the new framebuffer object

This kinda puts all the warnings from drm_framebuffer_init() under the
rug, so not enough text for such a tricky function. Proposal

"This allocates a  drm_framebuffer and publishes it by calling
drm_framebuffer_init().

IMPORTANT:
All checking and validation must be done before calling this function.
Framebuffers are supposed to be invariant over their lifetime, which means
evil userspace could otherwise trick the kernel into using unvalidated
framebuffer objects."

Not sure whether that kills your use-cases for this, in which case we
probably need to open-code this in all callers. Or remove the call to
drm_framebuffer_init() and place the driver's validation code between the
call to _alloc() and _init().

Maybe we should even change _init() to be called _register() to avoid this
bug in the future.


The only reason drm_gem_fb_alloc() is exported is to add framebuffers
for fbdev emulation. So maybe it's better to hide that function and make
an explicit one:

/**
 * drm_gem_fbdev_fb_create - Create a drm_framebuffer for fbdev emulation
 * @dev: DRM device
 * @sizes: fbdev size description
 * @pitch_align: optional pitch alignment
 * @obj: GEM object backing the framebuffer
 * @funcs: vtable to be used for the new framebuffer object
 *
 * This function creates a framebuffer for use with fbdev emulation.
 *
 * Returns:
 * Pointer to a drm_framebuffer on success or an error pointer on failure.
 */
struct drm_framebuffer *
drm_gem_fbdev_fb_create(struct drm_device *dev,
struct drm_fb_helper_surface_size *sizes,
unsigned int pitch_align, struct drm_gem_object *obj,
const struct drm_framebuffer_funcs *funcs)
{
struct drm_mode_fb_cmd2 mode_cmd = { 0 };

mode_cmd.width = sizes->surface_width;
mode_cmd.height = sizes->surface_height;
mode_cmd.pitches[0] = sizes->surface_width *
  DIV_ROUND_UP(sizes->surface_bpp, 8);
if (pitch_align)
mode_cmd.pitches[0] = roundup(mode_cmd.pitches[0],
  pitch_align);
mode_cmd.pixel_format = drm_mode_legacy_fb_format(sizes->surface_bpp,
sizes->surface_depth);
if (obj->size < mode_cmd.pitches[0] * mode_cmd.height)
return ERR_PTR(-EINVAL);

return drm_gem_fb_alloc(dev, _cmd, , 1, funcs);
}
EXPORT_SYMBOL(drm_gem_fbdev_fb_create);


Noralf.


But that's just all aside, from your create_with_funcs example below it
all looks good.


+ *
+ * Returns:
+ * Allocated struct drm_framebuffer * or error encoded pointer.
+ */
+struct drm_framebuffer *
+drm_gem_fb_alloc(struct drm_device *dev,
+const struct drm_mode_fb_cmd2 *mode_cmd,
+struct drm_gem_object **obj, unsigned int num_planes,
+const struct drm_framebuffer_funcs *funcs)
+{
+   struct drm_framebuffer *fb;
+   int ret, i;
+
+   fb = kzalloc(sizeof(*fb), GFP_KERNEL);
+   if (!fb)
+   return ERR_PTR(-ENOMEM);
+
+   drm_helper_mode_fill_fb_struct(dev, fb, mode_cmd);
+
+   for (i = 0; i < num_planes; i++)
+   fb->obj[i] = obj[i];
+
+   ret = drm_framebuffer_init(dev, fb, funcs);
+   if (ret) {
+   DRM_DEV_ERROR(dev->dev, "Failed to init framebuffer: %d\n",
+ ret);
+   kfree(fb);
+   return ERR_PTR(ret);
+   }
+
+   return fb;
+}
+EXPORT_SYMBOL(drm_gem_fb_alloc);
+
+/**
+ * drm_gem_fb_destroy - Free GEM backed framebuffer
+ * @fb: DRM framebuffer
+ *
+ * Frees a GEM backed framebuffer with it's backing buffer(s) and the structure
+ * itself. Drivers can use this as their _framebuffer_funcs->destroy
+ * callback.
+ */
+void drm_gem_fb_destroy(struct drm_framebuffer *fb)
+{
+   int i;
+
+   for (i = 0; i < 4; i++) {
+   if (fb->obj[i])
+   drm_gem_object_put_unlocked(fb->obj[i]);
+   }
+
+   drm_framebuffer_cleanup(fb);
+   kfree(fb);
+}
+EXPORT_SYMBOL(drm_gem_fb_destroy);
+
+/**
+ * drm_gem_fb_create_handle - Create handle for GEM backed framebuffer
+ * @fb: DRM framebuffer
+ * @file: drm file
+ * @handle: handle created
+ *
+ * Drivers can use this as their _framebuffer_funcs->create_handle
+ * callback.
+ *
+ * Returns:
+ * 0 on success or a 

Re: [PATCH v2 01/22] drm: Add GEM backed framebuffer library

2017-08-10 Thread Joe Kniss
A few nits.

On Wed, Aug 9, 2017 at 3:12 AM,
<dri-devel-requ...@lists.freedesktop.org> wrote:
> Send dri-devel mailing list submissions to
> dri-devel@lists.freedesktop.org
>
> To subscribe or unsubscribe via the World Wide Web, visit
> https://lists.freedesktop.org/mailman/listinfo/dri-devel
> or, via email, send a message with subject or body 'help' to
> dri-devel-requ...@lists.freedesktop.org
>
> You can reach the person managing the list at
> dri-devel-ow...@lists.freedesktop.org
>
> When replying, please edit your Subject line so it is more specific
> than "Re: Contents of dri-devel digest..."
>
>
> Today's Topics:
>
>1. [PATCH v2 06/22] drm/arm/mali: Use drm_gem_fb_create()
>   (Noralf Trønnes)
>2. [PATCH v2 01/22] drm: Add GEM backed framebuffer library
>   (Noralf Trønnes)
>3. [PATCH v2 04/22] drm/arc: Use drm_gem_fb_create()
>   (Noralf Trønnes)
>4. [PATCH v2 09/22] drm/hisilicon/kirin: Use drm_gem_fb_create()
>   (Noralf Trønnes)
>5. [PATCH v2 03/22] drm/tinydrm: Use drm_gem_framebuffer_helper
>   (Noralf Trønnes)
>6. [PATCH v2 05/22] drm/arm/hdlcd: Use drm_gem_fb_create()
>   (Noralf Trønnes)
>
>
> --
>
> Message: 1
> Date: Wed,  9 Aug 2017 12:11:09 +0200
> From: Noralf Trønnes <nor...@tronnes.org>
> To: dri-devel@lists.freedesktop.org
> Cc: narmstr...@baylibre.com, liviu.du...@arm.com,
> laurent.pinch...@ideasonboard.com, ma...@denx.de,
> boris.brezil...@free-electrons.com, abrod...@synopsys.com,
> z.liuxinli...@hisilicon.com, kong.kongxin...@hisilicon.com,
> tomi.valkei...@ti.com, puck.c...@hisilicon.com, jsa...@ti.com,
> vincent.abr...@st.com, alison.w...@freescale.com,
> philippe.co...@st.com, yannick.fer...@st.com, zourongr...@gmail.com,
> maxime.rip...@free-electrons.com, shawn...@kernel.org
> Subject: [PATCH v2 06/22] drm/arm/mali: Use drm_gem_fb_create()
> Message-ID: <1502273485-62636-7-git-send-email-nor...@tronnes.org>
> Content-Type: text/plain; charset=UTF-8
>
> drm_fb_cma_create() is just a wrapper around drm_gem_fb_create() now,
> so use the function directly.
>
> Cc: Liviu Dudau <liviu.du...@arm.com>
> Cc: Brian Starkey <brian.star...@arm.com>
> Signed-off-by: Noralf Trønnes <nor...@tronnes.org>
> ---
>  drivers/gpu/drm/arm/malidp_drv.c | 3 ++-
>  1 file changed, 2 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/gpu/drm/arm/malidp_drv.c 
> b/drivers/gpu/drm/arm/malidp_drv.c
> index 1a57cc2..b894466 100644
> --- a/drivers/gpu/drm/arm/malidp_drv.c
> +++ b/drivers/gpu/drm/arm/malidp_drv.c
> @@ -26,6 +26,7 @@
>  #include 
>  #include 
>  #include 
> +#include 
>  #include 
>
>  #include "malidp_drv.h"
> @@ -249,7 +250,7 @@ static const struct drm_mode_config_helper_funcs 
> malidp_mode_config_helpers = {
>  };
>
>  static const struct drm_mode_config_funcs malidp_mode_config_funcs = {
> -   .fb_create = drm_fb_cma_create,
> +   .fb_create = drm_gem_fb_create,
> .output_poll_changed = malidp_output_poll_changed,
> .atomic_check = drm_atomic_helper_check,
> .atomic_commit = drm_atomic_helper_commit,
> --
> 2.7.4
>
>
>
> --
>
> Message: 2
> Date: Wed,  9 Aug 2017 12:11:04 +0200
> From: Noralf Trønnes <nor...@tronnes.org>
> To: dri-devel@lists.freedesktop.org
> Cc: narmstr...@baylibre.com, liviu.du...@arm.com,
> laurent.pinch...@ideasonboard.com, ma...@denx.de,
> boris.brezil...@free-electrons.com, abrod...@synopsys.com,
> z.liuxinli...@hisilicon.com, kong.kongxin...@hisilicon.com,
> tomi.valkei...@ti.com, puck.c...@hisilicon.com, jsa...@ti.com,
> vincent.abr...@st.com, alison.w...@freescale.com,
> philippe.co...@st.com, yannick.fer...@st.com, zourongr...@gmail.com,
> maxime.rip...@free-electrons.com, shawn...@kernel.org
> Subject: [PATCH v2 01/22] drm: Add GEM backed framebuffer library
> Message-ID: <1502273485-62636-2-git-send-email-nor...@tronnes.org>
> Content-Type: text/plain; charset=UTF-8
>
> This library provides helpers for drivers that don't subclass
> drm_framebuffer and are backed by drm_gem_object. The code is
> taken from drm_fb_cma_helper.
>
> Signed-off-by: Noralf Trønnes <nor...@tronnes.org>
> ---
>  Documentation/gpu/drm-kms-helpers.rst|   9 +
>  drivers/gpu/drm/Makefile |   2 +-
>  drivers/gpu/drm/drm_gem_framebuffer_helper.c | 252 
> +++
>  include/drm/drm_framebuffer.h   

Re: [PATCH v2 01/22] drm: Add GEM backed framebuffer library

2017-08-09 Thread Daniel Vetter
On Wed, Aug 09, 2017 at 12:11:04PM +0200, Noralf Trønnes wrote:
> This library provides helpers for drivers that don't subclass
> drm_framebuffer and are backed by drm_gem_object. The code is
> taken from drm_fb_cma_helper.
> 
> Signed-off-by: Noralf Trønnes 

lgtm, a few nits below to polish the documentation. With those addressed:

Reviewed-by: Daniel Vetter 
> ---
>  Documentation/gpu/drm-kms-helpers.rst|   9 +
>  drivers/gpu/drm/Makefile |   2 +-
>  drivers/gpu/drm/drm_gem_framebuffer_helper.c | 252 
> +++
>  include/drm/drm_framebuffer.h|   4 +
>  include/drm/drm_gem_framebuffer_helper.h |  35 
>  5 files changed, 301 insertions(+), 1 deletion(-)
>  create mode 100644 drivers/gpu/drm/drm_gem_framebuffer_helper.c
>  create mode 100644 include/drm/drm_gem_framebuffer_helper.h
> 
> diff --git a/Documentation/gpu/drm-kms-helpers.rst 
> b/Documentation/gpu/drm-kms-helpers.rst
> index 7c5e254..13dd237 100644
> --- a/Documentation/gpu/drm-kms-helpers.rst
> +++ b/Documentation/gpu/drm-kms-helpers.rst
> @@ -296,3 +296,12 @@ Auxiliary Modeset Helpers
>  
>  .. kernel-doc:: drivers/gpu/drm/drm_modeset_helper.c
> :export:
> +
> +Framebuffer GEM Helper Reference
> +
> +
> +.. kernel-doc:: drivers/gpu/drm/drm_gem_framebuffer_helper.c
> +   :doc: overview
> +
> +.. kernel-doc:: drivers/gpu/drm/drm_gem_framebuffer_helper.c
> +   :export:
> diff --git a/drivers/gpu/drm/Makefile b/drivers/gpu/drm/Makefile
> index 24a066e..a8acc19 100644
> --- a/drivers/gpu/drm/Makefile
> +++ b/drivers/gpu/drm/Makefile
> @@ -33,7 +33,7 @@ drm_kms_helper-y := drm_crtc_helper.o drm_dp_helper.o 
> drm_probe_helper.o \
>   drm_plane_helper.o drm_dp_mst_topology.o drm_atomic_helper.o \
>   drm_kms_helper_common.o drm_dp_dual_mode_helper.o \
>   drm_simple_kms_helper.o drm_modeset_helper.o \
> - drm_scdc_helper.o
> + drm_scdc_helper.o drm_gem_framebuffer_helper.o
>  
>  drm_kms_helper-$(CONFIG_DRM_PANEL_BRIDGE) += bridge/panel.o
>  drm_kms_helper-$(CONFIG_DRM_LOAD_EDID_FIRMWARE) += drm_edid_load.o
> diff --git a/drivers/gpu/drm/drm_gem_framebuffer_helper.c 
> b/drivers/gpu/drm/drm_gem_framebuffer_helper.c
> new file mode 100644
> index 000..41a506c
> --- /dev/null
> +++ b/drivers/gpu/drm/drm_gem_framebuffer_helper.c
> @@ -0,0 +1,252 @@
> +/*
> + * drm gem framebuffer helper functions
> + *
> + * Copyright (C) 2017 Noralf Trønnes
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License as published by
> + * the Free Software Foundation; either version 2 of the License, or
> + * (at your option) any later version.
> + */
> +
> +#include 
> +#include 
> +#include 
> +#include 
> +
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +
> +/**
> + * DOC: overview
> + *
> + * This library provides helpers for drivers that don't subclass
> + * _framebuffer and are backed by _gem_object.

I'd rephrase this as "and use _gem_object for their backing storage".

Maybe also drop a hint for the main entry point for drivers into this
library:

"Drivers without addition needs to validate framebuffers can simply use
drm_gem_fb_create() and everything is wired up automatically. But all
parts can be used individually, too."

> + */
> +
> +/**
> + * drm_gem_fb_get_obj() - Get GEM object for framebuffer
> + * @fb: The framebuffer
> + * @plane: Which plane
> + *
> + * Returns the GEM object for given framebuffer.
> + */
> +struct drm_gem_object *drm_gem_fb_get_obj(struct drm_framebuffer *fb,
> +   unsigned int plane)
> +{
> + if (plane >= 4)
> + return NULL;
> +
> + return fb->obj[plane];
> +}
> +EXPORT_SYMBOL_GPL(drm_gem_fb_get_obj);
> +
> +/**
> + * drm_gem_fb_alloc - Allocate GEM backed framebuffer
> + * @dev: DRM device
> + * @mode_cmd: metadata from the userspace fb creation request
> + * @obj: GEM object(s) backing the framebuffer
> + * @num_planes: Number of planes
> + * @funcs: vtable to be used for the new framebuffer object

This kinda puts all the warnings from drm_framebuffer_init() under the
rug, so not enough text for such a tricky function. Proposal

"This allocates a  drm_framebuffer and publishes it by calling
drm_framebuffer_init().

IMPORTANT:
All checking and validation must be done before calling this function.
Framebuffers are supposed to be invariant over their lifetime, which means
evil userspace could otherwise trick the kernel into using unvalidated
framebuffer objects."

Not sure whether that kills your use-cases for this, in which case we
probably need to open-code this in all callers. Or remove the call to
drm_framebuffer_init() and place the driver's validation code between the
call to _alloc() and _init().

Maybe we should even 

[PATCH v2 01/22] drm: Add GEM backed framebuffer library

2017-08-09 Thread Noralf Trønnes
This library provides helpers for drivers that don't subclass
drm_framebuffer and are backed by drm_gem_object. The code is
taken from drm_fb_cma_helper.

Signed-off-by: Noralf Trønnes 
---
 Documentation/gpu/drm-kms-helpers.rst|   9 +
 drivers/gpu/drm/Makefile |   2 +-
 drivers/gpu/drm/drm_gem_framebuffer_helper.c | 252 +++
 include/drm/drm_framebuffer.h|   4 +
 include/drm/drm_gem_framebuffer_helper.h |  35 
 5 files changed, 301 insertions(+), 1 deletion(-)
 create mode 100644 drivers/gpu/drm/drm_gem_framebuffer_helper.c
 create mode 100644 include/drm/drm_gem_framebuffer_helper.h

diff --git a/Documentation/gpu/drm-kms-helpers.rst 
b/Documentation/gpu/drm-kms-helpers.rst
index 7c5e254..13dd237 100644
--- a/Documentation/gpu/drm-kms-helpers.rst
+++ b/Documentation/gpu/drm-kms-helpers.rst
@@ -296,3 +296,12 @@ Auxiliary Modeset Helpers
 
 .. kernel-doc:: drivers/gpu/drm/drm_modeset_helper.c
:export:
+
+Framebuffer GEM Helper Reference
+
+
+.. kernel-doc:: drivers/gpu/drm/drm_gem_framebuffer_helper.c
+   :doc: overview
+
+.. kernel-doc:: drivers/gpu/drm/drm_gem_framebuffer_helper.c
+   :export:
diff --git a/drivers/gpu/drm/Makefile b/drivers/gpu/drm/Makefile
index 24a066e..a8acc19 100644
--- a/drivers/gpu/drm/Makefile
+++ b/drivers/gpu/drm/Makefile
@@ -33,7 +33,7 @@ drm_kms_helper-y := drm_crtc_helper.o drm_dp_helper.o 
drm_probe_helper.o \
drm_plane_helper.o drm_dp_mst_topology.o drm_atomic_helper.o \
drm_kms_helper_common.o drm_dp_dual_mode_helper.o \
drm_simple_kms_helper.o drm_modeset_helper.o \
-   drm_scdc_helper.o
+   drm_scdc_helper.o drm_gem_framebuffer_helper.o
 
 drm_kms_helper-$(CONFIG_DRM_PANEL_BRIDGE) += bridge/panel.o
 drm_kms_helper-$(CONFIG_DRM_LOAD_EDID_FIRMWARE) += drm_edid_load.o
diff --git a/drivers/gpu/drm/drm_gem_framebuffer_helper.c 
b/drivers/gpu/drm/drm_gem_framebuffer_helper.c
new file mode 100644
index 000..41a506c
--- /dev/null
+++ b/drivers/gpu/drm/drm_gem_framebuffer_helper.c
@@ -0,0 +1,252 @@
+/*
+ * drm gem framebuffer helper functions
+ *
+ * Copyright (C) 2017 Noralf Trønnes
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include 
+#include 
+#include 
+#include 
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+/**
+ * DOC: overview
+ *
+ * This library provides helpers for drivers that don't subclass
+ * _framebuffer and are backed by _gem_object.
+ */
+
+/**
+ * drm_gem_fb_get_obj() - Get GEM object for framebuffer
+ * @fb: The framebuffer
+ * @plane: Which plane
+ *
+ * Returns the GEM object for given framebuffer.
+ */
+struct drm_gem_object *drm_gem_fb_get_obj(struct drm_framebuffer *fb,
+ unsigned int plane)
+{
+   if (plane >= 4)
+   return NULL;
+
+   return fb->obj[plane];
+}
+EXPORT_SYMBOL_GPL(drm_gem_fb_get_obj);
+
+/**
+ * drm_gem_fb_alloc - Allocate GEM backed framebuffer
+ * @dev: DRM device
+ * @mode_cmd: metadata from the userspace fb creation request
+ * @obj: GEM object(s) backing the framebuffer
+ * @num_planes: Number of planes
+ * @funcs: vtable to be used for the new framebuffer object
+ *
+ * Returns:
+ * Allocated struct drm_framebuffer * or error encoded pointer.
+ */
+struct drm_framebuffer *
+drm_gem_fb_alloc(struct drm_device *dev,
+const struct drm_mode_fb_cmd2 *mode_cmd,
+struct drm_gem_object **obj, unsigned int num_planes,
+const struct drm_framebuffer_funcs *funcs)
+{
+   struct drm_framebuffer *fb;
+   int ret, i;
+
+   fb = kzalloc(sizeof(*fb), GFP_KERNEL);
+   if (!fb)
+   return ERR_PTR(-ENOMEM);
+
+   drm_helper_mode_fill_fb_struct(dev, fb, mode_cmd);
+
+   for (i = 0; i < num_planes; i++)
+   fb->obj[i] = obj[i];
+
+   ret = drm_framebuffer_init(dev, fb, funcs);
+   if (ret) {
+   DRM_DEV_ERROR(dev->dev, "Failed to init framebuffer: %d\n",
+ ret);
+   kfree(fb);
+   return ERR_PTR(ret);
+   }
+
+   return fb;
+}
+EXPORT_SYMBOL(drm_gem_fb_alloc);
+
+/**
+ * drm_gem_fb_destroy - Free GEM backed framebuffer
+ * @fb: DRM framebuffer
+ *
+ * Frees a GEM backed framebuffer with it's backing buffer(s) and the structure
+ * itself. Drivers can use this as their _framebuffer_funcs->destroy
+ * callback.
+ */
+void drm_gem_fb_destroy(struct drm_framebuffer *fb)
+{
+   int i;
+
+   for (i = 0; i < 4; i++) {
+   if (fb->obj[i])
+   drm_gem_object_put_unlocked(fb->obj[i]);
+   }
+
+