aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/nouveau/nouveau_display.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm/nouveau/nouveau_display.c')
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_display.c127
1 files changed, 56 insertions, 71 deletions
diff --git a/drivers/gpu/drm/nouveau/nouveau_display.c b/drivers/gpu/drm/nouveau/nouveau_display.c
index f17dc2ab03ec..907d20ef6d4d 100644
--- a/drivers/gpu/drm/nouveau/nouveau_display.c
+++ b/drivers/gpu/drm/nouveau/nouveau_display.c
@@ -26,6 +26,7 @@
#include <drm/drmP.h>
#include <drm/drm_crtc_helper.h>
+#include <drm/ttm/ttm_execbuf_util.h>
#include "nouveau_fbcon.h"
#include "dispnv04/hw.h"
@@ -137,7 +138,7 @@ nouveau_user_framebuffer_create(struct drm_device *dev,
{
struct nouveau_framebuffer *nouveau_fb;
struct drm_gem_object *gem;
- int ret;
+ int ret = -ENOMEM;
gem = drm_gem_object_lookup(dev, file_priv, mode_cmd->handles[0]);
if (!gem)
@@ -145,15 +146,19 @@ nouveau_user_framebuffer_create(struct drm_device *dev,
nouveau_fb = kzalloc(sizeof(struct nouveau_framebuffer), GFP_KERNEL);
if (!nouveau_fb)
- return ERR_PTR(-ENOMEM);
+ goto err_unref;
ret = nouveau_framebuffer_init(dev, nouveau_fb, mode_cmd, nouveau_gem_object(gem));
- if (ret) {
- drm_gem_object_unreference(gem);
- return ERR_PTR(ret);
- }
+ if (ret)
+ goto err;
return &nouveau_fb->base;
+
+err:
+ kfree(nouveau_fb);
+err_unref:
+ drm_gem_object_unreference(gem);
+ return ERR_PTR(ret);
}
static const struct drm_mode_config_funcs nouveau_mode_config_funcs = {
@@ -332,10 +337,15 @@ nouveau_display_create(struct drm_device *dev)
if (nouveau_modeset == 1 ||
(nouveau_modeset < 0 && pclass == PCI_CLASS_DISPLAY_VGA)) {
- if (nv_device(drm->device)->card_type < NV_50)
- ret = nv04_display_create(dev);
- else
- ret = nv50_display_create(dev);
+ if (drm->vbios.dcb.entries) {
+ if (nv_device(drm->device)->card_type < NV_50)
+ ret = nv04_display_create(dev);
+ else
+ ret = nv50_display_create(dev);
+ } else {
+ ret = 0;
+ }
+
if (ret)
goto disp_create_err;
@@ -457,51 +467,6 @@ nouveau_display_resume(struct drm_device *dev)
}
static int
-nouveau_page_flip_reserve(struct nouveau_bo *old_bo,
- struct nouveau_bo *new_bo)
-{
- int ret;
-
- ret = nouveau_bo_pin(new_bo, TTM_PL_FLAG_VRAM);
- if (ret)
- return ret;
-
- ret = ttm_bo_reserve(&new_bo->bo, false, false, false, 0);
- if (ret)
- goto fail;
-
- if (likely(old_bo != new_bo)) {
- ret = ttm_bo_reserve(&old_bo->bo, false, false, false, 0);
- if (ret)
- goto fail_unreserve;
- }
-
- return 0;
-
-fail_unreserve:
- ttm_bo_unreserve(&new_bo->bo);
-fail:
- nouveau_bo_unpin(new_bo);
- return ret;
-}
-
-static void
-nouveau_page_flip_unreserve(struct nouveau_bo *old_bo,
- struct nouveau_bo *new_bo,
- struct nouveau_fence *fence)
-{
- nouveau_bo_fence(new_bo, fence);
- ttm_bo_unreserve(&new_bo->bo);
-
- if (likely(old_bo != new_bo)) {
- nouveau_bo_fence(old_bo, fence);
- ttm_bo_unreserve(&old_bo->bo);
- }
-
- nouveau_bo_unpin(old_bo);
-}
-
-static int
nouveau_page_flip_emit(struct nouveau_channel *chan,
struct nouveau_bo *old_bo,
struct nouveau_bo *new_bo,
@@ -563,6 +528,12 @@ nouveau_crtc_page_flip(struct drm_crtc *crtc, struct drm_framebuffer *fb,
struct nouveau_page_flip_state *s;
struct nouveau_channel *chan = NULL;
struct nouveau_fence *fence;
+ struct ttm_validate_buffer resv[2] = {
+ { .bo = &old_bo->bo },
+ { .bo = &new_bo->bo },
+ };
+ struct ww_acquire_ctx ticket;
+ LIST_HEAD(res);
int ret;
if (!drm->channel)
@@ -572,32 +543,40 @@ nouveau_crtc_page_flip(struct drm_crtc *crtc, struct drm_framebuffer *fb,
if (!s)
return -ENOMEM;
- /* Don't let the buffers go away while we flip */
- ret = nouveau_page_flip_reserve(old_bo, new_bo);
- if (ret)
- goto fail_free;
-
- /* Initialize a page flip struct */
- *s = (struct nouveau_page_flip_state)
- { { }, event, nouveau_crtc(crtc)->index,
- fb->bits_per_pixel, fb->pitches[0], crtc->x, crtc->y,
- new_bo->bo.offset };
-
/* Choose the channel the flip will be handled in */
+ spin_lock(&old_bo->bo.bdev->fence_lock);
fence = new_bo->bo.sync_obj;
if (fence)
chan = fence->channel;
if (!chan)
chan = drm->channel;
+ spin_unlock(&old_bo->bo.bdev->fence_lock);
+
+ if (new_bo != old_bo) {
+ ret = nouveau_bo_pin(new_bo, TTM_PL_FLAG_VRAM);
+ if (ret)
+ goto fail_free;
+
+ list_add(&resv[1].head, &res);
+ }
+ list_add(&resv[0].head, &res);
+
mutex_lock(&chan->cli->mutex);
+ ret = ttm_eu_reserve_buffers(&ticket, &res);
+ if (ret)
+ goto fail_unpin;
+
+ /* Initialize a page flip struct */
+ *s = (struct nouveau_page_flip_state)
+ { { }, event, nouveau_crtc(crtc)->index,
+ fb->bits_per_pixel, fb->pitches[0], crtc->x, crtc->y,
+ new_bo->bo.offset };
/* Emit a page flip */
if (nv_device(drm->device)->card_type >= NV_50) {
ret = nv50_display_flip_next(crtc, fb, chan, 0);
- if (ret) {
- mutex_unlock(&chan->cli->mutex);
+ if (ret)
goto fail_unreserve;
- }
}
ret = nouveau_page_flip_emit(chan, old_bo, new_bo, s, &fence);
@@ -608,12 +587,18 @@ nouveau_crtc_page_flip(struct drm_crtc *crtc, struct drm_framebuffer *fb,
/* Update the crtc struct and cleanup */
crtc->fb = fb;
- nouveau_page_flip_unreserve(old_bo, new_bo, fence);
+ ttm_eu_fence_buffer_objects(&ticket, &res, fence);
+ if (old_bo != new_bo)
+ nouveau_bo_unpin(old_bo);
nouveau_fence_unref(&fence);
return 0;
fail_unreserve:
- nouveau_page_flip_unreserve(old_bo, new_bo, NULL);
+ ttm_eu_backoff_reservation(&ticket, &res);
+fail_unpin:
+ mutex_unlock(&chan->cli->mutex);
+ if (old_bo != new_bo)
+ nouveau_bo_unpin(new_bo);
fail_free:
kfree(s);
return ret;