Re: [PATCH 7/8] drm/qxl: Use drm_fb_helper deferred_io support

2016-04-21 Thread Daniel Vetter
On Thu, Apr 21, 2016 at 09:49:39AM +0200, Daniel Vetter wrote:
> On Thu, Apr 21, 2016 at 09:41:34AM +0200, Daniel Vetter wrote:
> > On Wed, Apr 20, 2016 at 09:04:38PM +0200, Noralf Trønnes wrote:
> > > 
> > > Den 20.04.2016 19:47, skrev Daniel Vetter:
> > > >On Wed, Apr 20, 2016 at 05:25:28PM +0200, Noralf Trønnes wrote:
> > > >>Use the fbdev deferred io support in drm_fb_helper.
> > > >>The (struct fb_ops *)->fb_{fillrect,copyarea,imageblit} functions will
> > > >>now be deferred in the same way that mmap damage is, instead of being
> > > >>flushed directly.
> > > >>This patch has only been compile tested.
> > > >>
> > > >>Signed-off-by: Noralf Trønnes 
> > > >>---
> > > >>  drivers/gpu/drm/qxl/qxl_display.c |   9 +-
> > > >>  drivers/gpu/drm/qxl/qxl_drv.h |   7 +-
> > > >>  drivers/gpu/drm/qxl/qxl_fb.c  | 220 
> > > >> ++
> > > >>  drivers/gpu/drm/qxl/qxl_kms.c |   4 -
> > > >>  4 files changed, 62 insertions(+), 178 deletions(-)
> > > >>
> > > >>diff --git a/drivers/gpu/drm/qxl/qxl_display.c 
> > > >>b/drivers/gpu/drm/qxl/qxl_display.c
> > > >>index 030409a..9a03524 100644
> > > >>--- a/drivers/gpu/drm/qxl/qxl_display.c
> > > >>+++ b/drivers/gpu/drm/qxl/qxl_display.c
> > > >>@@ -465,7 +465,7 @@ static const struct drm_crtc_funcs qxl_crtc_funcs = 
> > > >>{
> > > >>.page_flip = qxl_crtc_page_flip,
> > > >>  };
> > > >>-static void qxl_user_framebuffer_destroy(struct drm_framebuffer *fb)
> > > >>+void qxl_user_framebuffer_destroy(struct drm_framebuffer *fb)
> > > >>  {
> > > >>struct qxl_framebuffer *qxl_fb = to_qxl_framebuffer(fb);
> > > >>@@ -527,12 +527,13 @@ int
> > > >>  qxl_framebuffer_init(struct drm_device *dev,
> > > >> struct qxl_framebuffer *qfb,
> > > >> const struct drm_mode_fb_cmd2 *mode_cmd,
> > > >>-struct drm_gem_object *obj)
> > > >>+struct drm_gem_object *obj,
> > > >>+const struct drm_framebuffer_funcs *funcs)
> > > >There should be no need at all to have a separate fb funcs table for the
> > > >fbdev fb. Both /should/ be able to use the exact same (already existing)
> > > >->dirty() callback. We need this only in CMA because CMA is a midlayer
> > > >used by multiple drivers.
> > > 
> > > I don't see how I can avoid it.
> > > 
> > > fbdev framebuffer flushing:
> > > 
> > > static void qxl_fb_dirty_flush(struct fb_info *info)
> > > {
> > > qxl_fb_image_init(&qxl_fb_image, qdev, info, NULL);
> > > qxl_draw_opaque_fb(&qxl_fb_image, stride);
> > > }
> > > 
> > > drm framebuffer flushing:
> > > 
> > > static int qxl_framebuffer_surface_dirty(...)
> > > {
> > > qxl_draw_dirty_fb(...);
> > > }
> > > 
> > > qxl_draw_opaque_fb() and qxl_draw_dirty_fb() differ so much that it's way
> > > over my head to see if they can be combined.
> > > Here's an online diff of the two functions:
> > > https://www.diffchecker.com/jqbbalux
> > 
> > Imo nuke the fbdev one entirely. If it breaks then it's either a bug in
> > your generic fbdefio code, or the qxl ->dirty implementation has a bug. It
> > should work ;-)
> > 
> > Ok, slightly more seriously the difference seems to be that the fbdev one
> > support paletted mode too. But since qxl has 0 pixel format checking
> > anywhere I have no idea whether that's dead code (i.e. broken) or actually
> > working. I guess keeping the split is ok, if we add a big FIXME comment to
> > it that this is very fishy.
> 
> Ok, I read around a bit more. The only things qxl seems to support are
> bits_per_pixel of 1, 24 and 32 (see qxl_image_init_helper). And drm has no
> way to pass in 1 bpp images. And it doesn't support 8 bit paletted, which
> is the only paletted thing drm supports.
> 
> So if you totally feel like I think we could add format checking for
> DRM_FORMAT_XRGB and DRM_FORMAT_RGB888 in qxl_framebuffer_init and then
> rip out all that code. But that's a few more patches and probably should
> be tested actually ;-)

Even simpler: Check for bits_per_pixel == 24 || 32, since that matches the
only other check in qxl. Extremely unlikely qxl supports all these
formats, but meh ...
-Daniel
-- 
Daniel Vetter
Software Engineer, Intel Corporation
http://blog.ffwll.ch


Re: [PATCH 7/8] drm/qxl: Use drm_fb_helper deferred_io support

2016-04-21 Thread Daniel Vetter
On Thu, Apr 21, 2016 at 09:41:34AM +0200, Daniel Vetter wrote:
> On Wed, Apr 20, 2016 at 09:04:38PM +0200, Noralf Trønnes wrote:
> > 
> > Den 20.04.2016 19:47, skrev Daniel Vetter:
> > >On Wed, Apr 20, 2016 at 05:25:28PM +0200, Noralf Trønnes wrote:
> > >>Use the fbdev deferred io support in drm_fb_helper.
> > >>The (struct fb_ops *)->fb_{fillrect,copyarea,imageblit} functions will
> > >>now be deferred in the same way that mmap damage is, instead of being
> > >>flushed directly.
> > >>This patch has only been compile tested.
> > >>
> > >>Signed-off-by: Noralf Trønnes 
> > >>---
> > >>  drivers/gpu/drm/qxl/qxl_display.c |   9 +-
> > >>  drivers/gpu/drm/qxl/qxl_drv.h |   7 +-
> > >>  drivers/gpu/drm/qxl/qxl_fb.c  | 220 
> > >> ++
> > >>  drivers/gpu/drm/qxl/qxl_kms.c |   4 -
> > >>  4 files changed, 62 insertions(+), 178 deletions(-)
> > >>
> > >>diff --git a/drivers/gpu/drm/qxl/qxl_display.c 
> > >>b/drivers/gpu/drm/qxl/qxl_display.c
> > >>index 030409a..9a03524 100644
> > >>--- a/drivers/gpu/drm/qxl/qxl_display.c
> > >>+++ b/drivers/gpu/drm/qxl/qxl_display.c
> > >>@@ -465,7 +465,7 @@ static const struct drm_crtc_funcs qxl_crtc_funcs = {
> > >>  .page_flip = qxl_crtc_page_flip,
> > >>  };
> > >>-static void qxl_user_framebuffer_destroy(struct drm_framebuffer *fb)
> > >>+void qxl_user_framebuffer_destroy(struct drm_framebuffer *fb)
> > >>  {
> > >>  struct qxl_framebuffer *qxl_fb = to_qxl_framebuffer(fb);
> > >>@@ -527,12 +527,13 @@ int
> > >>  qxl_framebuffer_init(struct drm_device *dev,
> > >>   struct qxl_framebuffer *qfb,
> > >>   const struct drm_mode_fb_cmd2 *mode_cmd,
> > >>-  struct drm_gem_object *obj)
> > >>+  struct drm_gem_object *obj,
> > >>+  const struct drm_framebuffer_funcs *funcs)
> > >There should be no need at all to have a separate fb funcs table for the
> > >fbdev fb. Both /should/ be able to use the exact same (already existing)
> > >->dirty() callback. We need this only in CMA because CMA is a midlayer
> > >used by multiple drivers.
> > 
> > I don't see how I can avoid it.
> > 
> > fbdev framebuffer flushing:
> > 
> > static void qxl_fb_dirty_flush(struct fb_info *info)
> > {
> > qxl_fb_image_init(&qxl_fb_image, qdev, info, NULL);
> > qxl_draw_opaque_fb(&qxl_fb_image, stride);
> > }
> > 
> > drm framebuffer flushing:
> > 
> > static int qxl_framebuffer_surface_dirty(...)
> > {
> > qxl_draw_dirty_fb(...);
> > }
> > 
> > qxl_draw_opaque_fb() and qxl_draw_dirty_fb() differ so much that it's way
> > over my head to see if they can be combined.
> > Here's an online diff of the two functions:
> > https://www.diffchecker.com/jqbbalux
> 
> Imo nuke the fbdev one entirely. If it breaks then it's either a bug in
> your generic fbdefio code, or the qxl ->dirty implementation has a bug. It
> should work ;-)
> 
> Ok, slightly more seriously the difference seems to be that the fbdev one
> support paletted mode too. But since qxl has 0 pixel format checking
> anywhere I have no idea whether that's dead code (i.e. broken) or actually
> working. I guess keeping the split is ok, if we add a big FIXME comment to
> it that this is very fishy.

Ok, I read around a bit more. The only things qxl seems to support are
bits_per_pixel of 1, 24 and 32 (see qxl_image_init_helper). And drm has no
way to pass in 1 bpp images. And it doesn't support 8 bit paletted, which
is the only paletted thing drm supports.

So if you totally feel like I think we could add format checking for
DRM_FORMAT_XRGB and DRM_FORMAT_RGB888 in qxl_framebuffer_init and then
rip out all that code. But that's a few more patches and probably should
be tested actually ;-)

FIXME plus explaing it all in the commit message is fine with me too.
-Daniel
-- 
Daniel Vetter
Software Engineer, Intel Corporation
http://blog.ffwll.ch


Re: [PATCH 7/8] drm/qxl: Use drm_fb_helper deferred_io support

2016-04-21 Thread Daniel Vetter
On Wed, Apr 20, 2016 at 09:04:38PM +0200, Noralf Trønnes wrote:
> 
> Den 20.04.2016 19:47, skrev Daniel Vetter:
> >On Wed, Apr 20, 2016 at 05:25:28PM +0200, Noralf Trønnes wrote:
> >>Use the fbdev deferred io support in drm_fb_helper.
> >>The (struct fb_ops *)->fb_{fillrect,copyarea,imageblit} functions will
> >>now be deferred in the same way that mmap damage is, instead of being
> >>flushed directly.
> >>This patch has only been compile tested.
> >>
> >>Signed-off-by: Noralf Trønnes 
> >>---
> >>  drivers/gpu/drm/qxl/qxl_display.c |   9 +-
> >>  drivers/gpu/drm/qxl/qxl_drv.h |   7 +-
> >>  drivers/gpu/drm/qxl/qxl_fb.c  | 220 
> >> ++
> >>  drivers/gpu/drm/qxl/qxl_kms.c |   4 -
> >>  4 files changed, 62 insertions(+), 178 deletions(-)
> >>
> >>diff --git a/drivers/gpu/drm/qxl/qxl_display.c 
> >>b/drivers/gpu/drm/qxl/qxl_display.c
> >>index 030409a..9a03524 100644
> >>--- a/drivers/gpu/drm/qxl/qxl_display.c
> >>+++ b/drivers/gpu/drm/qxl/qxl_display.c
> >>@@ -465,7 +465,7 @@ static const struct drm_crtc_funcs qxl_crtc_funcs = {
> >>.page_flip = qxl_crtc_page_flip,
> >>  };
> >>-static void qxl_user_framebuffer_destroy(struct drm_framebuffer *fb)
> >>+void qxl_user_framebuffer_destroy(struct drm_framebuffer *fb)
> >>  {
> >>struct qxl_framebuffer *qxl_fb = to_qxl_framebuffer(fb);
> >>@@ -527,12 +527,13 @@ int
> >>  qxl_framebuffer_init(struct drm_device *dev,
> >> struct qxl_framebuffer *qfb,
> >> const struct drm_mode_fb_cmd2 *mode_cmd,
> >>-struct drm_gem_object *obj)
> >>+struct drm_gem_object *obj,
> >>+const struct drm_framebuffer_funcs *funcs)
> >There should be no need at all to have a separate fb funcs table for the
> >fbdev fb. Both /should/ be able to use the exact same (already existing)
> >->dirty() callback. We need this only in CMA because CMA is a midlayer
> >used by multiple drivers.
> 
> I don't see how I can avoid it.
> 
> fbdev framebuffer flushing:
> 
> static void qxl_fb_dirty_flush(struct fb_info *info)
> {
> qxl_fb_image_init(&qxl_fb_image, qdev, info, NULL);
> qxl_draw_opaque_fb(&qxl_fb_image, stride);
> }
> 
> drm framebuffer flushing:
> 
> static int qxl_framebuffer_surface_dirty(...)
> {
> qxl_draw_dirty_fb(...);
> }
> 
> qxl_draw_opaque_fb() and qxl_draw_dirty_fb() differ so much that it's way
> over my head to see if they can be combined.
> Here's an online diff of the two functions:
> https://www.diffchecker.com/jqbbalux

Imo nuke the fbdev one entirely. If it breaks then it's either a bug in
your generic fbdefio code, or the qxl ->dirty implementation has a bug. It
should work ;-)

Ok, slightly more seriously the difference seems to be that the fbdev one
support paletted mode too. But since qxl has 0 pixel format checking
anywhere I have no idea whether that's dead code (i.e. broken) or actually
working. I guess keeping the split is ok, if we add a big FIXME comment to
it that this is very fishy.
-Daniel


> 
> 
> >
> >With that change you should be able to condense this patch down to pretty
> >much just removing lines. Which is Good (tm).
> >
> >Cheers, Daniel
> >
> >>  {
> >>int ret;
> >>qfb->obj = obj;
> >>-   ret = drm_framebuffer_init(dev, &qfb->base, &qxl_fb_funcs);
> >>+   ret = drm_framebuffer_init(dev, &qfb->base, funcs);
> >>if (ret) {
> >>qfb->obj = NULL;
> >>return ret;
> >>@@ -999,7 +1000,7 @@ qxl_user_framebuffer_create(struct drm_device *dev,
> >>if (qxl_fb == NULL)
> >>return NULL;
> >>-   ret = qxl_framebuffer_init(dev, qxl_fb, mode_cmd, obj);
> >>+   ret = qxl_framebuffer_init(dev, qxl_fb, mode_cmd, obj, &qxl_fb_funcs);
> >>if (ret) {
> >>kfree(qxl_fb);
> >>drm_gem_object_unreference_unlocked(obj);
> >>diff --git a/drivers/gpu/drm/qxl/qxl_drv.h b/drivers/gpu/drm/qxl/qxl_drv.h
> >>index 3f3897e..3ad6604 100644
> >>--- a/drivers/gpu/drm/qxl/qxl_drv.h
> >>+++ b/drivers/gpu/drm/qxl/qxl_drv.h
> >>@@ -324,8 +324,6 @@ struct qxl_device {
> >>struct workqueue_struct *gc_queue;
> >>struct work_struct gc_work;
> >>-   struct work_struct fb_work;
> >>-
> >>struct drm_property *hotplug_mode_update_property;
> >>int monitors_config_width;
> >>int monitors_config_height;
> >>@@ -389,11 +387,13 @@ int qxl_get_handle_for_primary_fb(struct qxl_device 
> >>*qdev,
> >>  void qxl_fbdev_set_suspend(struct qxl_device *qdev, int state);
> >>  /* qxl_display.c */
> >>+void qxl_user_framebuffer_destroy(struct drm_framebuffer *fb);
> >>  int
> >>  qxl_framebuffer_init(struct drm_device *dev,
> >> struct qxl_framebuffer *rfb,
> >> const struct drm_mode_fb_cmd2 *mode_cmd,
> >>-struct drm_gem_object *obj);
> >>+struct drm_gem_object *obj,
> >>+const struct drm_framebuffer_funcs *funcs);
> >>  void qxl_display_read_client_monitors_config(struct qxl_device 

Re: [PATCH 7/8] drm/qxl: Use drm_fb_helper deferred_io support

2016-04-20 Thread Noralf Trønnes


Den 20.04.2016 19:47, skrev Daniel Vetter:

On Wed, Apr 20, 2016 at 05:25:28PM +0200, Noralf Trønnes wrote:

Use the fbdev deferred io support in drm_fb_helper.
The (struct fb_ops *)->fb_{fillrect,copyarea,imageblit} functions will
now be deferred in the same way that mmap damage is, instead of being
flushed directly.
This patch has only been compile tested.

Signed-off-by: Noralf Trønnes 
---
  drivers/gpu/drm/qxl/qxl_display.c |   9 +-
  drivers/gpu/drm/qxl/qxl_drv.h |   7 +-
  drivers/gpu/drm/qxl/qxl_fb.c  | 220 ++
  drivers/gpu/drm/qxl/qxl_kms.c |   4 -
  4 files changed, 62 insertions(+), 178 deletions(-)

diff --git a/drivers/gpu/drm/qxl/qxl_display.c 
b/drivers/gpu/drm/qxl/qxl_display.c
index 030409a..9a03524 100644
--- a/drivers/gpu/drm/qxl/qxl_display.c
+++ b/drivers/gpu/drm/qxl/qxl_display.c
@@ -465,7 +465,7 @@ static const struct drm_crtc_funcs qxl_crtc_funcs = {
.page_flip = qxl_crtc_page_flip,
  };
  
-static void qxl_user_framebuffer_destroy(struct drm_framebuffer *fb)

+void qxl_user_framebuffer_destroy(struct drm_framebuffer *fb)
  {
struct qxl_framebuffer *qxl_fb = to_qxl_framebuffer(fb);
  
@@ -527,12 +527,13 @@ int

  qxl_framebuffer_init(struct drm_device *dev,
 struct qxl_framebuffer *qfb,
 const struct drm_mode_fb_cmd2 *mode_cmd,
-struct drm_gem_object *obj)
+struct drm_gem_object *obj,
+const struct drm_framebuffer_funcs *funcs)

There should be no need at all to have a separate fb funcs table for the
fbdev fb. Both /should/ be able to use the exact same (already existing)
->dirty() callback. We need this only in CMA because CMA is a midlayer
used by multiple drivers.


I don't see how I can avoid it.

fbdev framebuffer flushing:

static void qxl_fb_dirty_flush(struct fb_info *info)
{
qxl_fb_image_init(&qxl_fb_image, qdev, info, NULL);
qxl_draw_opaque_fb(&qxl_fb_image, stride);
}

drm framebuffer flushing:

static int qxl_framebuffer_surface_dirty(...)
{
qxl_draw_dirty_fb(...);
}

qxl_draw_opaque_fb() and qxl_draw_dirty_fb() differ so much that it's way
over my head to see if they can be combined.
Here's an online diff of the two functions:
https://www.diffchecker.com/jqbbalux




With that change you should be able to condense this patch down to pretty
much just removing lines. Which is Good (tm).

Cheers, Daniel


  {
int ret;
  
  	qfb->obj = obj;

-   ret = drm_framebuffer_init(dev, &qfb->base, &qxl_fb_funcs);
+   ret = drm_framebuffer_init(dev, &qfb->base, funcs);
if (ret) {
qfb->obj = NULL;
return ret;
@@ -999,7 +1000,7 @@ qxl_user_framebuffer_create(struct drm_device *dev,
if (qxl_fb == NULL)
return NULL;
  
-	ret = qxl_framebuffer_init(dev, qxl_fb, mode_cmd, obj);

+   ret = qxl_framebuffer_init(dev, qxl_fb, mode_cmd, obj, &qxl_fb_funcs);
if (ret) {
kfree(qxl_fb);
drm_gem_object_unreference_unlocked(obj);
diff --git a/drivers/gpu/drm/qxl/qxl_drv.h b/drivers/gpu/drm/qxl/qxl_drv.h
index 3f3897e..3ad6604 100644
--- a/drivers/gpu/drm/qxl/qxl_drv.h
+++ b/drivers/gpu/drm/qxl/qxl_drv.h
@@ -324,8 +324,6 @@ struct qxl_device {
struct workqueue_struct *gc_queue;
struct work_struct gc_work;
  
-	struct work_struct fb_work;

-
struct drm_property *hotplug_mode_update_property;
int monitors_config_width;
int monitors_config_height;
@@ -389,11 +387,13 @@ int qxl_get_handle_for_primary_fb(struct qxl_device *qdev,
  void qxl_fbdev_set_suspend(struct qxl_device *qdev, int state);
  
  /* qxl_display.c */

+void qxl_user_framebuffer_destroy(struct drm_framebuffer *fb);
  int
  qxl_framebuffer_init(struct drm_device *dev,
 struct qxl_framebuffer *rfb,
 const struct drm_mode_fb_cmd2 *mode_cmd,
-struct drm_gem_object *obj);
+struct drm_gem_object *obj,
+const struct drm_framebuffer_funcs *funcs);
  void qxl_display_read_client_monitors_config(struct qxl_device *qdev);
  void qxl_send_monitors_config(struct qxl_device *qdev);
  int qxl_create_monitors_object(struct qxl_device *qdev);
@@ -553,7 +553,6 @@ int qxl_irq_init(struct qxl_device *qdev);
  irqreturn_t qxl_irq_handler(int irq, void *arg);
  
  /* qxl_fb.c */

-int qxl_fb_init(struct qxl_device *qdev);
  bool qxl_fbdev_qobj_is_fb(struct qxl_device *qdev, struct qxl_bo *qobj);
  
  int qxl_debugfs_add_files(struct qxl_device *qdev,

diff --git a/drivers/gpu/drm/qxl/qxl_fb.c b/drivers/gpu/drm/qxl/qxl_fb.c
index 06f032d..090dcee 100644
--- a/drivers/gpu/drm/qxl/qxl_fb.c
+++ b/drivers/gpu/drm/qxl/qxl_fb.c
@@ -30,6 +30,7 @@
  #include "drm/drm.h"
  #include "drm/drm_crtc.h"
  #include "drm/drm_crtc_helper.h"
+#include "drm/drm_rect.h"
  #include "qxl_drv.h"
  
  #include "qxl_object.h"

@@ -46,15 +47,

Re: [PATCH 7/8] drm/qxl: Use drm_fb_helper deferred_io support

2016-04-20 Thread Daniel Vetter
On Wed, Apr 20, 2016 at 05:25:28PM +0200, Noralf Trønnes wrote:
> Use the fbdev deferred io support in drm_fb_helper.
> The (struct fb_ops *)->fb_{fillrect,copyarea,imageblit} functions will
> now be deferred in the same way that mmap damage is, instead of being
> flushed directly.
> This patch has only been compile tested.
> 
> Signed-off-by: Noralf Trønnes 
> ---
>  drivers/gpu/drm/qxl/qxl_display.c |   9 +-
>  drivers/gpu/drm/qxl/qxl_drv.h |   7 +-
>  drivers/gpu/drm/qxl/qxl_fb.c  | 220 
> ++
>  drivers/gpu/drm/qxl/qxl_kms.c |   4 -
>  4 files changed, 62 insertions(+), 178 deletions(-)
> 
> diff --git a/drivers/gpu/drm/qxl/qxl_display.c 
> b/drivers/gpu/drm/qxl/qxl_display.c
> index 030409a..9a03524 100644
> --- a/drivers/gpu/drm/qxl/qxl_display.c
> +++ b/drivers/gpu/drm/qxl/qxl_display.c
> @@ -465,7 +465,7 @@ static const struct drm_crtc_funcs qxl_crtc_funcs = {
>   .page_flip = qxl_crtc_page_flip,
>  };
>  
> -static void qxl_user_framebuffer_destroy(struct drm_framebuffer *fb)
> +void qxl_user_framebuffer_destroy(struct drm_framebuffer *fb)
>  {
>   struct qxl_framebuffer *qxl_fb = to_qxl_framebuffer(fb);
>  
> @@ -527,12 +527,13 @@ int
>  qxl_framebuffer_init(struct drm_device *dev,
>struct qxl_framebuffer *qfb,
>const struct drm_mode_fb_cmd2 *mode_cmd,
> -  struct drm_gem_object *obj)
> +  struct drm_gem_object *obj,
> +  const struct drm_framebuffer_funcs *funcs)

There should be no need at all to have a separate fb funcs table for the
fbdev fb. Both /should/ be able to use the exact same (already existing)
->dirty() callback. We need this only in CMA because CMA is a midlayer
used by multiple drivers.

With that change you should be able to condense this patch down to pretty
much just removing lines. Which is Good (tm).

Cheers, Daniel

>  {
>   int ret;
>  
>   qfb->obj = obj;
> - ret = drm_framebuffer_init(dev, &qfb->base, &qxl_fb_funcs);
> + ret = drm_framebuffer_init(dev, &qfb->base, funcs);
>   if (ret) {
>   qfb->obj = NULL;
>   return ret;
> @@ -999,7 +1000,7 @@ qxl_user_framebuffer_create(struct drm_device *dev,
>   if (qxl_fb == NULL)
>   return NULL;
>  
> - ret = qxl_framebuffer_init(dev, qxl_fb, mode_cmd, obj);
> + ret = qxl_framebuffer_init(dev, qxl_fb, mode_cmd, obj, &qxl_fb_funcs);
>   if (ret) {
>   kfree(qxl_fb);
>   drm_gem_object_unreference_unlocked(obj);
> diff --git a/drivers/gpu/drm/qxl/qxl_drv.h b/drivers/gpu/drm/qxl/qxl_drv.h
> index 3f3897e..3ad6604 100644
> --- a/drivers/gpu/drm/qxl/qxl_drv.h
> +++ b/drivers/gpu/drm/qxl/qxl_drv.h
> @@ -324,8 +324,6 @@ struct qxl_device {
>   struct workqueue_struct *gc_queue;
>   struct work_struct gc_work;
>  
> - struct work_struct fb_work;
> -
>   struct drm_property *hotplug_mode_update_property;
>   int monitors_config_width;
>   int monitors_config_height;
> @@ -389,11 +387,13 @@ int qxl_get_handle_for_primary_fb(struct qxl_device 
> *qdev,
>  void qxl_fbdev_set_suspend(struct qxl_device *qdev, int state);
>  
>  /* qxl_display.c */
> +void qxl_user_framebuffer_destroy(struct drm_framebuffer *fb);
>  int
>  qxl_framebuffer_init(struct drm_device *dev,
>struct qxl_framebuffer *rfb,
>const struct drm_mode_fb_cmd2 *mode_cmd,
> -  struct drm_gem_object *obj);
> +  struct drm_gem_object *obj,
> +  const struct drm_framebuffer_funcs *funcs);
>  void qxl_display_read_client_monitors_config(struct qxl_device *qdev);
>  void qxl_send_monitors_config(struct qxl_device *qdev);
>  int qxl_create_monitors_object(struct qxl_device *qdev);
> @@ -553,7 +553,6 @@ int qxl_irq_init(struct qxl_device *qdev);
>  irqreturn_t qxl_irq_handler(int irq, void *arg);
>  
>  /* qxl_fb.c */
> -int qxl_fb_init(struct qxl_device *qdev);
>  bool qxl_fbdev_qobj_is_fb(struct qxl_device *qdev, struct qxl_bo *qobj);
>  
>  int qxl_debugfs_add_files(struct qxl_device *qdev,
> diff --git a/drivers/gpu/drm/qxl/qxl_fb.c b/drivers/gpu/drm/qxl/qxl_fb.c
> index 06f032d..090dcee 100644
> --- a/drivers/gpu/drm/qxl/qxl_fb.c
> +++ b/drivers/gpu/drm/qxl/qxl_fb.c
> @@ -30,6 +30,7 @@
>  #include "drm/drm.h"
>  #include "drm/drm_crtc.h"
>  #include "drm/drm_crtc_helper.h"
> +#include "drm/drm_rect.h"
>  #include "qxl_drv.h"
>  
>  #include "qxl_object.h"
> @@ -46,15 +47,6 @@ struct qxl_fbdev {
>   struct list_head delayed_ops;
>   void *shadow;
>   int size;
> -
> - /* dirty memory logging */
> - struct {
> - spinlock_t lock;
> - unsigned x1;
> - unsigned y1;
> - unsigned x2;
> - unsigned y2;
> - } dirty;
>  };
>  
>  static void qxl_fb_image_init(struct qxl_fb_image *qxl_fb_image,
> @@ -82,169 +74,18 @@ static void qxl_fb_image_init(struct qxl_fb_image