mirror of
https://github.com/edk2-porting/linux-next.git
synced 2024-12-23 12:43:55 +08:00
drm/nv50/kms: fix pin refcnt leaks
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>
This commit is contained in:
parent
fdfb833265
commit
8dda53fca2
@ -355,6 +355,7 @@ struct nv50_oimm {
|
|||||||
|
|
||||||
struct nv50_head {
|
struct nv50_head {
|
||||||
struct nouveau_crtc base;
|
struct nouveau_crtc base;
|
||||||
|
struct nouveau_bo *image;
|
||||||
struct nv50_curs curs;
|
struct nv50_curs curs;
|
||||||
struct nv50_sync sync;
|
struct nv50_sync sync;
|
||||||
struct nv50_ovly ovly;
|
struct nv50_ovly ovly;
|
||||||
@ -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_framebuffer *nv_fb = nouveau_framebuffer(fb);
|
||||||
struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
|
struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
|
||||||
|
struct nv50_head *head = nv50_head(crtc);
|
||||||
struct nv50_sync *sync = nv50_sync(crtc);
|
struct nv50_sync *sync = nv50_sync(crtc);
|
||||||
int head = nv_crtc->index, ret;
|
|
||||||
u32 *push;
|
u32 *push;
|
||||||
|
int ret;
|
||||||
|
|
||||||
swap_interval <<= 4;
|
swap_interval <<= 4;
|
||||||
if (swap_interval == 0)
|
if (swap_interval == 0)
|
||||||
@ -537,7 +539,7 @@ nv50_display_flip_next(struct drm_crtc *crtc, struct drm_framebuffer *fb,
|
|||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
BEGIN_NV04(chan, 0, NV11_SUBCHAN_DMA_SEMAPHORE, 2);
|
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);
|
OUT_RING (chan, sync->addr ^ 0x10);
|
||||||
BEGIN_NV04(chan, 0, NV11_SUBCHAN_SEMAPHORE_RELEASE, 1);
|
BEGIN_NV04(chan, 0, NV11_SUBCHAN_SEMAPHORE_RELEASE, 1);
|
||||||
OUT_RING (chan, sync->data + 1);
|
OUT_RING (chan, sync->data + 1);
|
||||||
@ -546,7 +548,7 @@ nv50_display_flip_next(struct drm_crtc *crtc, struct drm_framebuffer *fb,
|
|||||||
OUT_RING (chan, sync->data);
|
OUT_RING (chan, sync->data);
|
||||||
} else
|
} else
|
||||||
if (chan && nv_mclass(chan->object) < NVC0_CHANNEL_IND_CLASS) {
|
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);
|
ret = RING_SPACE(chan, 12);
|
||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
@ -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);
|
OUT_RING (chan, NV84_SUBCHAN_SEMAPHORE_TRIGGER_ACQUIRE_EQUAL);
|
||||||
} else
|
} else
|
||||||
if (chan) {
|
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);
|
ret = RING_SPACE(chan, 10);
|
||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
@ -630,6 +632,8 @@ nv50_display_flip_next(struct drm_crtc *crtc, struct drm_framebuffer *fb,
|
|||||||
evo_mthd(push, 0x0080, 1);
|
evo_mthd(push, 0x0080, 1);
|
||||||
evo_data(push, 0x00000000);
|
evo_data(push, 0x00000000);
|
||||||
evo_kick(push, sync);
|
evo_kick(push, sync);
|
||||||
|
|
||||||
|
nouveau_bo_ref(nv_fb->nvbo, &head->image);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1038,18 +1042,17 @@ static int
|
|||||||
nv50_crtc_swap_fbs(struct drm_crtc *crtc, struct drm_framebuffer *old_fb)
|
nv50_crtc_swap_fbs(struct drm_crtc *crtc, struct drm_framebuffer *old_fb)
|
||||||
{
|
{
|
||||||
struct nouveau_framebuffer *nvfb = nouveau_framebuffer(crtc->fb);
|
struct nouveau_framebuffer *nvfb = nouveau_framebuffer(crtc->fb);
|
||||||
|
struct nv50_head *head = nv50_head(crtc);
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
ret = nouveau_bo_pin(nvfb->nvbo, TTM_PL_FLAG_VRAM);
|
ret = nouveau_bo_pin(nvfb->nvbo, TTM_PL_FLAG_VRAM);
|
||||||
if (ret)
|
if (ret == 0) {
|
||||||
return ret;
|
if (head->image)
|
||||||
|
nouveau_bo_unpin(head->image);
|
||||||
if (old_fb) {
|
nouveau_bo_ref(nvfb->nvbo, &head->image);
|
||||||
nvfb = nouveau_framebuffer(old_fb);
|
|
||||||
nouveau_bo_unpin(nvfb->nvbo);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
@ -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
|
static int
|
||||||
nv50_crtc_cursor_set(struct drm_crtc *crtc, struct drm_file *file_priv,
|
nv50_crtc_cursor_set(struct drm_crtc *crtc, struct drm_file *file_priv,
|
||||||
uint32_t handle, uint32_t width, uint32_t height)
|
uint32_t handle, uint32_t width, uint32_t height)
|
||||||
@ -1271,18 +1283,29 @@ nv50_crtc_destroy(struct drm_crtc *crtc)
|
|||||||
struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
|
struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
|
||||||
struct nv50_disp *disp = nv50_disp(crtc->dev);
|
struct nv50_disp *disp = nv50_disp(crtc->dev);
|
||||||
struct nv50_head *head = nv50_head(crtc);
|
struct nv50_head *head = nv50_head(crtc);
|
||||||
|
|
||||||
nv50_dmac_destroy(disp->core, &head->ovly.base);
|
nv50_dmac_destroy(disp->core, &head->ovly.base);
|
||||||
nv50_pioc_destroy(disp->core, &head->oimm.base);
|
nv50_pioc_destroy(disp->core, &head->oimm.base);
|
||||||
nv50_dmac_destroy(disp->core, &head->sync.base);
|
nv50_dmac_destroy(disp->core, &head->sync.base);
|
||||||
nv50_pioc_destroy(disp->core, &head->curs.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);
|
nouveau_bo_unmap(nv_crtc->cursor.nvbo);
|
||||||
if (nv_crtc->cursor.nvbo)
|
if (nv_crtc->cursor.nvbo)
|
||||||
nouveau_bo_unpin(nv_crtc->cursor.nvbo);
|
nouveau_bo_unpin(nv_crtc->cursor.nvbo);
|
||||||
nouveau_bo_ref(NULL, &nv_crtc->cursor.nvbo);
|
nouveau_bo_ref(NULL, &nv_crtc->cursor.nvbo);
|
||||||
|
|
||||||
nouveau_bo_unmap(nv_crtc->lut.nvbo);
|
nouveau_bo_unmap(nv_crtc->lut.nvbo);
|
||||||
if (nv_crtc->lut.nvbo)
|
if (nv_crtc->lut.nvbo)
|
||||||
nouveau_bo_unpin(nv_crtc->lut.nvbo);
|
nouveau_bo_unpin(nv_crtc->lut.nvbo);
|
||||||
nouveau_bo_ref(NULL, &nv_crtc->lut.nvbo);
|
nouveau_bo_ref(NULL, &nv_crtc->lut.nvbo);
|
||||||
|
|
||||||
drm_crtc_cleanup(crtc);
|
drm_crtc_cleanup(crtc);
|
||||||
kfree(crtc);
|
kfree(crtc);
|
||||||
}
|
}
|
||||||
@ -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 = nv50_crtc_mode_set_base,
|
||||||
.mode_set_base_atomic = nv50_crtc_mode_set_base_atomic,
|
.mode_set_base_atomic = nv50_crtc_mode_set_base_atomic,
|
||||||
.load_lut = nv50_crtc_lut_load,
|
.load_lut = nv50_crtc_lut_load,
|
||||||
|
.disable = nv50_crtc_disable,
|
||||||
};
|
};
|
||||||
|
|
||||||
static const struct drm_crtc_funcs nv50_crtc_func = {
|
static const struct drm_crtc_funcs nv50_crtc_func = {
|
||||||
|
Loading…
Reference in New Issue
Block a user