mirror of
https://github.com/torvalds/linux.git
synced 2024-11-16 09:02:00 +00:00
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 <rob@ti.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
parent
5609f7fe30
commit
9b55b95a8e
@ -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;
|
||||
|
@ -566,6 +566,8 @@ fail:
|
||||
|
||||
/* 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)
|
||||
{
|
||||
@ -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 */
|
||||
|
Loading…
Reference in New Issue
Block a user