Skip to content

Commit

Permalink
staging: drm/omap: call omap_gem_roll() in non-atomic ctx
Browse files Browse the repository at this point in the history
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 <rob@ti.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
  • Loading branch information
Rob Clark authored and Greg Kroah-Hartman committed Mar 7, 2012
1 parent 5609f7f commit 9b55b95
Show file tree
Hide file tree
Showing 2 changed files with 24 additions and 16 deletions.
26 changes: 22 additions & 4 deletions drivers/staging/omapdrm/omap_fbdev.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -75,22 +78,35 @@ 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;

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;

Expand Down Expand Up @@ -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;
Expand Down
14 changes: 2 additions & 12 deletions drivers/staging/omapdrm/omap_gem.c
Original file line number Diff line number Diff line change
Expand Up @@ -566,6 +566,8 @@ int omap_gem_dumb_map_offset(struct drm_file *file, struct drm_device *dev,

/* Set scrolling position. This allows us to implement fast scrolling
* for console.
*
* Call only from non-atomic contexts.
*/
int omap_gem_roll(struct drm_gem_object *obj, uint32_t roll)
{
Expand All @@ -580,18 +582,6 @@ int omap_gem_roll(struct drm_gem_object *obj, uint32_t roll)

omap_obj->roll = roll;

if (in_atomic() || mutex_is_locked(&obj->dev->struct_mutex)) {
/* this can get called from fbcon in atomic context.. so
* just ignore it and wait for next time called from
* interruptible context to update the PAT.. the result
* may be that user sees wrap-around instead of scrolling
* momentarily on the screen. If we wanted to be fancier
* we could perhaps schedule some workqueue work at this
* point.
*/
return 0;
}

mutex_lock(&obj->dev->struct_mutex);

/* if we aren't mapped yet, we don't need to do anything */
Expand Down

0 comments on commit 9b55b95

Please sign in to comment.