aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDave Airlie2013-05-02 01:40:25 -0500
committerGreg Kroah-Hartman2013-05-11 15:54:00 -0500
commit294b04d109ad9654f0f6608e7963a2f821d784c5 (patch)
tree82e3144652499eeec5843c78aaa796f4870f1e86
parentfd282737ffe294ec6345338260d0754450cf2a7d (diff)
downloadkernel-omap-294b04d109ad9654f0f6608e7963a2f821d784c5.tar.gz
kernel-omap-294b04d109ad9654f0f6608e7963a2f821d784c5.tar.xz
kernel-omap-294b04d109ad9654f0f6608e7963a2f821d784c5.zip
drm/ast: deal with bo reserve fail in dirty update path
commit 306373b645d80625335b8e684fa09b14ba460cec upstream. Port over the mgag200 fix to ast as it suffers the same issue. On F19 testing, it was noticed we get a lot of errors in dmesg about being unable to reserve the buffer when plymouth starts, this is due to the buffer being in the process of migrating, so it makes sense we can't reserve it. In order to deal with it, this adds delayed updates for the dirty updates, when the bo is unreservable, in the normal console case this shouldn't ever happen, its just when plymouth or X is pushing the console bo to system memory. Signed-off-by: Dave Airlie <airlied@redhat.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-rw-r--r--drivers/gpu/drm/ast/ast_drv.h2
-rw-r--r--drivers/gpu/drm/ast/ast_fb.c43
-rw-r--r--drivers/gpu/drm/ast/ast_ttm.c2
3 files changed, 43 insertions, 4 deletions
diff --git a/drivers/gpu/drm/ast/ast_drv.h b/drivers/gpu/drm/ast/ast_drv.h
index 5ccf984f063a..cac9c9a4fe70 100644
--- a/drivers/gpu/drm/ast/ast_drv.h
+++ b/drivers/gpu/drm/ast/ast_drv.h
@@ -239,6 +239,8 @@ struct ast_fbdev {
239 void *sysram; 239 void *sysram;
240 int size; 240 int size;
241 struct ttm_bo_kmap_obj mapping; 241 struct ttm_bo_kmap_obj mapping;
242 int x1, y1, x2, y2; /* dirty rect */
243 spinlock_t dirty_lock;
242}; 244};
243 245
244#define to_ast_crtc(x) container_of(x, struct ast_crtc, base) 246#define to_ast_crtc(x) container_of(x, struct ast_crtc, base)
diff --git a/drivers/gpu/drm/ast/ast_fb.c b/drivers/gpu/drm/ast/ast_fb.c
index d9ec77959dff..9138678e7ea1 100644
--- a/drivers/gpu/drm/ast/ast_fb.c
+++ b/drivers/gpu/drm/ast/ast_fb.c
@@ -52,16 +52,52 @@ static void ast_dirty_update(struct ast_fbdev *afbdev,
52 int bpp = (afbdev->afb.base.bits_per_pixel + 7)/8; 52 int bpp = (afbdev->afb.base.bits_per_pixel + 7)/8;
53 int ret; 53 int ret;
54 bool unmap = false; 54 bool unmap = false;
55 bool store_for_later = false;
56 int x2, y2;
57 unsigned long flags;
55 58
56 obj = afbdev->afb.obj; 59 obj = afbdev->afb.obj;
57 bo = gem_to_ast_bo(obj); 60 bo = gem_to_ast_bo(obj);
58 61
62 /*
63 * try and reserve the BO, if we fail with busy
64 * then the BO is being moved and we should
65 * store up the damage until later.
66 */
59 ret = ast_bo_reserve(bo, true); 67 ret = ast_bo_reserve(bo, true);
60 if (ret) { 68 if (ret) {
61 DRM_ERROR("failed to reserve fb bo\n"); 69 if (ret != -EBUSY)
70 return;
71
72 store_for_later = true;
73 }
74
75 x2 = x + width - 1;
76 y2 = y + height - 1;
77 spin_lock_irqsave(&afbdev->dirty_lock, flags);
78
79 if (afbdev->y1 < y)
80 y = afbdev->y1;
81 if (afbdev->y2 > y2)
82 y2 = afbdev->y2;
83 if (afbdev->x1 < x)
84 x = afbdev->x1;
85 if (afbdev->x2 > x2)
86 x2 = afbdev->x2;
87
88 if (store_for_later) {
89 afbdev->x1 = x;
90 afbdev->x2 = x2;
91 afbdev->y1 = y;
92 afbdev->y2 = y2;
93 spin_unlock_irqrestore(&afbdev->dirty_lock, flags);
62 return; 94 return;
63 } 95 }
64 96
97 afbdev->x1 = afbdev->y1 = INT_MAX;
98 afbdev->x2 = afbdev->y2 = 0;
99 spin_unlock_irqrestore(&afbdev->dirty_lock, flags);
100
65 if (!bo->kmap.virtual) { 101 if (!bo->kmap.virtual) {
66 ret = ttm_bo_kmap(&bo->bo, 0, bo->bo.num_pages, &bo->kmap); 102 ret = ttm_bo_kmap(&bo->bo, 0, bo->bo.num_pages, &bo->kmap);
67 if (ret) { 103 if (ret) {
@@ -71,10 +107,10 @@ static void ast_dirty_update(struct ast_fbdev *afbdev,
71 } 107 }
72 unmap = true; 108 unmap = true;
73 } 109 }
74 for (i = y; i < y + height; i++) { 110 for (i = y; i <= y2; i++) {
75 /* assume equal stride for now */ 111 /* assume equal stride for now */
76 src_offset = dst_offset = i * afbdev->afb.base.pitches[0] + (x * bpp); 112 src_offset = dst_offset = i * afbdev->afb.base.pitches[0] + (x * bpp);
77 memcpy_toio(bo->kmap.virtual + src_offset, afbdev->sysram + src_offset, width * bpp); 113 memcpy_toio(bo->kmap.virtual + src_offset, afbdev->sysram + src_offset, (x2 - x + 1) * bpp);
78 114
79 } 115 }
80 if (unmap) 116 if (unmap)
@@ -305,6 +341,7 @@ int ast_fbdev_init(struct drm_device *dev)
305 341
306 ast->fbdev = afbdev; 342 ast->fbdev = afbdev;
307 afbdev->helper.funcs = &ast_fb_helper_funcs; 343 afbdev->helper.funcs = &ast_fb_helper_funcs;
344 spin_lock_init(&afbdev->dirty_lock);
308 ret = drm_fb_helper_init(dev, &afbdev->helper, 345 ret = drm_fb_helper_init(dev, &afbdev->helper,
309 1, 1); 346 1, 1);
310 if (ret) { 347 if (ret) {
diff --git a/drivers/gpu/drm/ast/ast_ttm.c b/drivers/gpu/drm/ast/ast_ttm.c
index 3602731a6112..09da3393c527 100644
--- a/drivers/gpu/drm/ast/ast_ttm.c
+++ b/drivers/gpu/drm/ast/ast_ttm.c
@@ -316,7 +316,7 @@ int ast_bo_reserve(struct ast_bo *bo, bool no_wait)
316 316
317 ret = ttm_bo_reserve(&bo->bo, true, no_wait, false, 0); 317 ret = ttm_bo_reserve(&bo->bo, true, no_wait, false, 0);
318 if (ret) { 318 if (ret) {
319 if (ret != -ERESTARTSYS) 319 if (ret != -ERESTARTSYS && ret != -EBUSY)
320 DRM_ERROR("reserve failed %p\n", bo); 320 DRM_ERROR("reserve failed %p\n", bo);
321 return ret; 321 return ret;
322 } 322 }