Re: [mipsel+rs780e]Occasionally "GPU lockup" after resuming from suspend.

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



在 2012年2月17日 下午5:27,Chen Jie <chenj@xxxxxxxxxx> 写道:
>> One good way to test gart is to go over GPU gart table and write a
>> dword using the GPU at end of each page something like 0xCAFEDEAD
>> or somevalue that is unlikely to be already set. And then go over
>> all the page and check that GPU write succeed. Abusing the scratch
>> register write back feature is the easiest way to try that.
> I'm planning to add a GART table check procedure when resume, which
> will go over GPU gart table:
> 1. read(backup) a dword at end of each GPU page
> 2. write a mark by GPU and check it
> 3. restore the original dword
Attachment validateGART.patch do the job:
* It current only works for mips64 platform.
* To use it, apply all_in_vram.patch first, which will allocate CP
ring, ih, ib in VRAM and hard code no_wb=1.

The gart test routine will be invoked in r600_resume. We've tried it,
and find that when lockup happened the gart table was good before
userspace restarting. The related dmesg follows:
[ 1521.820312] [drm] r600_gart_table_validate(): Validate GART Table
at 9000000040040000, 32768 entries, Dummy
Page[0x000000000e004000-0x000000000e007fff]
[ 1522.019531] [drm] r600_gart_table_validate(): Sweep 32768
entries(valid=8544, invalid=24224, total=32768).
...
[ 1531.156250] PM: resume of devices complete after 9396.588 msecs
[ 1532.152343] Restarting tasks ... done.
[ 1544.468750] radeon 0000:01:05.0: GPU lockup CP stall for more than 10003msec
[ 1544.472656] ------------[ cut here ]------------
[ 1544.480468] WARNING: at drivers/gpu/drm/radeon/radeon_fence.c:243
radeon_fence_wait+0x25c/0x314()
[ 1544.488281] GPU lockup (waiting for 0x0002136B last fence id 0x0002136A)
...
[ 1544.886718] radeon 0000:01:05.0: Wait for MC idle timedout !
[ 1545.046875] radeon 0000:01:05.0: Wait for MC idle timedout !
[ 1545.062500] radeon 0000:01:05.0: WB disabled
[ 1545.097656] [drm] ring test succeeded in 0 usecs
[ 1545.105468] [drm] ib test succeeded in 0 usecs
[ 1545.109375] [drm] Enabling audio support
[ 1545.113281] [drm] r600_gart_table_validate(): Validate GART Table
at 9000000040040000, 32768 entries, Dummy
Page[0x000000000e004000-0x000000000e007fff]
[ 1545.125000] [drm:r600_gart_table_validate] *ERROR* Iter=0:
unexpected value 0x745aaad1(expect 0xDEADBEEF)
entry=0x000000000e008067, orignal=0x745aaad1
...
/* System blocked here. */

Any idea?

BTW, we find the following in r600_pcie_gart_enable()
(drivers/gpu/drm/radeon/r600.c):
WREG32(VM_CONTEXT0_PROTECTION_FAULT_DEFAULT_ADDR,
(u32)(rdev->dummy_page.addr >> 12));

On our platform, PAGE_SIZE is 16K, does it have any problem?

Also in radeon_gart_unbind() and radeon_gart_restore(), the logic
should change to:
  for (j = 0; j < (PAGE_SIZE / RADEON_GPU_PAGE_SIZE); j++, t++) {
          radeon_gart_set_page(rdev, t, page_base);
-         page_base += RADEON_GPU_PAGE_SIZE;
+         if (page_base != rdev->dummy_page.addr)
+                 page_base += RADEON_GPU_PAGE_SIZE;
  }
???



Regards,
-- Chen Jie
diff --git a/drivers/gpu/drm/radeon/r600.c b/drivers/gpu/drm/radeon/r600.c
index 53dbf50..e5961ed 100644
--- a/drivers/gpu/drm/radeon/r600.c
+++ b/drivers/gpu/drm/radeon/r600.c
@@ -2215,6 +2218,8 @@ int r600_cp_resume(struct radeon_device *rdev)
 
 void r600_cp_commit(struct radeon_device *rdev)
 {
+	if ((rdev->cp.ring_obj->tbo.mem.placement &  TTM_PL_MASK_MEM) == TTM_PL_FLAG_VRAM)
+		WREG32(R_005480_HDP_MEM_COHERENCY_FLUSH_CNTL, 0x1);
 	WREG32(CP_RB_WPTR, rdev->cp.wptr);
 	(void)RREG32(CP_RB_WPTR);
 }
@@ -2754,7 +2764,7 @@ static int r600_ih_ring_alloc(struct radeon_device *rdev)
 	if (rdev->ih.ring_obj == NULL) {
 		r = radeon_bo_create(rdev, NULL, rdev->ih.ring_size,
 				     true,
-				     RADEON_GEM_DOMAIN_GTT,
+				     RADEON_GEM_DOMAIN_VRAM,
 				     &rdev->ih.ring_obj);
 		if (r) {
 			DRM_ERROR("radeon: failed to create ih ring buffer (%d).\n", r);
@@ -2764,7 +2774,7 @@ static int r600_ih_ring_alloc(struct radeon_device *rdev)
 		if (unlikely(r != 0))
 			return r;
 		r = radeon_bo_pin(rdev->ih.ring_obj,
-				  RADEON_GEM_DOMAIN_GTT,
+				  RADEON_GEM_DOMAIN_VRAM,
 				  &rdev->ih.gpu_addr);
 		if (r) {
 			radeon_bo_unreserve(rdev->ih.ring_obj);
@@ -3444,6 +3454,8 @@ restart_ih:
 	if (queue_hotplug)
 		queue_work(rdev->wq, &rdev->hotplug_work);
 	rdev->ih.rptr = rptr;
+	if ((rdev->ih.ring_obj->tbo.mem.placement &  TTM_PL_MASK_MEM) == TTM_PL_FLAG_VRAM)
+		WREG32(R_005480_HDP_MEM_COHERENCY_FLUSH_CNTL, 0x1);
 	WREG32(IH_RB_RPTR, rdev->ih.rptr);
 	spin_unlock_irqrestore(&rdev->ih.lock, flags);
 	return IRQ_HANDLED;
diff --git a/drivers/gpu/drm/radeon/radeon_drv.c b/drivers/gpu/drm/radeon/radeon_drv.c
index 795403b..c5326e0 100644
--- a/drivers/gpu/drm/radeon/radeon_drv.c
+++ b/drivers/gpu/drm/radeon/radeon_drv.c
@@ -82,13 +82,13 @@ void radeon_debugfs_cleanup(struct drm_minor *minor);
 #endif
 
 
-int radeon_no_wb;
+int radeon_no_wb = 1;
 int radeon_modeset = -1;
 int radeon_dynclks = -1;
 int radeon_r4xx_atom = 0;
 int radeon_agpmode = 0;
 int radeon_vram_limit = 0;
-int radeon_gart_size = 512; /* default gart size */
+int radeon_gart_size = 128; /* default gart size */
 int radeon_benchmarking = 0;
 int radeon_testing = 0;
 int radeon_connector_table = 0;
diff --git a/drivers/gpu/drm/radeon/radeon_ring.c b/drivers/gpu/drm/radeon/radeon_ring.c
index 6ea798c..608d2fe 100644
--- a/drivers/gpu/drm/radeon/radeon_ring.c
+++ b/drivers/gpu/drm/radeon/radeon_ring.c
@@ -176,7 +180,7 @@ int radeon_ib_pool_init(struct radeon_device *rdev)
 	INIT_LIST_HEAD(&rdev->ib_pool.bogus_ib);
 	/* Allocate 1M object buffer */
 	r = radeon_bo_create(rdev, NULL,  RADEON_IB_POOL_SIZE*64*1024,
-				true, RADEON_GEM_DOMAIN_GTT,
+				true, RADEON_GEM_DOMAIN_VRAM,
 				&rdev->ib_pool.robj);
 	if (r) {
 		DRM_ERROR("radeon: failed to ib pool (%d).\n", r);
@@ -185,7 +189,7 @@ int radeon_ib_pool_init(struct radeon_device *rdev)
 	r = radeon_bo_reserve(rdev->ib_pool.robj, false);
 	if (unlikely(r != 0))
 		return r;
-	r = radeon_bo_pin(rdev->ib_pool.robj, RADEON_GEM_DOMAIN_GTT, &gpu_addr);
+	r = radeon_bo_pin(rdev->ib_pool.robj, RADEON_GEM_DOMAIN_VRAM, &gpu_addr);
 	if (r) {
 		radeon_bo_unreserve(rdev->ib_pool.robj);
 		DRM_ERROR("radeon: failed to pin ib pool (%d).\n", r);
@@ -333,7 +337,7 @@ int radeon_ring_init(struct radeon_device *rdev, unsigned ring_size)
 	/* Allocate ring buffer */
 	if (rdev->cp.ring_obj == NULL) {
 		r = radeon_bo_create(rdev, NULL, rdev->cp.ring_size, true,
-					RADEON_GEM_DOMAIN_GTT,
+					RADEON_GEM_DOMAIN_VRAM,
 					&rdev->cp.ring_obj);
 		if (r) {
 			dev_err(rdev->dev, "(%d) ring create failed\n", r);
@@ -342,7 +346,7 @@ int radeon_ring_init(struct radeon_device *rdev, unsigned ring_size)
 		r = radeon_bo_reserve(rdev->cp.ring_obj, false);
 		if (unlikely(r != 0))
 			return r;
-		r = radeon_bo_pin(rdev->cp.ring_obj, RADEON_GEM_DOMAIN_GTT,
+		r = radeon_bo_pin(rdev->cp.ring_obj, RADEON_GEM_DOMAIN_VRAM,
 					&rdev->cp.gpu_addr);
 		if (r) {
 			radeon_bo_unreserve(rdev->cp.ring_obj);
 
diff --git a/drivers/gpu/drm/radeon/r600.c b/drivers/gpu/drm/radeon/r600.c
index fb45a3f..7d55085 100644
--- a/drivers/gpu/drm/radeon/r600.c
+++ b/drivers/gpu/drm/radeon/r600.c
@@ -2445,6 +2447,116 @@ void r600_vga_set_state(struct radeon_device *rdev, bool state)
 	WREG32(CONFIG_CNTL, temp);
 }
 
+int r600_gart_table_validate(struct radeon_device *rdev)
+{
+	int r, i, invalid_count, count, total_entries;
+	u64 dummy_page_start, dummy_page_end;
+	struct radeon_fence *fence = NULL;
+
+	invalid_count = count = 0;
+	total_entries = rdev->gart.table_size >> 3;
+
+	dummy_page_start = (u64) rdev->dummy_page.addr;
+	dummy_page_end = dummy_page_start + PAGE_SIZE - 1;
+
+	DRM_INFO("%s(): Validate GART Table at %p, %d entries, Dummy Page[0x%016llx-0x%016llx]\n",
+		 __func__, rdev->gart.table.vram.ptr, total_entries,
+		 dummy_page_start, dummy_page_end);
+
+	for (i = 0; i < total_entries; i++) {
+		void __iomem *ptr;
+
+		u64 entry_val;
+      		u64 bus_addr, paddr;
+		volatile void *vaddr;
+		u64 gpu_addr;
+		u32 backup, what_read;
+
+		ptr = ((void __iomem *) rdev->gart.table.vram.ptr) + i * 8;
+	       	entry_val = readq(ptr);	
+
+		bus_addr = entry_val & 0xFFFFFFFFFFFFF000ULL;
+
+		/* For loongson, PAGE_SIZE=16K */
+		if (bus_addr >= dummy_page_start && bus_addr <= dummy_page_end) {
+			if (bus_addr + RADEON_GPU_PAGE_SIZE - 1 > dummy_page_end)
+				DRM_ERROR("Iter=%d: dummy page intersects with normal page(entry=%016llx)!\n",
+					  i, entry_val);
+
+			invalid_count++;
+			continue;
+		}
+
+		/* paddr == bus_addr */
+		paddr = bus_addr;
+		/* mips64: map to xkphys: unmapped cached window */
+		vaddr = (volatile void *) (paddr | 0x9800000000000000ULL);
+
+		backup = *((volatile u32 *) (vaddr + RADEON_GPU_PAGE_SIZE - sizeof(u32)));
+
+		gpu_addr = rdev->mc.gtt_start + i*RADEON_GPU_PAGE_SIZE +
+			   RADEON_GPU_PAGE_SIZE - sizeof(u32);
+
+		r = radeon_fence_create(rdev, &fence);
+		if (r) {
+			DRM_ERROR("Iter=%d: failed to create fence.\n", i);
+			break;
+		}
+
+		r = radeon_ring_lock(rdev, 16 /* fence emit */ + 5);
+		if (r) {
+                	DRM_ERROR("Iter=%d: cp failed to lock ring (%d).\n", i, r);
+			break;
+        	}
+
+		radeon_ring_write(rdev, PACKET3(PACKET3_MEM_WRITE, 3));
+
+#define MY_GPU_ADDR_LO32_ALIGN32(gpu_addr) ((u32) ((gpu_addr) & 0xfffffffc))
+#define MY_GPU_ADDR_HI8(gpu_addr) ((u32) ((((gpu_addr) >> 32) & 0xff)))
+#define MY_DATA32_MODE (1<<18)
+
+		radeon_ring_write(rdev, 
+#ifdef __BIG_ENDIAN 
+			(2 << 0) | 
+#endif
+			MY_GPU_ADDR_LO32_ALIGN32(gpu_addr));
+		radeon_ring_write(rdev, MY_GPU_ADDR_HI8(gpu_addr) | MY_DATA32_MODE);
+		radeon_ring_write(rdev, 0xDEADBEEF);
+		radeon_ring_write(rdev, 0x0); /* Discarded */
+		radeon_fence_emit(rdev, fence);
+		radeon_ring_unlock_commit(rdev);
+
+		r = radeon_fence_wait(fence, false);
+                radeon_fence_unref(&fence);
+		if (r) {
+			DRM_ERROR("Iter=%d: failed to wait for fence.\n", i);
+			*((volatile u32 *) (vaddr + RADEON_GPU_PAGE_SIZE - sizeof(u32))) = backup;
+			break;
+		}
+
+		what_read = *((volatile u32 *) (vaddr + RADEON_GPU_PAGE_SIZE - sizeof(u32)));
+		if (what_read != 0xDEADBEEF) {
+			DRM_ERROR("Iter=%d: unexpected value 0x%08x(expect 0xDEADBEEF) "
+				  "entry=0x%016llx, orignal=0x%08x\n", 
+				  i, what_read, entry_val, backup);
+			// *((volatile u32 *) (vaddr + RADEON_GPU_PAGE_SIZE - sizeof(u32))) = backup;
+			// break;
+		}
+
+		*((volatile u32 *) (vaddr + RADEON_GPU_PAGE_SIZE - sizeof(u32))) = backup;
+		count++;
+	}
+
+
+	DRM_INFO("%s(): Sweep %d entries(valid=%d, invalid=%d, total=%d).\n",
+		 __func__, i, count, invalid_count, total_entries);
+
+	if (fence)
+		radeon_fence_unref(&fence);
+
+	return 0;
+}
+
 int r600_resume(struct radeon_device *rdev)
 {
 	int r;
@@ -2474,6 +2586,12 @@ int r600_resume(struct radeon_device *rdev)
 		return r;
 	}
 
+	r = r600_gart_table_validate(rdev);
+	if (r) {
+		DRM_ERROR("radeon: GART invalid failed\n");
+		return r;
+	}
+
 	return r;
 }
 
_______________________________________________
dri-devel mailing list
dri-devel@xxxxxxxxxxxxxxxxxxxxx
http://lists.freedesktop.org/mailman/listinfo/dri-devel

[Index of Archives]     [Linux DRI Users]     [Linux Intel Graphics]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [XFree86]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Linux Kernel]     [Linux SCSI]     [XFree86]
  Powered by Linux