在 2012年2月17日 下午5:27,Chen Jie <[email protected]> 写道:
>> 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
[email protected]
http://lists.freedesktop.org/mailman/listinfo/dri-devel