Skip to content

Commit

Permalink
drm/nv50/kms: fix pin refcnt leaks
Browse files Browse the repository at this point in the history
Weren't critical previously, the buffers would go away anyway.  But with
recent changes to core drm/ttm lockdep will get pissed off now, so let's
fix it.

Reported-by: Maarten Lankhorst <maarten.lankhorst@canonical.com>
Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
Acked-by: Maarten Lankhorst <maarten.lankhorst@canonical.com>
  • Loading branch information
Ben Skeggs committed Jul 10, 2013
1 parent fdfb833 commit 8dda53f
Showing 1 changed file with 35 additions and 11 deletions.
46 changes: 35 additions & 11 deletions drivers/gpu/drm/nouveau/nv50_display.c
Original file line number Diff line number Diff line change
Expand Up @@ -355,6 +355,7 @@ struct nv50_oimm {

struct nv50_head {
struct nouveau_crtc base;
struct nouveau_bo *image;
struct nv50_curs curs;
struct nv50_sync sync;
struct nv50_ovly ovly;
Expand Down Expand Up @@ -517,9 +518,10 @@ nv50_display_flip_next(struct drm_crtc *crtc, struct drm_framebuffer *fb,
{
struct nouveau_framebuffer *nv_fb = nouveau_framebuffer(fb);
struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
struct nv50_head *head = nv50_head(crtc);
struct nv50_sync *sync = nv50_sync(crtc);
int head = nv_crtc->index, ret;
u32 *push;
int ret;

swap_interval <<= 4;
if (swap_interval == 0)
Expand All @@ -537,7 +539,7 @@ nv50_display_flip_next(struct drm_crtc *crtc, struct drm_framebuffer *fb,
return ret;

BEGIN_NV04(chan, 0, NV11_SUBCHAN_DMA_SEMAPHORE, 2);
OUT_RING (chan, NvEvoSema0 + head);
OUT_RING (chan, NvEvoSema0 + nv_crtc->index);
OUT_RING (chan, sync->addr ^ 0x10);
BEGIN_NV04(chan, 0, NV11_SUBCHAN_SEMAPHORE_RELEASE, 1);
OUT_RING (chan, sync->data + 1);
Expand All @@ -546,7 +548,7 @@ nv50_display_flip_next(struct drm_crtc *crtc, struct drm_framebuffer *fb,
OUT_RING (chan, sync->data);
} else
if (chan && nv_mclass(chan->object) < NVC0_CHANNEL_IND_CLASS) {
u64 addr = nv84_fence_crtc(chan, head) + sync->addr;
u64 addr = nv84_fence_crtc(chan, nv_crtc->index) + sync->addr;
ret = RING_SPACE(chan, 12);
if (ret)
return ret;
Expand All @@ -565,7 +567,7 @@ nv50_display_flip_next(struct drm_crtc *crtc, struct drm_framebuffer *fb,
OUT_RING (chan, NV84_SUBCHAN_SEMAPHORE_TRIGGER_ACQUIRE_EQUAL);
} else
if (chan) {
u64 addr = nv84_fence_crtc(chan, head) + sync->addr;
u64 addr = nv84_fence_crtc(chan, nv_crtc->index) + sync->addr;
ret = RING_SPACE(chan, 10);
if (ret)
return ret;
Expand Down Expand Up @@ -630,6 +632,8 @@ nv50_display_flip_next(struct drm_crtc *crtc, struct drm_framebuffer *fb,
evo_mthd(push, 0x0080, 1);
evo_data(push, 0x00000000);
evo_kick(push, sync);

nouveau_bo_ref(nv_fb->nvbo, &head->image);
return 0;
}

Expand Down Expand Up @@ -1038,18 +1042,17 @@ static int
nv50_crtc_swap_fbs(struct drm_crtc *crtc, struct drm_framebuffer *old_fb)
{
struct nouveau_framebuffer *nvfb = nouveau_framebuffer(crtc->fb);
struct nv50_head *head = nv50_head(crtc);
int ret;

ret = nouveau_bo_pin(nvfb->nvbo, TTM_PL_FLAG_VRAM);
if (ret)
return ret;

if (old_fb) {
nvfb = nouveau_framebuffer(old_fb);
nouveau_bo_unpin(nvfb->nvbo);
if (ret == 0) {
if (head->image)
nouveau_bo_unpin(head->image);
nouveau_bo_ref(nvfb->nvbo, &head->image);
}

return 0;
return ret;
}

static int
Expand Down Expand Up @@ -1198,6 +1201,15 @@ nv50_crtc_lut_load(struct drm_crtc *crtc)
}
}

static void
nv50_crtc_disable(struct drm_crtc *crtc)
{
struct nv50_head *head = nv50_head(crtc);
if (head->image)
nouveau_bo_unpin(head->image);
nouveau_bo_ref(NULL, &head->image);
}

static int
nv50_crtc_cursor_set(struct drm_crtc *crtc, struct drm_file *file_priv,
uint32_t handle, uint32_t width, uint32_t height)
Expand Down Expand Up @@ -1271,18 +1283,29 @@ nv50_crtc_destroy(struct drm_crtc *crtc)
struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
struct nv50_disp *disp = nv50_disp(crtc->dev);
struct nv50_head *head = nv50_head(crtc);

nv50_dmac_destroy(disp->core, &head->ovly.base);
nv50_pioc_destroy(disp->core, &head->oimm.base);
nv50_dmac_destroy(disp->core, &head->sync.base);
nv50_pioc_destroy(disp->core, &head->curs.base);

/*XXX: this shouldn't be necessary, but the core doesn't call
* disconnect() during the cleanup paths
*/
if (head->image)
nouveau_bo_unpin(head->image);
nouveau_bo_ref(NULL, &head->image);

nouveau_bo_unmap(nv_crtc->cursor.nvbo);
if (nv_crtc->cursor.nvbo)
nouveau_bo_unpin(nv_crtc->cursor.nvbo);
nouveau_bo_ref(NULL, &nv_crtc->cursor.nvbo);

nouveau_bo_unmap(nv_crtc->lut.nvbo);
if (nv_crtc->lut.nvbo)
nouveau_bo_unpin(nv_crtc->lut.nvbo);
nouveau_bo_ref(NULL, &nv_crtc->lut.nvbo);

drm_crtc_cleanup(crtc);
kfree(crtc);
}
Expand All @@ -1296,6 +1319,7 @@ static const struct drm_crtc_helper_funcs nv50_crtc_hfunc = {
.mode_set_base = nv50_crtc_mode_set_base,
.mode_set_base_atomic = nv50_crtc_mode_set_base_atomic,
.load_lut = nv50_crtc_lut_load,
.disable = nv50_crtc_disable,
};

static const struct drm_crtc_funcs nv50_crtc_func = {
Expand Down

0 comments on commit 8dda53f

Please sign in to comment.