diff options
author | Ben Skeggs <bskeggs@redhat.com> | 2013-07-29 21:47:47 -0400 |
---|---|---|
committer | Ben Skeggs <bskeggs@redhat.com> | 2013-07-30 02:42:29 -0400 |
commit | e0bacd2f7e0abf7fd26ab7d12e1cfb96a5350fad (patch) | |
tree | 3278d14905515cef206c3ff945d83c5346c62dd1 | |
parent | dc409df9447a4e3884d150e2b0dbd89242403fa6 (diff) |
drm/nouveau/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>
-rw-r--r-- | drivers/gpu/drm/nouveau/core/include/subdev/vm.h | 2 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/core/subdev/vm/base.c | 27 |
2 files changed, 11 insertions, 18 deletions
diff --git a/drivers/gpu/drm/nouveau/core/include/subdev/vm.h b/drivers/gpu/drm/nouveau/core/include/subdev/vm.h index f2e87b105666..fcf57fa309bf 100644 --- a/drivers/gpu/drm/nouveau/core/include/subdev/vm.h +++ b/drivers/gpu/drm/nouveau/core/include/subdev/vm.h | |||
@@ -55,7 +55,7 @@ struct nouveau_vma { | |||
55 | struct nouveau_vm { | 55 | struct nouveau_vm { |
56 | struct nouveau_vmmgr *vmm; | 56 | struct nouveau_vmmgr *vmm; |
57 | struct nouveau_mm mm; | 57 | struct nouveau_mm mm; |
58 | int refcount; | 58 | struct kref refcount; |
59 | 59 | ||
60 | struct list_head pgd_list; | 60 | struct list_head pgd_list; |
61 | atomic_t engref[NVDEV_SUBDEV_NR]; | 61 | atomic_t engref[NVDEV_SUBDEV_NR]; |
diff --git a/drivers/gpu/drm/nouveau/core/subdev/vm/base.c b/drivers/gpu/drm/nouveau/core/subdev/vm/base.c index 67fcb6c852ac..ef3133e7575c 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/vm/base.c +++ b/drivers/gpu/drm/nouveau/core/subdev/vm/base.c | |||
@@ -361,7 +361,7 @@ nouveau_vm_create(struct nouveau_vmmgr *vmm, u64 offset, u64 length, | |||
361 | 361 | ||
362 | INIT_LIST_HEAD(&vm->pgd_list); | 362 | INIT_LIST_HEAD(&vm->pgd_list); |
363 | vm->vmm = vmm; | 363 | vm->vmm = vmm; |
364 | vm->refcount = 1; | 364 | kref_init(&vm->refcount); |
365 | vm->fpde = offset >> (vmm->pgt_bits + 12); | 365 | vm->fpde = offset >> (vmm->pgt_bits + 12); |
366 | vm->lpde = (offset + length - 1) >> (vmm->pgt_bits + 12); | 366 | vm->lpde = (offset + length - 1) >> (vmm->pgt_bits + 12); |
367 | 367 | ||
@@ -441,8 +441,9 @@ nouveau_vm_unlink(struct nouveau_vm *vm, struct nouveau_gpuobj *mpgd) | |||
441 | } | 441 | } |
442 | 442 | ||
443 | static void | 443 | static void |
444 | nouveau_vm_del(struct nouveau_vm *vm) | 444 | nouveau_vm_del(struct kref *kref) |
445 | { | 445 | { |
446 | struct nouveau_vm *vm = container_of(kref, typeof(*vm), refcount); | ||
446 | struct nouveau_vm_pgd *vpgd, *tmp; | 447 | struct nouveau_vm_pgd *vpgd, *tmp; |
447 | 448 | ||
448 | list_for_each_entry_safe(vpgd, tmp, &vm->pgd_list, head) { | 449 | list_for_each_entry_safe(vpgd, tmp, &vm->pgd_list, head) { |
@@ -458,27 +459,19 @@ int | |||
458 | nouveau_vm_ref(struct nouveau_vm *ref, struct nouveau_vm **ptr, | 459 | nouveau_vm_ref(struct nouveau_vm *ref, struct nouveau_vm **ptr, |
459 | struct nouveau_gpuobj *pgd) | 460 | struct nouveau_gpuobj *pgd) |
460 | { | 461 | { |
461 | struct nouveau_vm *vm; | 462 | if (ref) { |
462 | int ret; | 463 | int ret = nouveau_vm_link(ref, pgd); |
463 | |||
464 | vm = ref; | ||
465 | if (vm) { | ||
466 | ret = nouveau_vm_link(vm, pgd); | ||
467 | if (ret) | 464 | if (ret) |
468 | return ret; | 465 | return ret; |
469 | 466 | ||
470 | vm->refcount++; | 467 | kref_get(&ref->refcount); |
471 | } | 468 | } |
472 | 469 | ||
473 | vm = *ptr; | 470 | if (*ptr) { |
474 | *ptr = ref; | 471 | nouveau_vm_unlink(*ptr, pgd); |
475 | 472 | kref_put(&(*ptr)->refcount, nouveau_vm_del); | |
476 | if (vm) { | ||
477 | nouveau_vm_unlink(vm, pgd); | ||
478 | |||
479 | if (--vm->refcount == 0) | ||
480 | nouveau_vm_del(vm); | ||
481 | } | 473 | } |
482 | 474 | ||
475 | *ptr = ref; | ||
483 | return 0; | 476 | return 0; |
484 | } | 477 | } |