diff options
Diffstat (limited to 'drivers/gpu/drm/nouveau/nouveau_display.c')
-rw-r--r-- | drivers/gpu/drm/nouveau/nouveau_display.c | 69 |
1 files changed, 31 insertions, 38 deletions
diff --git a/drivers/gpu/drm/nouveau/nouveau_display.c b/drivers/gpu/drm/nouveau/nouveau_display.c index 708b2d1c0037..907d20ef6d4d 100644 --- a/drivers/gpu/drm/nouveau/nouveau_display.c +++ b/drivers/gpu/drm/nouveau/nouveau_display.c | |||
@@ -138,7 +138,7 @@ nouveau_user_framebuffer_create(struct drm_device *dev, | |||
138 | { | 138 | { |
139 | struct nouveau_framebuffer *nouveau_fb; | 139 | struct nouveau_framebuffer *nouveau_fb; |
140 | struct drm_gem_object *gem; | 140 | struct drm_gem_object *gem; |
141 | int ret; | 141 | int ret = -ENOMEM; |
142 | 142 | ||
143 | gem = drm_gem_object_lookup(dev, file_priv, mode_cmd->handles[0]); | 143 | gem = drm_gem_object_lookup(dev, file_priv, mode_cmd->handles[0]); |
144 | if (!gem) | 144 | if (!gem) |
@@ -146,15 +146,19 @@ nouveau_user_framebuffer_create(struct drm_device *dev, | |||
146 | 146 | ||
147 | nouveau_fb = kzalloc(sizeof(struct nouveau_framebuffer), GFP_KERNEL); | 147 | nouveau_fb = kzalloc(sizeof(struct nouveau_framebuffer), GFP_KERNEL); |
148 | if (!nouveau_fb) | 148 | if (!nouveau_fb) |
149 | return ERR_PTR(-ENOMEM); | 149 | goto err_unref; |
150 | 150 | ||
151 | ret = nouveau_framebuffer_init(dev, nouveau_fb, mode_cmd, nouveau_gem_object(gem)); | 151 | ret = nouveau_framebuffer_init(dev, nouveau_fb, mode_cmd, nouveau_gem_object(gem)); |
152 | if (ret) { | 152 | if (ret) |
153 | drm_gem_object_unreference(gem); | 153 | goto err; |
154 | return ERR_PTR(ret); | ||
155 | } | ||
156 | 154 | ||
157 | return &nouveau_fb->base; | 155 | return &nouveau_fb->base; |
156 | |||
157 | err: | ||
158 | kfree(nouveau_fb); | ||
159 | err_unref: | ||
160 | drm_gem_object_unreference(gem); | ||
161 | return ERR_PTR(ret); | ||
158 | } | 162 | } |
159 | 163 | ||
160 | static const struct drm_mode_config_funcs nouveau_mode_config_funcs = { | 164 | static const struct drm_mode_config_funcs nouveau_mode_config_funcs = { |
@@ -524,9 +528,12 @@ nouveau_crtc_page_flip(struct drm_crtc *crtc, struct drm_framebuffer *fb, | |||
524 | struct nouveau_page_flip_state *s; | 528 | struct nouveau_page_flip_state *s; |
525 | struct nouveau_channel *chan = NULL; | 529 | struct nouveau_channel *chan = NULL; |
526 | struct nouveau_fence *fence; | 530 | struct nouveau_fence *fence; |
527 | struct list_head res; | 531 | struct ttm_validate_buffer resv[2] = { |
528 | struct ttm_validate_buffer res_val[2]; | 532 | { .bo = &old_bo->bo }, |
533 | { .bo = &new_bo->bo }, | ||
534 | }; | ||
529 | struct ww_acquire_ctx ticket; | 535 | struct ww_acquire_ctx ticket; |
536 | LIST_HEAD(res); | ||
530 | int ret; | 537 | int ret; |
531 | 538 | ||
532 | if (!drm->channel) | 539 | if (!drm->channel) |
@@ -545,27 +552,19 @@ nouveau_crtc_page_flip(struct drm_crtc *crtc, struct drm_framebuffer *fb, | |||
545 | chan = drm->channel; | 552 | chan = drm->channel; |
546 | spin_unlock(&old_bo->bo.bdev->fence_lock); | 553 | spin_unlock(&old_bo->bo.bdev->fence_lock); |
547 | 554 | ||
548 | mutex_lock(&chan->cli->mutex); | ||
549 | |||
550 | if (new_bo != old_bo) { | 555 | if (new_bo != old_bo) { |
551 | ret = nouveau_bo_pin(new_bo, TTM_PL_FLAG_VRAM); | 556 | ret = nouveau_bo_pin(new_bo, TTM_PL_FLAG_VRAM); |
552 | if (likely(!ret)) { | 557 | if (ret) |
553 | res_val[0].bo = &old_bo->bo; | 558 | goto fail_free; |
554 | res_val[1].bo = &new_bo->bo; | ||
555 | INIT_LIST_HEAD(&res); | ||
556 | list_add_tail(&res_val[0].head, &res); | ||
557 | list_add_tail(&res_val[1].head, &res); | ||
558 | ret = ttm_eu_reserve_buffers(&ticket, &res); | ||
559 | if (ret) | ||
560 | nouveau_bo_unpin(new_bo); | ||
561 | } | ||
562 | } else | ||
563 | ret = ttm_bo_reserve(&new_bo->bo, false, false, false, 0); | ||
564 | 559 | ||
565 | if (ret) { | 560 | list_add(&resv[1].head, &res); |
566 | mutex_unlock(&chan->cli->mutex); | ||
567 | goto fail_free; | ||
568 | } | 561 | } |
562 | list_add(&resv[0].head, &res); | ||
563 | |||
564 | mutex_lock(&chan->cli->mutex); | ||
565 | ret = ttm_eu_reserve_buffers(&ticket, &res); | ||
566 | if (ret) | ||
567 | goto fail_unpin; | ||
569 | 568 | ||
570 | /* Initialize a page flip struct */ | 569 | /* Initialize a page flip struct */ |
571 | *s = (struct nouveau_page_flip_state) | 570 | *s = (struct nouveau_page_flip_state) |
@@ -576,10 +575,8 @@ nouveau_crtc_page_flip(struct drm_crtc *crtc, struct drm_framebuffer *fb, | |||
576 | /* Emit a page flip */ | 575 | /* Emit a page flip */ |
577 | if (nv_device(drm->device)->card_type >= NV_50) { | 576 | if (nv_device(drm->device)->card_type >= NV_50) { |
578 | ret = nv50_display_flip_next(crtc, fb, chan, 0); | 577 | ret = nv50_display_flip_next(crtc, fb, chan, 0); |
579 | if (ret) { | 578 | if (ret) |
580 | mutex_unlock(&chan->cli->mutex); | ||
581 | goto fail_unreserve; | 579 | goto fail_unreserve; |
582 | } | ||
583 | } | 580 | } |
584 | 581 | ||
585 | ret = nouveau_page_flip_emit(chan, old_bo, new_bo, s, &fence); | 582 | ret = nouveau_page_flip_emit(chan, old_bo, new_bo, s, &fence); |
@@ -590,22 +587,18 @@ nouveau_crtc_page_flip(struct drm_crtc *crtc, struct drm_framebuffer *fb, | |||
590 | /* Update the crtc struct and cleanup */ | 587 | /* Update the crtc struct and cleanup */ |
591 | crtc->fb = fb; | 588 | crtc->fb = fb; |
592 | 589 | ||
593 | if (old_bo != new_bo) { | 590 | ttm_eu_fence_buffer_objects(&ticket, &res, fence); |
594 | ttm_eu_fence_buffer_objects(&ticket, &res, fence); | 591 | if (old_bo != new_bo) |
595 | nouveau_bo_unpin(old_bo); | 592 | nouveau_bo_unpin(old_bo); |
596 | } else { | ||
597 | nouveau_bo_fence(new_bo, fence); | ||
598 | ttm_bo_unreserve(&new_bo->bo); | ||
599 | } | ||
600 | nouveau_fence_unref(&fence); | 593 | nouveau_fence_unref(&fence); |
601 | return 0; | 594 | return 0; |
602 | 595 | ||
603 | fail_unreserve: | 596 | fail_unreserve: |
604 | if (old_bo != new_bo) { | 597 | ttm_eu_backoff_reservation(&ticket, &res); |
605 | ttm_eu_backoff_reservation(&ticket, &res); | 598 | fail_unpin: |
599 | mutex_unlock(&chan->cli->mutex); | ||
600 | if (old_bo != new_bo) | ||
606 | nouveau_bo_unpin(new_bo); | 601 | nouveau_bo_unpin(new_bo); |
607 | } else | ||
608 | ttm_bo_unreserve(&new_bo->bo); | ||
609 | fail_free: | 602 | fail_free: |
610 | kfree(s); | 603 | kfree(s); |
611 | return ret; | 604 | return ret; |