From 9b55b95a8eca1a6bb2d7674e4af1fed003462677 Mon Sep 17 00:00:00 2001 From: Rob Clark Date: Mon, 5 Mar 2012 10:48:33 -0600 Subject: staging: drm/omap: call omap_gem_roll() in non-atomic ctx If fbcon calls us from atomic context, push the work off to the workqueue to avoid calling into the gem/dmm code in an atomic context. Signed-off-by: Rob Clark Signed-off-by: Greg Kroah-Hartman --- drivers/staging/omapdrm/omap_fbdev.c | 26 ++++++++++++++++++++++---- 1 file changed, 22 insertions(+), 4 deletions(-) (limited to 'drivers/staging/omapdrm/omap_fbdev.c') diff --git a/drivers/staging/omapdrm/omap_fbdev.c b/drivers/staging/omapdrm/omap_fbdev.c index 96940bbfc6f4..11acd4c35ed2 100644 --- a/drivers/staging/omapdrm/omap_fbdev.c +++ b/drivers/staging/omapdrm/omap_fbdev.c @@ -37,6 +37,9 @@ struct omap_fbdev { struct drm_framebuffer *fb; struct drm_gem_object *bo; bool ywrap_enabled; + + /* for deferred dmm roll when getting called in atomic ctx */ + struct work_struct work; }; static void omap_fbdev_flush(struct fb_info *fbi, int x, int y, int w, int h); @@ -75,12 +78,22 @@ static void omap_fbdev_imageblit(struct fb_info *fbi, image->width, image->height); } +static void pan_worker(struct work_struct *work) +{ + struct omap_fbdev *fbdev = container_of(work, struct omap_fbdev, work); + struct fb_info *fbi = fbdev->base.fbdev; + int npages; + + /* DMM roll shifts in 4K pages: */ + npages = fbi->fix.line_length >> PAGE_SHIFT; + omap_gem_roll(fbdev->bo, fbi->var.yoffset * npages); +} + static int omap_fbdev_pan_display(struct fb_var_screeninfo *var, struct fb_info *fbi) { struct drm_fb_helper *helper = get_fb(fbi); struct omap_fbdev *fbdev = to_omap_fbdev(helper); - int npages; if (!helper) goto fallback; @@ -88,9 +101,12 @@ static int omap_fbdev_pan_display(struct fb_var_screeninfo *var, if (!fbdev->ywrap_enabled) goto fallback; - /* DMM roll shifts in 4K pages: */ - npages = fbi->fix.line_length >> PAGE_SHIFT; - omap_gem_roll(fbdev->bo, var->yoffset * npages); + if (drm_can_sleep()) { + pan_worker(&fbdev->work); + } else { + struct omap_drm_private *priv = helper->dev->dev_private; + queue_work(priv->wq, &fbdev->work); + } return 0; @@ -336,6 +352,8 @@ struct drm_fb_helper *omap_fbdev_init(struct drm_device *dev) goto fail; } + INIT_WORK(&fbdev->work, pan_worker); + helper = &fbdev->base; helper->funcs = &omap_fb_helper_funcs; -- cgit v1.2.3