Commit f5cfbd99 authored by Ben Skeggs's avatar Ben Skeggs

drm/nouveau/fb: protect comptags with private mutex

nvkm_subdev.mutex is going away.
Signed-off-by: default avatarBen Skeggs <bskeggs@redhat.com>
Reviewed-by: default avatarLyude Paul <lyude@redhat.com>
parent 71ccf2a0
...@@ -36,7 +36,11 @@ struct nvkm_fb { ...@@ -36,7 +36,11 @@ struct nvkm_fb {
struct nvkm_blob vpr_scrubber; struct nvkm_blob vpr_scrubber;
struct nvkm_ram *ram; struct nvkm_ram *ram;
struct nvkm_mm tags;
struct {
struct mutex mutex; /* protects mm and nvkm_memory::tags */
struct nvkm_mm mm;
} tags;
struct { struct {
struct nvkm_fb_tile region[16]; struct nvkm_fb_tile region[16];
......
...@@ -33,13 +33,13 @@ nvkm_memory_tags_put(struct nvkm_memory *memory, struct nvkm_device *device, ...@@ -33,13 +33,13 @@ nvkm_memory_tags_put(struct nvkm_memory *memory, struct nvkm_device *device,
struct nvkm_fb *fb = device->fb; struct nvkm_fb *fb = device->fb;
struct nvkm_tags *tags = *ptags; struct nvkm_tags *tags = *ptags;
if (tags) { if (tags) {
mutex_lock(&fb->subdev.mutex); mutex_lock(&fb->tags.mutex);
if (refcount_dec_and_test(&tags->refcount)) { if (refcount_dec_and_test(&tags->refcount)) {
nvkm_mm_free(&fb->tags, &tags->mn); nvkm_mm_free(&fb->tags.mm, &tags->mn);
kfree(memory->tags); kfree(memory->tags);
memory->tags = NULL; memory->tags = NULL;
} }
mutex_unlock(&fb->subdev.mutex); mutex_unlock(&fb->tags.mutex);
*ptags = NULL; *ptags = NULL;
} }
} }
...@@ -52,29 +52,29 @@ nvkm_memory_tags_get(struct nvkm_memory *memory, struct nvkm_device *device, ...@@ -52,29 +52,29 @@ nvkm_memory_tags_get(struct nvkm_memory *memory, struct nvkm_device *device,
struct nvkm_fb *fb = device->fb; struct nvkm_fb *fb = device->fb;
struct nvkm_tags *tags; struct nvkm_tags *tags;
mutex_lock(&fb->subdev.mutex); mutex_lock(&fb->tags.mutex);
if ((tags = memory->tags)) { if ((tags = memory->tags)) {
/* If comptags exist for the memory, but a different amount /* If comptags exist for the memory, but a different amount
* than requested, the buffer is being mapped with settings * than requested, the buffer is being mapped with settings
* that are incompatible with existing mappings. * that are incompatible with existing mappings.
*/ */
if (tags->mn && tags->mn->length != nr) { if (tags->mn && tags->mn->length != nr) {
mutex_unlock(&fb->subdev.mutex); mutex_unlock(&fb->tags.mutex);
return -EINVAL; return -EINVAL;
} }
refcount_inc(&tags->refcount); refcount_inc(&tags->refcount);
mutex_unlock(&fb->subdev.mutex); mutex_unlock(&fb->tags.mutex);
*ptags = tags; *ptags = tags;
return 0; return 0;
} }
if (!(tags = kmalloc(sizeof(*tags), GFP_KERNEL))) { if (!(tags = kmalloc(sizeof(*tags), GFP_KERNEL))) {
mutex_unlock(&fb->subdev.mutex); mutex_unlock(&fb->tags.mutex);
return -ENOMEM; return -ENOMEM;
} }
if (!nvkm_mm_head(&fb->tags, 0, 1, nr, nr, 1, &tags->mn)) { if (!nvkm_mm_head(&fb->tags.mm, 0, 1, nr, nr, 1, &tags->mn)) {
if (clr) if (clr)
clr(device, tags->mn->offset, tags->mn->length); clr(device, tags->mn->offset, tags->mn->length);
} else { } else {
...@@ -92,7 +92,7 @@ nvkm_memory_tags_get(struct nvkm_memory *memory, struct nvkm_device *device, ...@@ -92,7 +92,7 @@ nvkm_memory_tags_get(struct nvkm_memory *memory, struct nvkm_device *device,
refcount_set(&tags->refcount, 1); refcount_set(&tags->refcount, 1);
*ptags = memory->tags = tags; *ptags = memory->tags = tags;
mutex_unlock(&fb->subdev.mutex); mutex_unlock(&fb->tags.mutex);
return 0; return 0;
} }
......
...@@ -122,7 +122,7 @@ nvkm_fb_oneinit(struct nvkm_subdev *subdev) ...@@ -122,7 +122,7 @@ nvkm_fb_oneinit(struct nvkm_subdev *subdev)
nvkm_debug(subdev, "%d comptags\n", tags); nvkm_debug(subdev, "%d comptags\n", tags);
} }
return nvkm_mm_init(&fb->tags, 0, 0, tags, 1); return nvkm_mm_init(&fb->tags.mm, 0, 0, tags, 1);
} }
static int static int
...@@ -205,7 +205,9 @@ nvkm_fb_dtor(struct nvkm_subdev *subdev) ...@@ -205,7 +205,9 @@ nvkm_fb_dtor(struct nvkm_subdev *subdev)
for (i = 0; i < fb->tile.regions; i++) for (i = 0; i < fb->tile.regions; i++)
fb->func->tile.fini(fb, i, &fb->tile.region[i]); fb->func->tile.fini(fb, i, &fb->tile.region[i]);
nvkm_mm_fini(&fb->tags); nvkm_mm_fini(&fb->tags.mm);
mutex_destroy(&fb->tags.mutex);
nvkm_ram_del(&fb->ram); nvkm_ram_del(&fb->ram);
nvkm_blob_dtor(&fb->vpr_scrubber); nvkm_blob_dtor(&fb->vpr_scrubber);
...@@ -230,8 +232,8 @@ nvkm_fb_ctor(const struct nvkm_fb_func *func, struct nvkm_device *device, ...@@ -230,8 +232,8 @@ nvkm_fb_ctor(const struct nvkm_fb_func *func, struct nvkm_device *device,
nvkm_subdev_ctor(&nvkm_fb, device, index, &fb->subdev); nvkm_subdev_ctor(&nvkm_fb, device, index, &fb->subdev);
fb->func = func; fb->func = func;
fb->tile.regions = fb->func->tile.regions; fb->tile.regions = fb->func->tile.regions;
fb->page = nvkm_longopt(device->cfgopt, "NvFbBigPage", fb->page = nvkm_longopt(device->cfgopt, "NvFbBigPage", fb->func->default_bigpage);
fb->func->default_bigpage); mutex_init(&fb->tags.mutex);
} }
int int
......
...@@ -45,7 +45,7 @@ nv20_fb_tile_comp(struct nvkm_fb *fb, int i, u32 size, u32 flags, ...@@ -45,7 +45,7 @@ nv20_fb_tile_comp(struct nvkm_fb *fb, int i, u32 size, u32 flags,
{ {
u32 tiles = DIV_ROUND_UP(size, 0x40); u32 tiles = DIV_ROUND_UP(size, 0x40);
u32 tags = round_up(tiles / fb->ram->parts, 0x40); u32 tags = round_up(tiles / fb->ram->parts, 0x40);
if (!nvkm_mm_head(&fb->tags, 0, 1, tags, tags, 1, &tile->tag)) { if (!nvkm_mm_head(&fb->tags.mm, 0, 1, tags, tags, 1, &tile->tag)) {
if (!(flags & 2)) tile->zcomp = 0x00000000; /* Z16 */ if (!(flags & 2)) tile->zcomp = 0x00000000; /* Z16 */
else tile->zcomp = 0x04000000; /* Z24S8 */ else tile->zcomp = 0x04000000; /* Z24S8 */
tile->zcomp |= tile->tag->offset; tile->zcomp |= tile->tag->offset;
...@@ -63,7 +63,7 @@ nv20_fb_tile_fini(struct nvkm_fb *fb, int i, struct nvkm_fb_tile *tile) ...@@ -63,7 +63,7 @@ nv20_fb_tile_fini(struct nvkm_fb *fb, int i, struct nvkm_fb_tile *tile)
tile->limit = 0; tile->limit = 0;
tile->pitch = 0; tile->pitch = 0;
tile->zcomp = 0; tile->zcomp = 0;
nvkm_mm_free(&fb->tags, &tile->tag); nvkm_mm_free(&fb->tags.mm, &tile->tag);
} }
void void
......
...@@ -32,7 +32,7 @@ nv25_fb_tile_comp(struct nvkm_fb *fb, int i, u32 size, u32 flags, ...@@ -32,7 +32,7 @@ nv25_fb_tile_comp(struct nvkm_fb *fb, int i, u32 size, u32 flags,
{ {
u32 tiles = DIV_ROUND_UP(size, 0x40); u32 tiles = DIV_ROUND_UP(size, 0x40);
u32 tags = round_up(tiles / fb->ram->parts, 0x40); u32 tags = round_up(tiles / fb->ram->parts, 0x40);
if (!nvkm_mm_head(&fb->tags, 0, 1, tags, tags, 1, &tile->tag)) { if (!nvkm_mm_head(&fb->tags.mm, 0, 1, tags, tags, 1, &tile->tag)) {
if (!(flags & 2)) tile->zcomp = 0x00100000; /* Z16 */ if (!(flags & 2)) tile->zcomp = 0x00100000; /* Z16 */
else tile->zcomp = 0x00200000; /* Z24S8 */ else tile->zcomp = 0x00200000; /* Z24S8 */
tile->zcomp |= tile->tag->offset; tile->zcomp |= tile->tag->offset;
......
...@@ -51,7 +51,7 @@ nv30_fb_tile_comp(struct nvkm_fb *fb, int i, u32 size, u32 flags, ...@@ -51,7 +51,7 @@ nv30_fb_tile_comp(struct nvkm_fb *fb, int i, u32 size, u32 flags,
{ {
u32 tiles = DIV_ROUND_UP(size, 0x40); u32 tiles = DIV_ROUND_UP(size, 0x40);
u32 tags = round_up(tiles / fb->ram->parts, 0x40); u32 tags = round_up(tiles / fb->ram->parts, 0x40);
if (!nvkm_mm_head(&fb->tags, 0, 1, tags, tags, 1, &tile->tag)) { if (!nvkm_mm_head(&fb->tags.mm, 0, 1, tags, tags, 1, &tile->tag)) {
if (flags & 2) tile->zcomp |= 0x01000000; /* Z16 */ if (flags & 2) tile->zcomp |= 0x01000000; /* Z16 */
else tile->zcomp |= 0x02000000; /* Z24S8 */ else tile->zcomp |= 0x02000000; /* Z24S8 */
tile->zcomp |= ((tile->tag->offset ) >> 6); tile->zcomp |= ((tile->tag->offset ) >> 6);
......
...@@ -32,7 +32,7 @@ nv35_fb_tile_comp(struct nvkm_fb *fb, int i, u32 size, u32 flags, ...@@ -32,7 +32,7 @@ nv35_fb_tile_comp(struct nvkm_fb *fb, int i, u32 size, u32 flags,
{ {
u32 tiles = DIV_ROUND_UP(size, 0x40); u32 tiles = DIV_ROUND_UP(size, 0x40);
u32 tags = round_up(tiles / fb->ram->parts, 0x40); u32 tags = round_up(tiles / fb->ram->parts, 0x40);
if (!nvkm_mm_head(&fb->tags, 0, 1, tags, tags, 1, &tile->tag)) { if (!nvkm_mm_head(&fb->tags.mm, 0, 1, tags, tags, 1, &tile->tag)) {
if (flags & 2) tile->zcomp |= 0x04000000; /* Z16 */ if (flags & 2) tile->zcomp |= 0x04000000; /* Z16 */
else tile->zcomp |= 0x08000000; /* Z24S8 */ else tile->zcomp |= 0x08000000; /* Z24S8 */
tile->zcomp |= ((tile->tag->offset ) >> 6); tile->zcomp |= ((tile->tag->offset ) >> 6);
......
...@@ -32,7 +32,7 @@ nv36_fb_tile_comp(struct nvkm_fb *fb, int i, u32 size, u32 flags, ...@@ -32,7 +32,7 @@ nv36_fb_tile_comp(struct nvkm_fb *fb, int i, u32 size, u32 flags,
{ {
u32 tiles = DIV_ROUND_UP(size, 0x40); u32 tiles = DIV_ROUND_UP(size, 0x40);
u32 tags = round_up(tiles / fb->ram->parts, 0x40); u32 tags = round_up(tiles / fb->ram->parts, 0x40);
if (!nvkm_mm_head(&fb->tags, 0, 1, tags, tags, 1, &tile->tag)) { if (!nvkm_mm_head(&fb->tags.mm, 0, 1, tags, tags, 1, &tile->tag)) {
if (flags & 2) tile->zcomp |= 0x10000000; /* Z16 */ if (flags & 2) tile->zcomp |= 0x10000000; /* Z16 */
else tile->zcomp |= 0x20000000; /* Z24S8 */ else tile->zcomp |= 0x20000000; /* Z24S8 */
tile->zcomp |= ((tile->tag->offset ) >> 6); tile->zcomp |= ((tile->tag->offset ) >> 6);
......
...@@ -33,7 +33,7 @@ nv40_fb_tile_comp(struct nvkm_fb *fb, int i, u32 size, u32 flags, ...@@ -33,7 +33,7 @@ nv40_fb_tile_comp(struct nvkm_fb *fb, int i, u32 size, u32 flags,
u32 tiles = DIV_ROUND_UP(size, 0x80); u32 tiles = DIV_ROUND_UP(size, 0x80);
u32 tags = round_up(tiles / fb->ram->parts, 0x100); u32 tags = round_up(tiles / fb->ram->parts, 0x100);
if ( (flags & 2) && if ( (flags & 2) &&
!nvkm_mm_head(&fb->tags, 0, 1, tags, tags, 1, &tile->tag)) { !nvkm_mm_head(&fb->tags.mm, 0, 1, tags, tags, 1, &tile->tag)) {
tile->zcomp = 0x28000000; /* Z24S8_SPLIT_GRAD */ tile->zcomp = 0x28000000; /* Z24S8_SPLIT_GRAD */
tile->zcomp |= ((tile->tag->offset ) >> 8); tile->zcomp |= ((tile->tag->offset ) >> 8);
tile->zcomp |= ((tile->tag->offset + tags - 1) >> 8) << 13; tile->zcomp |= ((tile->tag->offset + tags - 1) >> 8) << 13;
......
...@@ -200,8 +200,8 @@ gf100_ltc_oneinit_tag_ram(struct nvkm_ltc *ltc) ...@@ -200,8 +200,8 @@ gf100_ltc_oneinit_tag_ram(struct nvkm_ltc *ltc)
} }
mm_init: mm_init:
nvkm_mm_fini(&fb->tags); nvkm_mm_fini(&fb->tags.mm);
return nvkm_mm_init(&fb->tags, 0, 0, ltc->num_tags, 1); return nvkm_mm_init(&fb->tags.mm, 0, 0, ltc->num_tags, 1);
} }
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