From 063d7ebf17304fe8a7b85ecb4662f20c4839b6af Mon Sep 17 00:00:00 2001
From: Qiang Yu <yuq825@gmail.com>
Date: Wed, 30 May 2018 19:18:03 +0800
Subject: [PATCH 069/146] drm/lima: vm alloc buffer with multi page table

Signed-off-by: Qiang Yu <yuq825@gmail.com>
---
 drivers/gpu/drm/lima/lima_vm.c | 95 ++++++++++++++++++++++------------
 drivers/gpu/drm/lima/lima_vm.h |  6 ++-
 2 files changed, 66 insertions(+), 35 deletions(-)

diff --git a/drivers/gpu/drm/lima/lima_vm.c b/drivers/gpu/drm/lima/lima_vm.c
index 19a683c2921b..ab7438685234 100644
--- a/drivers/gpu/drm/lima/lima_vm.c
+++ b/drivers/gpu/drm/lima/lima_vm.c
@@ -28,8 +28,18 @@ struct lima_bo_va {
 	struct lima_vm *vm;
 };
 
-#define LIMA_PDE(va) (va >> 22)
-#define LIMA_PTE(va) ((va & 0x3FFFFF) >> 12)
+#define LIMA_VM_PD_SHIFT 22
+#define LIMA_VM_PT_SHIFT 12
+#define LIMA_VM_PB_SHIFT (LIMA_VM_PD_SHIFT + LIMA_VM_NUM_PT_PER_BT_SHIFT)
+#define LIMA_VM_BT_SHIFT LIMA_VM_PT_SHIFT
+
+#define LIMA_VM_PT_MASK ((1 << LIMA_VM_PD_SHIFT) - 1)
+#define LIMA_VM_BT_MASK ((1 << LIMA_VM_PB_SHIFT) - 1)
+
+#define LIMA_PDE(va) (va >> LIMA_VM_PD_SHIFT)
+#define LIMA_PTE(va) ((va & LIMA_VM_PT_MASK) >> LIMA_VM_PT_SHIFT)
+#define LIMA_PBE(va) (va >> LIMA_VM_PB_SHIFT)
+#define LIMA_BTE(va) ((va & LIMA_VM_BT_MASK) >> LIMA_VM_BT_SHIFT)
 
 #define START(node) ((node)->start)
 #define LAST(node) ((node)->last)
@@ -45,12 +55,12 @@ static void lima_vm_unmap_page_table(struct lima_vm *vm, u32 start, u32 end)
 	u32 addr;
 
 	for (addr = start; addr <= end; addr += LIMA_PAGE_SIZE) {
-		u32 pde = LIMA_PDE(addr);
-		u32 pte = LIMA_PTE(addr);
-		u32 *pt;
+		u32 pbe = LIMA_PBE(addr);
+		u32 bte = LIMA_BTE(addr);
+		u32 *bt;
 
-		pt = lima_bo_kmap(vm->pt[pde]);
-		pt[pte] = 0;
+		bt = lima_bo_kmap(vm->bts[pbe]);
+		bt[bte] = 0;
 	}
 }
 
@@ -61,32 +71,43 @@ static int lima_vm_map_page_table(struct lima_vm *vm, dma_addr_t *dma,
 	int err, i = 0;
 
 	for (addr = start; addr <= end; addr += LIMA_PAGE_SIZE) {
-		u32 pde = LIMA_PDE(addr);
-		u32 pte = LIMA_PTE(addr);
-		u32 *pd, *pt;
+		u32 pbe = LIMA_PBE(addr);
+		u32 bte = LIMA_BTE(addr);
+		u32 *bt;
 
-		if (vm->pt[pde])
-			pt = lima_bo_kmap(vm->pt[pde]);
+		if (vm->bts[pbe])
+			bt = lima_bo_kmap(vm->bts[pbe]);
 		else {
-			vm->pt[pde] = lima_bo_create(
-				vm->dev, LIMA_PAGE_SIZE, 0, ttm_bo_type_kernel,
+			struct lima_bo *bt_bo;
+			dma_addr_t *pts;
+			u32 *pd;
+			int j;
+
+			bt_bo = lima_bo_create(
+				vm->dev, LIMA_PAGE_SIZE << LIMA_VM_NUM_PT_PER_BT_SHIFT,
+				0, ttm_bo_type_kernel,
 				NULL, vm->pd->tbo.resv);
-			if (IS_ERR(vm->pt[pde])) {
-				err = PTR_ERR(vm->pt[pde]);
+			if (IS_ERR(bt_bo)) {
+				err = PTR_ERR(bt_bo);
 				goto err_out;
 			}
 
-			pt = lima_bo_kmap(vm->pt[pde]);
-			if (IS_ERR(pt)) {
-				err = PTR_ERR(pt);
+			bt = lima_bo_kmap(bt_bo);
+			if (IS_ERR(bt)) {
+				lima_bo_unref(bt_bo);
+				err = PTR_ERR(bt);
 				goto err_out;
 			}
 
+			vm->bts[pbe] = bt_bo;
 			pd = lima_bo_kmap(vm->pd);
-			pd[pde] = *lima_bo_get_pages(vm->pt[pde]) | LIMA_VM_FLAG_PRESENT;
+			pd += pbe << LIMA_VM_NUM_PT_PER_BT_SHIFT;
+			pts = lima_bo_get_pages(bt_bo);
+			for (j = 0; j < LIMA_VM_NUM_PT_PER_BT; j++)
+				*pd++ = *pts++ | LIMA_VM_FLAG_PRESENT;
 		}
 
-		pt[pte] = dma[i++] | LIMA_VM_FLAGS_CACHE;
+		bt[bte] = dma[i++] | LIMA_VM_FLAGS_CACHE;
 	}
 
 	return 0;
@@ -293,9 +314,9 @@ void lima_vm_release(struct kref *kref)
 		dev_err(dev->dev, "still active bo inside vm\n");
 	}
 
-	for (i = 0; i < LIMA_PAGE_ENT_NUM; i++) {
-		if (vm->pt[i])
-			lima_bo_unref(vm->pt[i]);
+	for (i = 0; i < LIMA_VM_NUM_BT; i++) {
+		if (vm->bts[i])
+			lima_bo_unref(vm->bts[i]);
 	}
 
 	if (vm->pd)
@@ -306,20 +327,26 @@ void lima_vm_release(struct kref *kref)
 
 void lima_vm_print(struct lima_vm *vm)
 {
-	int i, j;
-	u32 *pd = lima_bo_kmap(vm->pd);
+	int i, j, k;
+	u32 *pd, *pt;
 
 	/* to avoid the defined by not used warning */
 	(void)&lima_vm_it_iter_next;
 
-	for (i = 0; i < LIMA_PAGE_ENT_NUM; i++) {
-		if (pd[i]) {
-			u32 *pt = lima_bo_kmap(vm->pt[i]);
-
-			printk(KERN_INFO "lima vm pd %03x:%08x\n", i, pd[i]);
-			for (j = 0; j < LIMA_PAGE_ENT_NUM; j++) {
-				if (pt[j])
-					printk(KERN_INFO "  pt %03x:%08x\n", j, pt[j]);
+	pd = lima_bo_kmap(vm->pd);
+	for (i = 0; i < LIMA_VM_NUM_BT; i++) {
+		if (!vm->bts[i])
+			continue;
+
+		pt = lima_bo_kmap(vm->bts[i]);
+		for (j = 0; j < LIMA_VM_NUM_PT_PER_BT; j++) {
+			int idx = (i << LIMA_VM_NUM_PT_PER_BT_SHIFT) + j;
+			printk(KERN_INFO "lima vm pd %03x:%08x\n", idx, pd[idx]);
+
+			for (k = 0; k < LIMA_PAGE_ENT_NUM; k++) {
+				u32 pte = *pt++;
+				if (pte)
+					printk(KERN_INFO "  pt %03x:%08x\n", k, pte);
 			}
 		}
 	}
diff --git a/drivers/gpu/drm/lima/lima_vm.h b/drivers/gpu/drm/lima/lima_vm.h
index c891a1ee95df..598708ac0d31 100644
--- a/drivers/gpu/drm/lima/lima_vm.h
+++ b/drivers/gpu/drm/lima/lima_vm.h
@@ -12,6 +12,10 @@
 #define LIMA_PAGE_MASK    (LIMA_PAGE_SIZE - 1)
 #define LIMA_PAGE_ENT_NUM (LIMA_PAGE_SIZE / sizeof(u32))
 
+#define LIMA_VM_NUM_PT_PER_BT_SHIFT 3
+#define LIMA_VM_NUM_PT_PER_BT (1 << LIMA_VM_NUM_PT_PER_BT_SHIFT)
+#define LIMA_VM_NUM_BT (LIMA_PAGE_ENT_NUM >> LIMA_VM_NUM_PT_PER_BT_SHIFT)
+
 #define LIMA_VA_RESERVE_START  0xFFF00000
 #define LIMA_VA_RESERVE_DLBU   LIMA_VA_RESERVE_START
 #define LIMA_VA_RESERVE_END    0x100000000
@@ -28,7 +32,7 @@ struct lima_vm {
 	struct lima_device *dev;
 
 	struct lima_bo *pd;
-	struct lima_bo *pt[LIMA_PAGE_ENT_NUM];
+	struct lima_bo *bts[LIMA_VM_NUM_BT];
 };
 
 int lima_vm_bo_map(struct lima_vm *vm, struct lima_bo *bo, u32 start);
-- 
2.17.1