summaryrefslogtreecommitdiff
path: root/nvkm/subdev/vm/base.c
diff options
context:
space:
mode:
authorBen Skeggs <bskeggs@redhat.com>2013-07-30 11:47:47 +1000
committerBen Skeggs <bskeggs@redhat.com>2013-07-30 16:34:28 +1000
commit78207e8d0bfc7c14d8fa16de2758192828c726a5 (patch)
treea61d0deb3e5786af003cf3b1c957dcdc710e4c08 /nvkm/subdev/vm/base.c
parent3e7361211453ba7fbb54686fe7df234e1d8ca863 (diff)
downloadnouveau-78207e8d0bfc7c14d8fa16de2758192828c726a5.tar.gz
vm: make vm refcount into a kref
Never used to be required, but a recent change made it necessary. Reported-by: Maarten Lankhorst <maarten.lankhorst@canonical.com> Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
Diffstat (limited to 'nvkm/subdev/vm/base.c')
-rw-r--r--nvkm/subdev/vm/base.c27
1 files changed, 10 insertions, 17 deletions
diff --git a/nvkm/subdev/vm/base.c b/nvkm/subdev/vm/base.c
index 67fcb6c85..ef3133e75 100644
--- a/nvkm/subdev/vm/base.c
+++ b/nvkm/subdev/vm/base.c
@@ -361,7 +361,7 @@ nouveau_vm_create(struct nouveau_vmmgr *vmm, u64 offset, u64 length,
INIT_LIST_HEAD(&vm->pgd_list);
vm->vmm = vmm;
- vm->refcount = 1;
+ kref_init(&vm->refcount);
vm->fpde = offset >> (vmm->pgt_bits + 12);
vm->lpde = (offset + length - 1) >> (vmm->pgt_bits + 12);
@@ -441,8 +441,9 @@ nouveau_vm_unlink(struct nouveau_vm *vm, struct nouveau_gpuobj *mpgd)
}
static void
-nouveau_vm_del(struct nouveau_vm *vm)
+nouveau_vm_del(struct kref *kref)
{
+ struct nouveau_vm *vm = container_of(kref, typeof(*vm), refcount);
struct nouveau_vm_pgd *vpgd, *tmp;
list_for_each_entry_safe(vpgd, tmp, &vm->pgd_list, head) {
@@ -458,27 +459,19 @@ int
nouveau_vm_ref(struct nouveau_vm *ref, struct nouveau_vm **ptr,
struct nouveau_gpuobj *pgd)
{
- struct nouveau_vm *vm;
- int ret;
-
- vm = ref;
- if (vm) {
- ret = nouveau_vm_link(vm, pgd);
+ if (ref) {
+ int ret = nouveau_vm_link(ref, pgd);
if (ret)
return ret;
- vm->refcount++;
+ kref_get(&ref->refcount);
}
- vm = *ptr;
- *ptr = ref;
-
- if (vm) {
- nouveau_vm_unlink(vm, pgd);
-
- if (--vm->refcount == 0)
- nouveau_vm_del(vm);
+ if (*ptr) {
+ nouveau_vm_unlink(*ptr, pgd);
+ kref_put(&(*ptr)->refcount, nouveau_vm_del);
}
+ *ptr = ref;
return 0;
}