From 62d1f5d2f5b3e5122eeac0f763dcdd1d04bf5c45 Mon Sep 17 00:00:00 2001 From: Alexandre Courbot Date: Wed, 16 Jul 2014 17:42:06 +0900 Subject: Experiments with large pages --- drm/nouveau_sgdma.c | 1 + drm/nouveau_ttm.c | 3 ++- nvkm/subdev/fb/ramgk20a.c | 22 +++++++++++++++++----- nvkm/subdev/vm/base.c | 16 +++++++++++++--- 4 files changed, 33 insertions(+), 9 deletions(-) diff --git a/drm/nouveau_sgdma.c b/drm/nouveau_sgdma.c index 01707e7de..3274eda02 100644 --- a/drm/nouveau_sgdma.c +++ b/drm/nouveau_sgdma.c @@ -38,6 +38,7 @@ nv04_sgdma_bind(struct ttm_tt *ttm, struct ttm_mem_reg *mem) node->pages = nvbe->ttm.dma_address; } node->size = (mem->num_pages << PAGE_SHIFT) >> 12; + node->page_shift = PAGE_SHIFT; nouveau_vm_map(&node->vma[0], node); nvbe->node = node; diff --git a/drm/nouveau_ttm.c b/drm/nouveau_ttm.c index 53874b76b..2298c7b08 100644 --- a/drm/nouveau_ttm.c +++ b/drm/nouveau_ttm.c @@ -93,7 +93,8 @@ nouveau_vram_manager_new(struct ttm_mem_type_manager *man, return (ret == -ENOSPC) ? 0 : ret; } - node->page_shift = nvbo->page_shift; + if (!node->page_shift) + node->page_shift = nvbo->page_shift; mem->mm_node = node; mem->start = node->offset >> PAGE_SHIFT; diff --git a/nvkm/subdev/fb/ramgk20a.c b/nvkm/subdev/fb/ramgk20a.c index 06dfdeced..873b1ebfd 100644 --- a/nvkm/subdev/fb/ramgk20a.c +++ b/nvkm/subdev/fb/ramgk20a.c @@ -53,8 +53,8 @@ gk20a_ram_get(struct nouveau_fb *pfb, u64 size, u32 align, u32 ncmin, u32 npages, order; int i; - nv_debug(pfb, "%s: size: %llx align: %x, ncmin: %x\n", __func__, size, - align, ncmin); + nv_debug(pfb, "%s: size: 0x%llx align: 0x%x, ncmin: 0x%x\n", __func__, + size, align, ncmin); npages = size >> PAGE_SHIFT; if (npages == 0) @@ -73,14 +73,26 @@ gk20a_ram_get(struct nouveau_fb *pfb, u64 size, u32 align, u32 ncmin, /* ensure returned address is correctly aligned */ npages = max(align, npages); + /* use big pages if we can, since our memory is always contiguous */ + if (ncmin == 0 && npages % 0x20 == 0) + ncmin = 0x20000; + else if (ncmin == 0) + ncmin = 0x1000; + ncmin >>= PAGE_SHIFT; + + /* ensure size is a multiple of ncmin */ + npages = roundup(npages, ncmin); + mem = kzalloc(sizeof(*mem), GFP_KERNEL); if (!mem) return -ENOMEM; mem->base.size = npages; mem->base.memtype = type; + mem->base.page_shift = fls(ncmin << PAGE_SHIFT) - 1; - mem->base.pages = kzalloc(sizeof(dma_addr_t) * npages, GFP_KERNEL); + mem->base.pages = kzalloc(sizeof(dma_addr_t) * npages / ncmin, + GFP_KERNEL); if (!mem->base.pages) { kfree(mem); return -ENOMEM; @@ -106,8 +118,8 @@ gk20a_ram_get(struct nouveau_fb *pfb, u64 size, u32 align, u32 ncmin, nv_debug(pfb, "alloc size: 0x%x, align: 0x%x, paddr: %pad, vaddr: %p\n", npages << PAGE_SHIFT, align, &mem->handle, mem->cpuaddr); - for (i = 0; i < npages; i++) - mem->base.pages[i] = mem->handle + (PAGE_SIZE * i); + for (i = 0; i < npages / ncmin; i++) + mem->base.pages[i] = mem->handle + (PAGE_SIZE * i * ncmin); mem->base.offset = (u64)mem->base.pages[0]; diff --git a/nvkm/subdev/vm/base.c b/nvkm/subdev/vm/base.c index f75a683bd..d4a758013 100644 --- a/nvkm/subdev/vm/base.c +++ b/nvkm/subdev/vm/base.c @@ -136,16 +136,26 @@ nouveau_vm_map_sg(struct nouveau_vma *vma, u64 delta, u64 length, { struct nouveau_vm *vm = vma->vm; struct nouveau_vmmgr *vmm = vm->vmm; + /* these pages are always PAGE_SIZE (should be mem->page_shift) sized */ dma_addr_t *list = mem->pages; - int big = vma->node->type != vmm->spg_shift; + /* whether the VMA type matches the small page type or not */ + /* if not, it should always match the big page type */ + int big = mem->page_shift != vmm->spg_shift; + /* first VMA page to map */ u32 offset = vma->node->offset + (delta >> 12); - u32 bits = vma->node->type - 12; - u32 num = length >> vma->node->type; + /* difference between size of node pages and small pages of VMM */ + u32 bits = mem->page_shift - vmm->spg_shift; + /* number of VMA pages to map */ + u32 num = length >> mem->page_shift; + /* first pde */ u32 pde = (offset >> vmm->pgt_bits) - vm->fpde; + /* first pte */ u32 pte = (offset & ((1 << vmm->pgt_bits) - 1)) >> bits; + /* last pte before switching to the next pde */ u32 max = 1 << (vmm->pgt_bits - bits); u32 end, len; + //printk("%s %d %d %d\n", __func__, big, vma->node->type, mem->page_shift); while (num) { struct nouveau_gpuobj *pgt = vm->pgt[pde].obj[big]; -- cgit v1.2.1