Skip to content

Commit a283773

Browse files
committed
Merge tag 'drm-misc-fixes-2023-01-12' of git://anongit.freedesktop.org/drm/drm-misc into drm-fixes
Several fixes for amdgpu (all addressing issues with fences), yet another orientation quirk for a Lenovo device, a use-after-free fix for virtio, a regression fix in TTM and a performance regression in drm buddy. Signed-off-by: Dave Airlie <[email protected]> From: Maxime Ripard <[email protected]> Link: https://patchwork.freedesktop.org/patch/msgid/20230112130954.pxt77g3a7rokha42@houat
2 parents b7bfaa7 + 5640e81 commit a283773

File tree

13 files changed

+202
-894
lines changed

13 files changed

+202
-894
lines changed

drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c

Lines changed: 34 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,8 @@ static int amdgpu_cs_parser_init(struct amdgpu_cs_parser *p,
6161
amdgpu_ctx_put(p->ctx);
6262
return -ECANCELED;
6363
}
64+
65+
amdgpu_sync_create(&p->sync);
6466
return 0;
6567
}
6668

@@ -452,18 +454,6 @@ static int amdgpu_syncobj_lookup_and_add(struct amdgpu_cs_parser *p,
452454
}
453455

454456
r = amdgpu_sync_fence(&p->sync, fence);
455-
if (r)
456-
goto error;
457-
458-
/*
459-
* When we have an explicit dependency it might be necessary to insert a
460-
* pipeline sync to make sure that all caches etc are flushed and the
461-
* next job actually sees the results from the previous one.
462-
*/
463-
if (fence->context == p->gang_leader->base.entity->fence_context)
464-
r = amdgpu_sync_fence(&p->gang_leader->explicit_sync, fence);
465-
466-
error:
467457
dma_fence_put(fence);
468458
return r;
469459
}
@@ -1188,10 +1178,19 @@ static int amdgpu_cs_vm_handling(struct amdgpu_cs_parser *p)
11881178
static int amdgpu_cs_sync_rings(struct amdgpu_cs_parser *p)
11891179
{
11901180
struct amdgpu_fpriv *fpriv = p->filp->driver_priv;
1181+
struct drm_gpu_scheduler *sched;
11911182
struct amdgpu_bo_list_entry *e;
1183+
struct dma_fence *fence;
11921184
unsigned int i;
11931185
int r;
11941186

1187+
r = amdgpu_ctx_wait_prev_fence(p->ctx, p->entities[p->gang_leader_idx]);
1188+
if (r) {
1189+
if (r != -ERESTARTSYS)
1190+
DRM_ERROR("amdgpu_ctx_wait_prev_fence failed.\n");
1191+
return r;
1192+
}
1193+
11951194
list_for_each_entry(e, &p->validated, tv.head) {
11961195
struct amdgpu_bo *bo = ttm_to_amdgpu_bo(e->tv.bo);
11971196
struct dma_resv *resv = bo->tbo.base.resv;
@@ -1211,10 +1210,24 @@ static int amdgpu_cs_sync_rings(struct amdgpu_cs_parser *p)
12111210
return r;
12121211
}
12131212

1214-
r = amdgpu_ctx_wait_prev_fence(p->ctx, p->entities[p->gang_leader_idx]);
1215-
if (r && r != -ERESTARTSYS)
1216-
DRM_ERROR("amdgpu_ctx_wait_prev_fence failed.\n");
1217-
return r;
1213+
sched = p->gang_leader->base.entity->rq->sched;
1214+
while ((fence = amdgpu_sync_get_fence(&p->sync))) {
1215+
struct drm_sched_fence *s_fence = to_drm_sched_fence(fence);
1216+
1217+
/*
1218+
* When we have an dependency it might be necessary to insert a
1219+
* pipeline sync to make sure that all caches etc are flushed and the
1220+
* next job actually sees the results from the previous one
1221+
* before we start executing on the same scheduler ring.
1222+
*/
1223+
if (!s_fence || s_fence->sched != sched)
1224+
continue;
1225+
1226+
r = amdgpu_sync_fence(&p->gang_leader->explicit_sync, fence);
1227+
if (r)
1228+
return r;
1229+
}
1230+
return 0;
12181231
}
12191232

12201233
static void amdgpu_cs_post_dependencies(struct amdgpu_cs_parser *p)
@@ -1254,9 +1267,12 @@ static int amdgpu_cs_submit(struct amdgpu_cs_parser *p,
12541267
continue;
12551268

12561269
fence = &p->jobs[i]->base.s_fence->scheduled;
1270+
dma_fence_get(fence);
12571271
r = drm_sched_job_add_dependency(&leader->base, fence);
1258-
if (r)
1272+
if (r) {
1273+
dma_fence_put(fence);
12591274
goto error_cleanup;
1275+
}
12601276
}
12611277

12621278
if (p->gang_size > 1) {
@@ -1344,6 +1360,7 @@ static void amdgpu_cs_parser_fini(struct amdgpu_cs_parser *parser)
13441360
{
13451361
unsigned i;
13461362

1363+
amdgpu_sync_free(&parser->sync);
13471364
for (i = 0; i < parser->num_post_deps; i++) {
13481365
drm_syncobj_put(parser->post_deps[i].syncobj);
13491366
kfree(parser->post_deps[i].chain);

drivers/gpu/drm/amd/amdgpu/amdgpu_sync.c

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -391,8 +391,10 @@ int amdgpu_sync_push_to_job(struct amdgpu_sync *sync, struct amdgpu_job *job)
391391

392392
dma_fence_get(f);
393393
r = drm_sched_job_add_dependency(&job->base, f);
394-
if (r)
394+
if (r) {
395+
dma_fence_put(f);
395396
return r;
397+
}
396398
}
397399
return 0;
398400
}

drivers/gpu/drm/drm_buddy.c

Lines changed: 54 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,25 @@ static void drm_block_free(struct drm_buddy *mm,
3838
kmem_cache_free(slab_blocks, block);
3939
}
4040

41+
static void list_insert_sorted(struct drm_buddy *mm,
42+
struct drm_buddy_block *block)
43+
{
44+
struct drm_buddy_block *node;
45+
struct list_head *head;
46+
47+
head = &mm->free_list[drm_buddy_block_order(block)];
48+
if (list_empty(head)) {
49+
list_add(&block->link, head);
50+
return;
51+
}
52+
53+
list_for_each_entry(node, head, link)
54+
if (drm_buddy_block_offset(block) < drm_buddy_block_offset(node))
55+
break;
56+
57+
__list_add(&block->link, node->link.prev, &node->link);
58+
}
59+
4160
static void mark_allocated(struct drm_buddy_block *block)
4261
{
4362
block->header &= ~DRM_BUDDY_HEADER_STATE;
@@ -52,8 +71,7 @@ static void mark_free(struct drm_buddy *mm,
5271
block->header &= ~DRM_BUDDY_HEADER_STATE;
5372
block->header |= DRM_BUDDY_FREE;
5473

55-
list_add(&block->link,
56-
&mm->free_list[drm_buddy_block_order(block)]);
74+
list_insert_sorted(mm, block);
5775
}
5876

5977
static void mark_split(struct drm_buddy_block *block)
@@ -387,20 +405,26 @@ alloc_range_bias(struct drm_buddy *mm,
387405
}
388406

389407
static struct drm_buddy_block *
390-
get_maxblock(struct list_head *head)
408+
get_maxblock(struct drm_buddy *mm, unsigned int order)
391409
{
392410
struct drm_buddy_block *max_block = NULL, *node;
411+
unsigned int i;
393412

394-
max_block = list_first_entry_or_null(head,
395-
struct drm_buddy_block,
396-
link);
397-
if (!max_block)
398-
return NULL;
413+
for (i = order; i <= mm->max_order; ++i) {
414+
if (!list_empty(&mm->free_list[i])) {
415+
node = list_last_entry(&mm->free_list[i],
416+
struct drm_buddy_block,
417+
link);
418+
if (!max_block) {
419+
max_block = node;
420+
continue;
421+
}
399422

400-
list_for_each_entry(node, head, link) {
401-
if (drm_buddy_block_offset(node) >
402-
drm_buddy_block_offset(max_block))
403-
max_block = node;
423+
if (drm_buddy_block_offset(node) >
424+
drm_buddy_block_offset(max_block)) {
425+
max_block = node;
426+
}
427+
}
404428
}
405429

406430
return max_block;
@@ -412,20 +436,23 @@ alloc_from_freelist(struct drm_buddy *mm,
412436
unsigned long flags)
413437
{
414438
struct drm_buddy_block *block = NULL;
415-
unsigned int i;
439+
unsigned int tmp;
416440
int err;
417441

418-
for (i = order; i <= mm->max_order; ++i) {
419-
if (flags & DRM_BUDDY_TOPDOWN_ALLOCATION) {
420-
block = get_maxblock(&mm->free_list[i]);
421-
if (block)
422-
break;
423-
} else {
424-
block = list_first_entry_or_null(&mm->free_list[i],
425-
struct drm_buddy_block,
426-
link);
427-
if (block)
428-
break;
442+
if (flags & DRM_BUDDY_TOPDOWN_ALLOCATION) {
443+
block = get_maxblock(mm, order);
444+
if (block)
445+
/* Store the obtained block order */
446+
tmp = drm_buddy_block_order(block);
447+
} else {
448+
for (tmp = order; tmp <= mm->max_order; ++tmp) {
449+
if (!list_empty(&mm->free_list[tmp])) {
450+
block = list_last_entry(&mm->free_list[tmp],
451+
struct drm_buddy_block,
452+
link);
453+
if (block)
454+
break;
455+
}
429456
}
430457
}
431458

@@ -434,18 +461,18 @@ alloc_from_freelist(struct drm_buddy *mm,
434461

435462
BUG_ON(!drm_buddy_block_is_free(block));
436463

437-
while (i != order) {
464+
while (tmp != order) {
438465
err = split_block(mm, block);
439466
if (unlikely(err))
440467
goto err_undo;
441468

442469
block = block->right;
443-
i--;
470+
tmp--;
444471
}
445472
return block;
446473

447474
err_undo:
448-
if (i != order)
475+
if (tmp != order)
449476
__drm_buddy_free(mm, block);
450477
return ERR_PTR(err);
451478
}

drivers/gpu/drm/drm_panel_orientation_quirks.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -304,6 +304,12 @@ static const struct dmi_system_id orientation_data[] = {
304304
DMI_EXACT_MATCH(DMI_PRODUCT_VERSION, "Lenovo ideapad D330-10IGM"),
305305
},
306306
.driver_data = (void *)&lcd1200x1920_rightside_up,
307+
}, { /* Lenovo Ideapad D330-10IGL (HD) */
308+
.matches = {
309+
DMI_EXACT_MATCH(DMI_SYS_VENDOR, "LENOVO"),
310+
DMI_EXACT_MATCH(DMI_PRODUCT_VERSION, "Lenovo ideapad D330-10IGL"),
311+
},
312+
.driver_data = (void *)&lcd800x1280_rightside_up,
307313
}, { /* Lenovo Yoga Book X90F / X91F / X91L */
308314
.matches = {
309315
/* Non exact match to match all versions */

0 commit comments

Comments
 (0)