在 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