Commit 4c4101d2 authored by Marcin Slusarz's avatar Marcin Slusarz Committed by Ben Skeggs

drm/nouveau: add locking around instobj list operations

Fixes memory corruptions, oopses, etc. when multiple gpuobjs are
simultaneously created or destroyed.
Signed-off-by: default avatarMarcin Slusarz <marcin.slusarz@gmail.com>
Signed-off-by: default avatarBen Skeggs <bskeggs@redhat.com>
Cc: stable@vger.kernel.org
parent 1a1841d3
......@@ -40,15 +40,21 @@ nouveau_instobj_create_(struct nouveau_object *parent,
if (ret)
return ret;
mutex_lock(&imem->base.mutex);
list_add(&iobj->head, &imem->list);
mutex_unlock(&imem->base.mutex);
return 0;
}
void
nouveau_instobj_destroy(struct nouveau_instobj *iobj)
{
if (iobj->head.prev)
struct nouveau_subdev *subdev = nv_subdev(iobj->base.engine);
mutex_lock(&subdev->mutex);
list_del(&iobj->head);
mutex_unlock(&subdev->mutex);
return nouveau_object_destroy(&iobj->base);
}
......@@ -88,6 +94,8 @@ nouveau_instmem_init(struct nouveau_instmem *imem)
if (ret)
return ret;
mutex_lock(&imem->base.mutex);
list_for_each_entry(iobj, &imem->list, head) {
if (iobj->suspend) {
for (i = 0; i < iobj->size; i += 4)
......@@ -97,6 +105,8 @@ nouveau_instmem_init(struct nouveau_instmem *imem)
}
}
mutex_unlock(&imem->base.mutex);
return 0;
}
......@@ -104,17 +114,26 @@ int
nouveau_instmem_fini(struct nouveau_instmem *imem, bool suspend)
{
struct nouveau_instobj *iobj;
int i;
int i, ret = 0;
if (suspend) {
mutex_lock(&imem->base.mutex);
list_for_each_entry(iobj, &imem->list, head) {
iobj->suspend = vmalloc(iobj->size);
if (iobj->suspend) {
if (!iobj->suspend) {
ret = -ENOMEM;
break;
}
for (i = 0; i < iobj->size; i += 4)
iobj->suspend[i / 4] = nv_ro32(iobj, i);
} else
return -ENOMEM;
}
mutex_unlock(&imem->base.mutex);
if (ret)
return ret;
}
return nouveau_subdev_fini(&imem->base, suspend);
......
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