Skip to content

Commit d2dbaaf

Browse files
committed
Merge branch 'server-fixes' into drm-next
Merge the fixes for the server driver dirty update paths * server-fixes: drm/cirrus: deal with bo reserve fail in dirty update path drm/ast: deal with bo reserve fail in dirty update path drm/mgag200: deal with bo reserve fail in dirty update path
2 parents 7e17fc0 + f3b2bbd commit d2dbaaf

File tree

9 files changed

+127
-11
lines changed

9 files changed

+127
-11
lines changed

drivers/gpu/drm/ast/ast_drv.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -241,6 +241,8 @@ struct ast_fbdev {
241241
void *sysram;
242242
int size;
243243
struct ttm_bo_kmap_obj mapping;
244+
int x1, y1, x2, y2; /* dirty rect */
245+
spinlock_t dirty_lock;
244246
};
245247

246248
#define to_ast_crtc(x) container_of(x, struct ast_crtc, base)

drivers/gpu/drm/ast/ast_fb.c

Lines changed: 40 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -53,16 +53,52 @@ static void ast_dirty_update(struct ast_fbdev *afbdev,
5353
int bpp = (afbdev->afb.base.bits_per_pixel + 7)/8;
5454
int ret;
5555
bool unmap = false;
56+
bool store_for_later = false;
57+
int x2, y2;
58+
unsigned long flags;
5659

5760
obj = afbdev->afb.obj;
5861
bo = gem_to_ast_bo(obj);
5962

63+
/*
64+
* try and reserve the BO, if we fail with busy
65+
* then the BO is being moved and we should
66+
* store up the damage until later.
67+
*/
6068
ret = ast_bo_reserve(bo, true);
6169
if (ret) {
62-
DRM_ERROR("failed to reserve fb bo\n");
70+
if (ret != -EBUSY)
71+
return;
72+
73+
store_for_later = true;
74+
}
75+
76+
x2 = x + width - 1;
77+
y2 = y + height - 1;
78+
spin_lock_irqsave(&afbdev->dirty_lock, flags);
79+
80+
if (afbdev->y1 < y)
81+
y = afbdev->y1;
82+
if (afbdev->y2 > y2)
83+
y2 = afbdev->y2;
84+
if (afbdev->x1 < x)
85+
x = afbdev->x1;
86+
if (afbdev->x2 > x2)
87+
x2 = afbdev->x2;
88+
89+
if (store_for_later) {
90+
afbdev->x1 = x;
91+
afbdev->x2 = x2;
92+
afbdev->y1 = y;
93+
afbdev->y2 = y2;
94+
spin_unlock_irqrestore(&afbdev->dirty_lock, flags);
6395
return;
6496
}
6597

98+
afbdev->x1 = afbdev->y1 = INT_MAX;
99+
afbdev->x2 = afbdev->y2 = 0;
100+
spin_unlock_irqrestore(&afbdev->dirty_lock, flags);
101+
66102
if (!bo->kmap.virtual) {
67103
ret = ttm_bo_kmap(&bo->bo, 0, bo->bo.num_pages, &bo->kmap);
68104
if (ret) {
@@ -72,10 +108,10 @@ static void ast_dirty_update(struct ast_fbdev *afbdev,
72108
}
73109
unmap = true;
74110
}
75-
for (i = y; i < y + height; i++) {
111+
for (i = y; i <= y2; i++) {
76112
/* assume equal stride for now */
77113
src_offset = dst_offset = i * afbdev->afb.base.pitches[0] + (x * bpp);
78-
memcpy_toio(bo->kmap.virtual + src_offset, afbdev->sysram + src_offset, width * bpp);
114+
memcpy_toio(bo->kmap.virtual + src_offset, afbdev->sysram + src_offset, (x2 - x + 1) * bpp);
79115

80116
}
81117
if (unmap)
@@ -292,6 +328,7 @@ int ast_fbdev_init(struct drm_device *dev)
292328

293329
ast->fbdev = afbdev;
294330
afbdev->helper.funcs = &ast_fb_helper_funcs;
331+
spin_lock_init(&afbdev->dirty_lock);
295332
ret = drm_fb_helper_init(dev, &afbdev->helper,
296333
1, 1);
297334
if (ret) {

drivers/gpu/drm/ast/ast_ttm.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -316,7 +316,7 @@ int ast_bo_reserve(struct ast_bo *bo, bool no_wait)
316316

317317
ret = ttm_bo_reserve(&bo->bo, true, no_wait, false, 0);
318318
if (ret) {
319-
if (ret != -ERESTARTSYS)
319+
if (ret != -ERESTARTSYS && ret != -EBUSY)
320320
DRM_ERROR("reserve failed %p\n", bo);
321321
return ret;
322322
}

drivers/gpu/drm/cirrus/cirrus_drv.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -154,6 +154,8 @@ struct cirrus_fbdev {
154154
struct list_head fbdev_list;
155155
void *sysram;
156156
int size;
157+
int x1, y1, x2, y2; /* dirty rect */
158+
spinlock_t dirty_lock;
157159
};
158160

159161
struct cirrus_bo {

drivers/gpu/drm/cirrus/cirrus_fbdev.c

Lines changed: 37 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,16 +27,51 @@ static void cirrus_dirty_update(struct cirrus_fbdev *afbdev,
2727
int bpp = (afbdev->gfb.base.bits_per_pixel + 7)/8;
2828
int ret;
2929
bool unmap = false;
30+
bool store_for_later = false;
31+
int x2, y2;
32+
unsigned long flags;
3033

3134
obj = afbdev->gfb.obj;
3235
bo = gem_to_cirrus_bo(obj);
3336

37+
/*
38+
* try and reserve the BO, if we fail with busy
39+
* then the BO is being moved and we should
40+
* store up the damage until later.
41+
*/
3442
ret = cirrus_bo_reserve(bo, true);
3543
if (ret) {
36-
DRM_ERROR("failed to reserve fb bo\n");
44+
if (ret != -EBUSY)
45+
return;
46+
store_for_later = true;
47+
}
48+
49+
x2 = x + width - 1;
50+
y2 = y + height - 1;
51+
spin_lock_irqsave(&afbdev->dirty_lock, flags);
52+
53+
if (afbdev->y1 < y)
54+
y = afbdev->y1;
55+
if (afbdev->y2 > y2)
56+
y2 = afbdev->y2;
57+
if (afbdev->x1 < x)
58+
x = afbdev->x1;
59+
if (afbdev->x2 > x2)
60+
x2 = afbdev->x2;
61+
62+
if (store_for_later) {
63+
afbdev->x1 = x;
64+
afbdev->x2 = x2;
65+
afbdev->y1 = y;
66+
afbdev->y2 = y2;
67+
spin_unlock_irqrestore(&afbdev->dirty_lock, flags);
3768
return;
3869
}
3970

71+
afbdev->x1 = afbdev->y1 = INT_MAX;
72+
afbdev->x2 = afbdev->y2 = 0;
73+
spin_unlock_irqrestore(&afbdev->dirty_lock, flags);
74+
4075
if (!bo->kmap.virtual) {
4176
ret = ttm_bo_kmap(&bo->bo, 0, bo->bo.num_pages, &bo->kmap);
4277
if (ret) {
@@ -268,6 +303,7 @@ int cirrus_fbdev_init(struct cirrus_device *cdev)
268303

269304
cdev->mode_info.gfbdev = gfbdev;
270305
gfbdev->helper.funcs = &cirrus_fb_helper_funcs;
306+
spin_lock_init(&gfbdev->dirty_lock);
271307

272308
ret = drm_fb_helper_init(cdev->dev, &gfbdev->helper,
273309
cdev->num_crtc, CIRRUSFB_CONN_LIMIT);

drivers/gpu/drm/cirrus/cirrus_ttm.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -321,7 +321,7 @@ int cirrus_bo_reserve(struct cirrus_bo *bo, bool no_wait)
321321

322322
ret = ttm_bo_reserve(&bo->bo, true, no_wait, false, 0);
323323
if (ret) {
324-
if (ret != -ERESTARTSYS)
324+
if (ret != -ERESTARTSYS && ret != -EBUSY)
325325
DRM_ERROR("reserve failed %p\n", bo);
326326
return ret;
327327
}

drivers/gpu/drm/mgag200/mgag200_drv.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,8 @@ struct mga_fbdev {
115115
void *sysram;
116116
int size;
117117
struct ttm_bo_kmap_obj mapping;
118+
int x1, y1, x2, y2; /* dirty rect */
119+
spinlock_t dirty_lock;
118120
};
119121

120122
struct mga_crtc {

drivers/gpu/drm/mgag200/mgag200_fb.c

Lines changed: 40 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -29,16 +29,52 @@ static void mga_dirty_update(struct mga_fbdev *mfbdev,
2929
int bpp = (mfbdev->mfb.base.bits_per_pixel + 7)/8;
3030
int ret;
3131
bool unmap = false;
32+
bool store_for_later = false;
33+
int x2, y2;
34+
unsigned long flags;
3235

3336
obj = mfbdev->mfb.obj;
3437
bo = gem_to_mga_bo(obj);
3538

39+
/*
40+
* try and reserve the BO, if we fail with busy
41+
* then the BO is being moved and we should
42+
* store up the damage until later.
43+
*/
3644
ret = mgag200_bo_reserve(bo, true);
3745
if (ret) {
38-
DRM_ERROR("failed to reserve fb bo\n");
46+
if (ret != -EBUSY)
47+
return;
48+
49+
store_for_later = true;
50+
}
51+
52+
x2 = x + width - 1;
53+
y2 = y + height - 1;
54+
spin_lock_irqsave(&mfbdev->dirty_lock, flags);
55+
56+
if (mfbdev->y1 < y)
57+
y = mfbdev->y1;
58+
if (mfbdev->y2 > y2)
59+
y2 = mfbdev->y2;
60+
if (mfbdev->x1 < x)
61+
x = mfbdev->x1;
62+
if (mfbdev->x2 > x2)
63+
x2 = mfbdev->x2;
64+
65+
if (store_for_later) {
66+
mfbdev->x1 = x;
67+
mfbdev->x2 = x2;
68+
mfbdev->y1 = y;
69+
mfbdev->y2 = y2;
70+
spin_unlock_irqrestore(&mfbdev->dirty_lock, flags);
3971
return;
4072
}
4173

74+
mfbdev->x1 = mfbdev->y1 = INT_MAX;
75+
mfbdev->x2 = mfbdev->y2 = 0;
76+
spin_unlock_irqrestore(&mfbdev->dirty_lock, flags);
77+
4278
if (!bo->kmap.virtual) {
4379
ret = ttm_bo_kmap(&bo->bo, 0, bo->bo.num_pages, &bo->kmap);
4480
if (ret) {
@@ -48,10 +84,10 @@ static void mga_dirty_update(struct mga_fbdev *mfbdev,
4884
}
4985
unmap = true;
5086
}
51-
for (i = y; i < y + height; i++) {
87+
for (i = y; i <= y2; i++) {
5288
/* assume equal stride for now */
5389
src_offset = dst_offset = i * mfbdev->mfb.base.pitches[0] + (x * bpp);
54-
memcpy_toio(bo->kmap.virtual + src_offset, mfbdev->sysram + src_offset, width * bpp);
90+
memcpy_toio(bo->kmap.virtual + src_offset, mfbdev->sysram + src_offset, (x2 - x + 1) * bpp);
5591

5692
}
5793
if (unmap)
@@ -252,6 +288,7 @@ int mgag200_fbdev_init(struct mga_device *mdev)
252288

253289
mdev->mfbdev = mfbdev;
254290
mfbdev->helper.funcs = &mga_fb_helper_funcs;
291+
spin_lock_init(&mfbdev->dirty_lock);
255292

256293
ret = drm_fb_helper_init(mdev->dev, &mfbdev->helper,
257294
mdev->num_crtc, MGAG200FB_CONN_LIMIT);

drivers/gpu/drm/mgag200/mgag200_ttm.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -315,8 +315,8 @@ int mgag200_bo_reserve(struct mgag200_bo *bo, bool no_wait)
315315

316316
ret = ttm_bo_reserve(&bo->bo, true, no_wait, false, 0);
317317
if (ret) {
318-
if (ret != -ERESTARTSYS)
319-
DRM_ERROR("reserve failed %p\n", bo);
318+
if (ret != -ERESTARTSYS && ret != -EBUSY)
319+
DRM_ERROR("reserve failed %p %d\n", bo, ret);
320320
return ret;
321321
}
322322
return 0;

0 commit comments

Comments
 (0)