Skip to content

Commit ecff665

Browse files
mlankhorstairlied
authored andcommitted
drm/ttm: make ttm reservation calls behave like reservation calls
This commit converts the source of the val_seq counter to the ww_mutex api. The reservation objects are converted later, because there is still a lockdep splat in nouveau that has to resolved first. Signed-off-by: Maarten Lankhorst <[email protected]> Reviewed-by: Jerome Glisse <[email protected]> Signed-off-by: Dave Airlie <[email protected]>
1 parent 786d725 commit ecff665

13 files changed

+172
-112
lines changed

drivers/gpu/drm/nouveau/nouveau_gem.c

Lines changed: 25 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -277,10 +277,12 @@ struct validate_op {
277277
struct list_head vram_list;
278278
struct list_head gart_list;
279279
struct list_head both_list;
280+
struct ww_acquire_ctx ticket;
280281
};
281282

282283
static void
283-
validate_fini_list(struct list_head *list, struct nouveau_fence *fence)
284+
validate_fini_list(struct list_head *list, struct nouveau_fence *fence,
285+
struct ww_acquire_ctx *ticket)
284286
{
285287
struct list_head *entry, *tmp;
286288
struct nouveau_bo *nvbo;
@@ -297,17 +299,24 @@ validate_fini_list(struct list_head *list, struct nouveau_fence *fence)
297299

298300
list_del(&nvbo->entry);
299301
nvbo->reserved_by = NULL;
300-
ttm_bo_unreserve(&nvbo->bo);
302+
ttm_bo_unreserve_ticket(&nvbo->bo, ticket);
301303
drm_gem_object_unreference_unlocked(nvbo->gem);
302304
}
303305
}
304306

305307
static void
306-
validate_fini(struct validate_op *op, struct nouveau_fence* fence)
308+
validate_fini_no_ticket(struct validate_op *op, struct nouveau_fence *fence)
307309
{
308-
validate_fini_list(&op->vram_list, fence);
309-
validate_fini_list(&op->gart_list, fence);
310-
validate_fini_list(&op->both_list, fence);
310+
validate_fini_list(&op->vram_list, fence, &op->ticket);
311+
validate_fini_list(&op->gart_list, fence, &op->ticket);
312+
validate_fini_list(&op->both_list, fence, &op->ticket);
313+
}
314+
315+
static void
316+
validate_fini(struct validate_op *op, struct nouveau_fence *fence)
317+
{
318+
validate_fini_no_ticket(op, fence);
319+
ww_acquire_fini(&op->ticket);
311320
}
312321

313322
static int
@@ -317,13 +326,11 @@ validate_init(struct nouveau_channel *chan, struct drm_file *file_priv,
317326
{
318327
struct nouveau_cli *cli = nouveau_cli(file_priv);
319328
struct drm_device *dev = chan->drm->dev;
320-
struct nouveau_drm *drm = nouveau_drm(dev);
321-
uint32_t sequence;
322329
int trycnt = 0;
323330
int ret, i;
324331
struct nouveau_bo *res_bo = NULL;
325332

326-
sequence = atomic_add_return(1, &drm->ttm.validate_sequence);
333+
ww_acquire_init(&op->ticket, &reservation_ww_class);
327334
retry:
328335
if (++trycnt > 100000) {
329336
NV_ERROR(cli, "%s failed and gave up.\n", __func__);
@@ -338,6 +345,7 @@ validate_init(struct nouveau_channel *chan, struct drm_file *file_priv,
338345
gem = drm_gem_object_lookup(dev, file_priv, b->handle);
339346
if (!gem) {
340347
NV_ERROR(cli, "Unknown handle 0x%08x\n", b->handle);
348+
ww_acquire_done(&op->ticket);
341349
validate_fini(op, NULL);
342350
return -ENOENT;
343351
}
@@ -352,21 +360,23 @@ validate_init(struct nouveau_channel *chan, struct drm_file *file_priv,
352360
NV_ERROR(cli, "multiple instances of buffer %d on "
353361
"validation list\n", b->handle);
354362
drm_gem_object_unreference_unlocked(gem);
363+
ww_acquire_done(&op->ticket);
355364
validate_fini(op, NULL);
356365
return -EINVAL;
357366
}
358367

359-
ret = ttm_bo_reserve(&nvbo->bo, true, false, true, sequence);
368+
ret = ttm_bo_reserve(&nvbo->bo, true, false, true, &op->ticket);
360369
if (ret) {
361-
validate_fini(op, NULL);
370+
validate_fini_no_ticket(op, NULL);
362371
if (unlikely(ret == -EAGAIN)) {
363-
sequence = atomic_add_return(1, &drm->ttm.validate_sequence);
364372
ret = ttm_bo_reserve_slowpath(&nvbo->bo, true,
365-
sequence);
373+
&op->ticket);
366374
if (!ret)
367375
res_bo = nvbo;
368376
}
369377
if (unlikely(ret)) {
378+
ww_acquire_done(&op->ticket);
379+
ww_acquire_fini(&op->ticket);
370380
drm_gem_object_unreference_unlocked(gem);
371381
if (ret != -ERESTARTSYS)
372382
NV_ERROR(cli, "fail reserve\n");
@@ -390,13 +400,15 @@ validate_init(struct nouveau_channel *chan, struct drm_file *file_priv,
390400
NV_ERROR(cli, "invalid valid domains: 0x%08x\n",
391401
b->valid_domains);
392402
list_add_tail(&nvbo->entry, &op->both_list);
403+
ww_acquire_done(&op->ticket);
393404
validate_fini(op, NULL);
394405
return -EINVAL;
395406
}
396407
if (nvbo == res_bo)
397408
goto retry;
398409
}
399410

411+
ww_acquire_done(&op->ticket);
400412
return 0;
401413
}
402414

drivers/gpu/drm/radeon/radeon.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -979,6 +979,7 @@ struct radeon_cs_parser {
979979
u32 cs_flags;
980980
u32 ring;
981981
s32 priority;
982+
struct ww_acquire_ctx ticket;
982983
};
983984

984985
extern int radeon_cs_finish_pages(struct radeon_cs_parser *p);

drivers/gpu/drm/radeon/radeon_cs.c

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,7 @@ static int radeon_cs_parser_relocs(struct radeon_cs_parser *p)
106106
radeon_bo_list_add_object(&p->relocs[i].lobj,
107107
&p->validated);
108108
}
109-
return radeon_bo_list_validate(&p->validated, p->ring);
109+
return radeon_bo_list_validate(&p->ticket, &p->validated, p->ring);
110110
}
111111

112112
static int radeon_cs_get_ring(struct radeon_cs_parser *p, u32 ring, s32 priority)
@@ -314,15 +314,17 @@ int radeon_cs_parser_init(struct radeon_cs_parser *p, void *data)
314314
* If error is set than unvalidate buffer, otherwise just free memory
315315
* used by parsing context.
316316
**/
317-
static void radeon_cs_parser_fini(struct radeon_cs_parser *parser, int error)
317+
static void radeon_cs_parser_fini(struct radeon_cs_parser *parser, int error, bool backoff)
318318
{
319319
unsigned i;
320320

321321
if (!error) {
322-
ttm_eu_fence_buffer_objects(&parser->validated,
322+
ttm_eu_fence_buffer_objects(&parser->ticket,
323+
&parser->validated,
323324
parser->ib.fence);
324-
} else {
325-
ttm_eu_backoff_reservation(&parser->validated);
325+
} else if (backoff) {
326+
ttm_eu_backoff_reservation(&parser->ticket,
327+
&parser->validated);
326328
}
327329

328330
if (parser->relocs != NULL) {
@@ -535,7 +537,7 @@ int radeon_cs_ioctl(struct drm_device *dev, void *data, struct drm_file *filp)
535537
r = radeon_cs_parser_init(&parser, data);
536538
if (r) {
537539
DRM_ERROR("Failed to initialize parser !\n");
538-
radeon_cs_parser_fini(&parser, r);
540+
radeon_cs_parser_fini(&parser, r, false);
539541
up_read(&rdev->exclusive_lock);
540542
r = radeon_cs_handle_lockup(rdev, r);
541543
return r;
@@ -544,7 +546,7 @@ int radeon_cs_ioctl(struct drm_device *dev, void *data, struct drm_file *filp)
544546
if (r) {
545547
if (r != -ERESTARTSYS)
546548
DRM_ERROR("Failed to parse relocation %d!\n", r);
547-
radeon_cs_parser_fini(&parser, r);
549+
radeon_cs_parser_fini(&parser, r, false);
548550
up_read(&rdev->exclusive_lock);
549551
r = radeon_cs_handle_lockup(rdev, r);
550552
return r;
@@ -563,7 +565,7 @@ int radeon_cs_ioctl(struct drm_device *dev, void *data, struct drm_file *filp)
563565
goto out;
564566
}
565567
out:
566-
radeon_cs_parser_fini(&parser, r);
568+
radeon_cs_parser_fini(&parser, r, true);
567569
up_read(&rdev->exclusive_lock);
568570
r = radeon_cs_handle_lockup(rdev, r);
569571
return r;

drivers/gpu/drm/radeon/radeon_object.c

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -349,14 +349,15 @@ void radeon_bo_list_add_object(struct radeon_bo_list *lobj,
349349
}
350350
}
351351

352-
int radeon_bo_list_validate(struct list_head *head, int ring)
352+
int radeon_bo_list_validate(struct ww_acquire_ctx *ticket,
353+
struct list_head *head, int ring)
353354
{
354355
struct radeon_bo_list *lobj;
355356
struct radeon_bo *bo;
356357
u32 domain;
357358
int r;
358359

359-
r = ttm_eu_reserve_buffers(head);
360+
r = ttm_eu_reserve_buffers(ticket, head);
360361
if (unlikely(r != 0)) {
361362
return r;
362363
}

drivers/gpu/drm/radeon/radeon_object.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -128,7 +128,8 @@ extern int radeon_bo_init(struct radeon_device *rdev);
128128
extern void radeon_bo_fini(struct radeon_device *rdev);
129129
extern void radeon_bo_list_add_object(struct radeon_bo_list *lobj,
130130
struct list_head *head);
131-
extern int radeon_bo_list_validate(struct list_head *head, int ring);
131+
extern int radeon_bo_list_validate(struct ww_acquire_ctx *ticket,
132+
struct list_head *head, int ring);
132133
extern int radeon_bo_fbdev_mmap(struct radeon_bo *bo,
133134
struct vm_area_struct *vma);
134135
extern int radeon_bo_set_tiling_flags(struct radeon_bo *bo,

drivers/gpu/drm/radeon/radeon_uvd.c

Lines changed: 13 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -550,6 +550,7 @@ static int radeon_uvd_send_msg(struct radeon_device *rdev,
550550
struct radeon_fence **fence)
551551
{
552552
struct ttm_validate_buffer tv;
553+
struct ww_acquire_ctx ticket;
553554
struct list_head head;
554555
struct radeon_ib ib;
555556
uint64_t addr;
@@ -561,24 +562,20 @@ static int radeon_uvd_send_msg(struct radeon_device *rdev,
561562
INIT_LIST_HEAD(&head);
562563
list_add(&tv.head, &head);
563564

564-
r = ttm_eu_reserve_buffers(&head);
565+
r = ttm_eu_reserve_buffers(&ticket, &head);
565566
if (r)
566567
return r;
567568

568569
radeon_ttm_placement_from_domain(bo, RADEON_GEM_DOMAIN_VRAM);
569570
radeon_uvd_force_into_uvd_segment(bo);
570571

571572
r = ttm_bo_validate(&bo->tbo, &bo->placement, true, false);
572-
if (r) {
573-
ttm_eu_backoff_reservation(&head);
574-
return r;
575-
}
573+
if (r)
574+
goto err;
576575

577576
r = radeon_ib_get(rdev, ring, &ib, NULL, 16);
578-
if (r) {
579-
ttm_eu_backoff_reservation(&head);
580-
return r;
581-
}
577+
if (r)
578+
goto err;
582579

583580
addr = radeon_bo_gpu_offset(bo);
584581
ib.ptr[0] = PACKET0(UVD_GPCOM_VCPU_DATA0, 0);
@@ -592,18 +589,20 @@ static int radeon_uvd_send_msg(struct radeon_device *rdev,
592589
ib.length_dw = 16;
593590

594591
r = radeon_ib_schedule(rdev, &ib, NULL);
595-
if (r) {
596-
ttm_eu_backoff_reservation(&head);
597-
return r;
598-
}
599-
ttm_eu_fence_buffer_objects(&head, ib.fence);
592+
if (r)
593+
goto err;
594+
ttm_eu_fence_buffer_objects(&ticket, &head, ib.fence);
600595

601596
if (fence)
602597
*fence = radeon_fence_ref(ib.fence);
603598

604599
radeon_ib_free(rdev, &ib);
605600
radeon_bo_unref(&bo);
606601
return 0;
602+
603+
err:
604+
ttm_eu_backoff_reservation(&ticket, &head);
605+
return r;
607606
}
608607

609608
/* multiple fence commands without any stream commands in between can

0 commit comments

Comments
 (0)