summaryrefslogtreecommitdiff
path: root/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ram.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm/nouveau/nvkm/subdev/fb/ram.c')
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/fb/ram.c54
1 files changed, 49 insertions, 5 deletions
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ram.c b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ram.c
index 03b1bdb27770..c826980bf70e 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ram.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ram.c
@@ -25,6 +25,7 @@
#include "ram.h"
#include <core/memory.h>
+#include <subdev/instmem.h>
#include <subdev/mmu.h>
struct nvkm_vram {
@@ -35,6 +36,12 @@ struct nvkm_vram {
};
static int
+nvkm_vram_kmap(struct nvkm_memory *memory, struct nvkm_memory **pmemory)
+{
+ return nvkm_instobj_wrap(nvkm_vram(memory)->ram->fb->subdev.device, memory, pmemory);
+}
+
+static int
nvkm_vram_map(struct nvkm_memory *memory, u64 offset, struct nvkm_vmm *vmm,
struct nvkm_vma *vma, void *argv, u32 argc)
{
@@ -81,12 +88,20 @@ nvkm_vram_dtor(struct nvkm_memory *memory)
struct nvkm_vram *vram = nvkm_vram(memory);
struct nvkm_mm_node *next = vram->mn;
struct nvkm_mm_node *node;
- mutex_lock(&vram->ram->mutex);
- while ((node = next)) {
- next = node->next;
- nvkm_mm_free(&vram->ram->vram, &node);
+
+ if (next) {
+ if (likely(next->nl_entry.next)){
+ mutex_lock(&vram->ram->mutex);
+ while ((node = next)) {
+ next = node->next;
+ nvkm_mm_free(&vram->ram->vram, &node);
+ }
+ mutex_unlock(&vram->ram->mutex);
+ } else {
+ kfree(vram->mn);
+ }
}
- mutex_unlock(&vram->ram->mutex);
+
return vram;
}
@@ -98,9 +113,38 @@ nvkm_vram = {
.addr = nvkm_vram_addr,
.size = nvkm_vram_size,
.map = nvkm_vram_map,
+ .kmap = nvkm_vram_kmap,
};
int
+nvkm_ram_wrap(struct nvkm_device *device, u64 addr, u64 size,
+ struct nvkm_memory **pmemory)
+{
+ struct nvkm_ram *ram;
+ struct nvkm_vram *vram;
+
+ if (!device->fb || !(ram = device->fb->ram))
+ return -ENODEV;
+ ram = device->fb->ram;
+
+ if (!(vram = kzalloc(sizeof(*vram), GFP_KERNEL)))
+ return -ENOMEM;
+
+ nvkm_memory_ctor(&nvkm_vram, &vram->memory);
+ vram->ram = ram;
+ vram->page = NVKM_RAM_MM_SHIFT;
+ *pmemory = &vram->memory;
+
+ vram->mn = kzalloc(sizeof(*vram->mn), GFP_KERNEL);
+ if (!vram->mn)
+ return -ENOMEM;
+
+ vram->mn->offset = addr >> NVKM_RAM_MM_SHIFT;
+ vram->mn->length = size >> NVKM_RAM_MM_SHIFT;
+ return 0;
+}
+
+int
nvkm_ram_get(struct nvkm_device *device, u8 heap, u8 type, u8 rpage, u64 size,
bool contig, bool back, struct nvkm_memory **pmemory)
{