aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDave Airlie2013-05-01 23:52:01 -0500
committerGreg Kroah-Hartman2013-05-11 15:53:59 -0500
commit47d9848811228290f12d4bf04882215cfccbf9f1 (patch)
tree6d402699e5e323e9b6d97bde97043bdc14c6d56f
parent52af8300d2a3478a621791f122bd9c4e3eb5840a (diff)
downloadkernel-omap-47d9848811228290f12d4bf04882215cfccbf9f1.tar.gz
kernel-omap-47d9848811228290f12d4bf04882215cfccbf9f1.tar.xz
kernel-omap-47d9848811228290f12d4bf04882215cfccbf9f1.zip
drm/mgag200: deal with bo reserve fail in dirty update path
commit 641719599528d806e00de8ae8c8453361266a312 upstream. 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/mgag200/mgag200_drv.h2
-rw-r--r--drivers/gpu/drm/mgag200/mgag200_fb.c43
-rw-r--r--drivers/gpu/drm/mgag200/mgag200_ttm.c4
3 files changed, 44 insertions, 5 deletions
diff --git a/drivers/gpu/drm/mgag200/mgag200_drv.h b/drivers/gpu/drm/mgag200/mgag200_drv.h
index 5ea5033eae0a..a657709aefd6 100644
--- a/drivers/gpu/drm/mgag200/mgag200_drv.h
+++ b/drivers/gpu/drm/mgag200/mgag200_drv.h
@@ -116,6 +116,8 @@ struct mga_fbdev {
116 void *sysram; 116 void *sysram;
117 int size; 117 int size;
118 struct ttm_bo_kmap_obj mapping; 118 struct ttm_bo_kmap_obj mapping;
119 int x1, y1, x2, y2; /* dirty rect */
120 spinlock_t dirty_lock;
119}; 121};
120 122
121struct mga_crtc { 123struct mga_crtc {
diff --git a/drivers/gpu/drm/mgag200/mgag200_fb.c b/drivers/gpu/drm/mgag200/mgag200_fb.c
index 2f486481d79a..41eefc4473bf 100644
--- a/drivers/gpu/drm/mgag200/mgag200_fb.c
+++ b/drivers/gpu/drm/mgag200/mgag200_fb.c
@@ -28,16 +28,52 @@ static void mga_dirty_update(struct mga_fbdev *mfbdev,
28 int bpp = (mfbdev->mfb.base.bits_per_pixel + 7)/8; 28 int bpp = (mfbdev->mfb.base.bits_per_pixel + 7)/8;
29 int ret; 29 int ret;
30 bool unmap = false; 30 bool unmap = false;
31 bool store_for_later = false;
32 int x2, y2;
33 unsigned long flags;
31 34
32 obj = mfbdev->mfb.obj; 35 obj = mfbdev->mfb.obj;
33 bo = gem_to_mga_bo(obj); 36 bo = gem_to_mga_bo(obj);
34 37
38 /*
39 * try and reserve the BO, if we fail with busy
40 * then the BO is being moved and we should
41 * store up the damage until later.
42 */
35 ret = mgag200_bo_reserve(bo, true); 43 ret = mgag200_bo_reserve(bo, true);
36 if (ret) { 44 if (ret) {
37 DRM_ERROR("failed to reserve fb bo\n"); 45 if (ret != -EBUSY)
46 return;
47
48 store_for_later = true;
49 }
50
51 x2 = x + width - 1;
52 y2 = y + height - 1;
53 spin_lock_irqsave(&mfbdev->dirty_lock, flags);
54
55 if (mfbdev->y1 < y)
56 y = mfbdev->y1;
57 if (mfbdev->y2 > y2)
58 y2 = mfbdev->y2;
59 if (mfbdev->x1 < x)
60 x = mfbdev->x1;
61 if (mfbdev->x2 > x2)
62 x2 = mfbdev->x2;
63
64 if (store_for_later) {
65 mfbdev->x1 = x;
66 mfbdev->x2 = x2;
67 mfbdev->y1 = y;
68 mfbdev->y2 = y2;
69 spin_unlock_irqrestore(&mfbdev->dirty_lock, flags);
38 return; 70 return;
39 } 71 }
40 72
73 mfbdev->x1 = mfbdev->y1 = INT_MAX;
74 mfbdev->x2 = mfbdev->y2 = 0;
75 spin_unlock_irqrestore(&mfbdev->dirty_lock, flags);
76
41 if (!bo->kmap.virtual) { 77 if (!bo->kmap.virtual) {
42 ret = ttm_bo_kmap(&bo->bo, 0, bo->bo.num_pages, &bo->kmap); 78 ret = ttm_bo_kmap(&bo->bo, 0, bo->bo.num_pages, &bo->kmap);
43 if (ret) { 79 if (ret) {
@@ -47,10 +83,10 @@ static void mga_dirty_update(struct mga_fbdev *mfbdev,
47 } 83 }
48 unmap = true; 84 unmap = true;
49 } 85 }
50 for (i = y; i < y + height; i++) { 86 for (i = y; i <= y2; i++) {
51 /* assume equal stride for now */ 87 /* assume equal stride for now */
52 src_offset = dst_offset = i * mfbdev->mfb.base.pitches[0] + (x * bpp); 88 src_offset = dst_offset = i * mfbdev->mfb.base.pitches[0] + (x * bpp);
53 memcpy_toio(bo->kmap.virtual + src_offset, mfbdev->sysram + src_offset, width * bpp); 89 memcpy_toio(bo->kmap.virtual + src_offset, mfbdev->sysram + src_offset, (x2 - x + 1) * bpp);
54 90
55 } 91 }
56 if (unmap) 92 if (unmap)
@@ -269,6 +305,7 @@ int mgag200_fbdev_init(struct mga_device *mdev)
269 305
270 mdev->mfbdev = mfbdev; 306 mdev->mfbdev = mfbdev;
271 mfbdev->helper.funcs = &mga_fb_helper_funcs; 307 mfbdev->helper.funcs = &mga_fb_helper_funcs;
308 spin_lock_init(&mfbdev->dirty_lock);
272 309
273 ret = drm_fb_helper_init(mdev->dev, &mfbdev->helper, 310 ret = drm_fb_helper_init(mdev->dev, &mfbdev->helper,
274 mdev->num_crtc, MGAG200FB_CONN_LIMIT); 311 mdev->num_crtc, MGAG200FB_CONN_LIMIT);
diff --git a/drivers/gpu/drm/mgag200/mgag200_ttm.c b/drivers/gpu/drm/mgag200/mgag200_ttm.c
index 8fc9d9201945..401c9891d3a8 100644
--- a/drivers/gpu/drm/mgag200/mgag200_ttm.c
+++ b/drivers/gpu/drm/mgag200/mgag200_ttm.c
@@ -315,8 +315,8 @@ int mgag200_bo_reserve(struct mgag200_bo *bo, bool no_wait)
315 315
316 ret = ttm_bo_reserve(&bo->bo, true, no_wait, false, 0); 316 ret = ttm_bo_reserve(&bo->bo, true, no_wait, false, 0);
317 if (ret) { 317 if (ret) {
318 if (ret != -ERESTARTSYS) 318 if (ret != -ERESTARTSYS && ret != -EBUSY)
319 DRM_ERROR("reserve failed %p\n", bo); 319 DRM_ERROR("reserve failed %p %d\n", bo, ret);
320 return ret; 320 return ret;
321 } 321 }
322 return 0; 322 return 0;