Commit dedaa8f0 authored by Roy Spliet's avatar Roy Spliet Committed by Ben Skeggs

drm/nvc0/fb: take lock in nvc0_ram_put()

Kernel panic caused by list corruption in ltcg seems to indicate a
concurrency issue.

Take mutex of pfb like nv50_ram_put() to eliminate concurrency.

V2: Separate critical section into separate function, avoid taking the
    lock twice on NVC0
Signed-off-by: default avatarRoy Spliet <r.spliet@student.tudelft.nl>
Signed-off-by: default avatarBen Skeggs <bskeggs@redhat.com>
parent bfcd92a0
...@@ -81,7 +81,7 @@ void nv44_fb_tile_prog(struct nouveau_fb *, int, struct nouveau_fb_tile *); ...@@ -81,7 +81,7 @@ void nv44_fb_tile_prog(struct nouveau_fb *, int, struct nouveau_fb_tile *);
void nv46_fb_tile_init(struct nouveau_fb *, int i, u32 addr, u32 size, void nv46_fb_tile_init(struct nouveau_fb *, int i, u32 addr, u32 size,
u32 pitch, u32 flags, struct nouveau_fb_tile *); u32 pitch, u32 flags, struct nouveau_fb_tile *);
void nv50_ram_put(struct nouveau_fb *, struct nouveau_mem **); void __nv50_ram_put(struct nouveau_fb *, struct nouveau_mem *);
extern int nv50_fb_memtype[0x80]; extern int nv50_fb_memtype[0x80];
#endif #endif
...@@ -27,17 +27,10 @@ ...@@ -27,17 +27,10 @@
#include "priv.h" #include "priv.h"
void void
nv50_ram_put(struct nouveau_fb *pfb, struct nouveau_mem **pmem) __nv50_ram_put(struct nouveau_fb *pfb, struct nouveau_mem *mem)
{ {
struct nouveau_mm_node *this; struct nouveau_mm_node *this;
struct nouveau_mem *mem;
mem = *pmem;
*pmem = NULL;
if (unlikely(mem == NULL))
return;
mutex_lock(&pfb->base.mutex);
while (!list_empty(&mem->regions)) { while (!list_empty(&mem->regions)) {
this = list_first_entry(&mem->regions, typeof(*this), rl_entry); this = list_first_entry(&mem->regions, typeof(*this), rl_entry);
...@@ -46,6 +39,19 @@ nv50_ram_put(struct nouveau_fb *pfb, struct nouveau_mem **pmem) ...@@ -46,6 +39,19 @@ nv50_ram_put(struct nouveau_fb *pfb, struct nouveau_mem **pmem)
} }
nouveau_mm_free(&pfb->tags, &mem->tag); nouveau_mm_free(&pfb->tags, &mem->tag);
}
void
nv50_ram_put(struct nouveau_fb *pfb, struct nouveau_mem **pmem)
{
struct nouveau_mem *mem = *pmem;
*pmem = NULL;
if (unlikely(mem == NULL))
return;
mutex_lock(&pfb->base.mutex);
__nv50_ram_put(pfb, mem);
mutex_unlock(&pfb->base.mutex); mutex_unlock(&pfb->base.mutex);
kfree(mem); kfree(mem);
......
...@@ -33,11 +33,19 @@ void ...@@ -33,11 +33,19 @@ void
nvc0_ram_put(struct nouveau_fb *pfb, struct nouveau_mem **pmem) nvc0_ram_put(struct nouveau_fb *pfb, struct nouveau_mem **pmem)
{ {
struct nouveau_ltcg *ltcg = nouveau_ltcg(pfb); struct nouveau_ltcg *ltcg = nouveau_ltcg(pfb);
struct nouveau_mem *mem = *pmem;
if ((*pmem)->tag) *pmem = NULL;
ltcg->tags_free(ltcg, &(*pmem)->tag); if (unlikely(mem == NULL))
return;
nv50_ram_put(pfb, pmem); mutex_lock(&pfb->base.mutex);
if (mem->tag)
ltcg->tags_free(ltcg, &mem->tag);
__nv50_ram_put(pfb, mem);
mutex_unlock(&pfb->base.mutex);
kfree(mem);
} }
int int
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment