diff options
| author | Roy Spliet <r.spliet@student.tudelft.nl> | 2013-07-19 17:59:12 -0400 |
|---|---|---|
| committer | Ben Skeggs <bskeggs@redhat.com> | 2013-07-29 23:04:07 -0400 |
| commit | dedaa8f0e6967edb9127a6643d0259e794196ed2 (patch) | |
| tree | 31c7ac3757eb7fcce99b103ad843fc88f57e5c87 /drivers/gpu/drm/nouveau | |
| parent | bfcd92a0ae2996a34b1fd020b3e0951946ae6903 (diff) | |
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: Roy Spliet <r.spliet@student.tudelft.nl>
Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
Diffstat (limited to 'drivers/gpu/drm/nouveau')
| -rw-r--r-- | drivers/gpu/drm/nouveau/core/subdev/fb/priv.h | 2 | ||||
| -rw-r--r-- | drivers/gpu/drm/nouveau/core/subdev/fb/ramnv50.c | 22 | ||||
| -rw-r--r-- | drivers/gpu/drm/nouveau/core/subdev/fb/ramnvc0.c | 14 |
3 files changed, 26 insertions, 12 deletions
diff --git a/drivers/gpu/drm/nouveau/core/subdev/fb/priv.h b/drivers/gpu/drm/nouveau/core/subdev/fb/priv.h index 6c974dd83e8b..db9d6ddde52c 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/fb/priv.h +++ b/drivers/gpu/drm/nouveau/core/subdev/fb/priv.h | |||
| @@ -81,7 +81,7 @@ void nv44_fb_tile_prog(struct nouveau_fb *, int, struct nouveau_fb_tile *); | |||
| 81 | void nv46_fb_tile_init(struct nouveau_fb *, int i, u32 addr, u32 size, | 81 | void nv46_fb_tile_init(struct nouveau_fb *, int i, u32 addr, u32 size, |
| 82 | u32 pitch, u32 flags, struct nouveau_fb_tile *); | 82 | u32 pitch, u32 flags, struct nouveau_fb_tile *); |
| 83 | 83 | ||
| 84 | void nv50_ram_put(struct nouveau_fb *, struct nouveau_mem **); | 84 | void __nv50_ram_put(struct nouveau_fb *, struct nouveau_mem *); |
| 85 | extern int nv50_fb_memtype[0x80]; | 85 | extern int nv50_fb_memtype[0x80]; |
| 86 | 86 | ||
| 87 | #endif | 87 | #endif |
diff --git a/drivers/gpu/drm/nouveau/core/subdev/fb/ramnv50.c b/drivers/gpu/drm/nouveau/core/subdev/fb/ramnv50.c index af5aa7ee8ad9..903baff77fdd 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/fb/ramnv50.c +++ b/drivers/gpu/drm/nouveau/core/subdev/fb/ramnv50.c | |||
| @@ -27,17 +27,10 @@ | |||
| 27 | #include "priv.h" | 27 | #include "priv.h" |
| 28 | 28 | ||
| 29 | void | 29 | void |
| 30 | nv50_ram_put(struct nouveau_fb *pfb, struct nouveau_mem **pmem) | 30 | __nv50_ram_put(struct nouveau_fb *pfb, struct nouveau_mem *mem) |
| 31 | { | 31 | { |
| 32 | struct nouveau_mm_node *this; | 32 | struct nouveau_mm_node *this; |
| 33 | struct nouveau_mem *mem; | ||
| 34 | 33 | ||
| 35 | mem = *pmem; | ||
| 36 | *pmem = NULL; | ||
| 37 | if (unlikely(mem == NULL)) | ||
| 38 | return; | ||
| 39 | |||
| 40 | mutex_lock(&pfb->base.mutex); | ||
| 41 | while (!list_empty(&mem->regions)) { | 34 | while (!list_empty(&mem->regions)) { |
| 42 | this = list_first_entry(&mem->regions, typeof(*this), rl_entry); | 35 | this = list_first_entry(&mem->regions, typeof(*this), rl_entry); |
| 43 | 36 | ||
| @@ -46,6 +39,19 @@ nv50_ram_put(struct nouveau_fb *pfb, struct nouveau_mem **pmem) | |||
| 46 | } | 39 | } |
| 47 | 40 | ||
| 48 | nouveau_mm_free(&pfb->tags, &mem->tag); | 41 | nouveau_mm_free(&pfb->tags, &mem->tag); |
| 42 | } | ||
| 43 | |||
| 44 | void | ||
| 45 | nv50_ram_put(struct nouveau_fb *pfb, struct nouveau_mem **pmem) | ||
| 46 | { | ||
| 47 | struct nouveau_mem *mem = *pmem; | ||
| 48 | |||
| 49 | *pmem = NULL; | ||
| 50 | if (unlikely(mem == NULL)) | ||
| 51 | return; | ||
| 52 | |||
| 53 | mutex_lock(&pfb->base.mutex); | ||
| 54 | __nv50_ram_put(pfb, mem); | ||
| 49 | mutex_unlock(&pfb->base.mutex); | 55 | mutex_unlock(&pfb->base.mutex); |
| 50 | 56 | ||
| 51 | kfree(mem); | 57 | kfree(mem); |
diff --git a/drivers/gpu/drm/nouveau/core/subdev/fb/ramnvc0.c b/drivers/gpu/drm/nouveau/core/subdev/fb/ramnvc0.c index 9c3634acbb9d..cf97c4de4a6b 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/fb/ramnvc0.c +++ b/drivers/gpu/drm/nouveau/core/subdev/fb/ramnvc0.c | |||
| @@ -33,11 +33,19 @@ void | |||
| 33 | nvc0_ram_put(struct nouveau_fb *pfb, struct nouveau_mem **pmem) | 33 | nvc0_ram_put(struct nouveau_fb *pfb, struct nouveau_mem **pmem) |
| 34 | { | 34 | { |
| 35 | struct nouveau_ltcg *ltcg = nouveau_ltcg(pfb); | 35 | struct nouveau_ltcg *ltcg = nouveau_ltcg(pfb); |
| 36 | struct nouveau_mem *mem = *pmem; | ||
| 36 | 37 | ||
| 37 | if ((*pmem)->tag) | 38 | *pmem = NULL; |
| 38 | ltcg->tags_free(ltcg, &(*pmem)->tag); | 39 | if (unlikely(mem == NULL)) |
| 40 | return; | ||
| 39 | 41 | ||
| 40 | nv50_ram_put(pfb, pmem); | 42 | mutex_lock(&pfb->base.mutex); |
| 43 | if (mem->tag) | ||
| 44 | ltcg->tags_free(ltcg, &mem->tag); | ||
| 45 | __nv50_ram_put(pfb, mem); | ||
| 46 | mutex_unlock(&pfb->base.mutex); | ||
| 47 | |||
| 48 | kfree(mem); | ||
| 41 | } | 49 | } |
| 42 | 50 | ||
| 43 | int | 51 | int |
