262 lines · 7.0 KB · C
RawDownload
/* * Copyright 2009 Jerome Glisse. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. * * Authors: Jerome Glisse */ #include <drm/amdgpu_drm.h>#include "amdgpu.h" #define AMDGPU_BENCHMARK_ITERATIONS 1024#define AMDGPU_BENCHMARK_COMMON_MODES_N 17 static int amdgpu_benchmark_do_move(struct amdgpu_device *adev, unsigned size,				    uint64_t saddr, uint64_t daddr, int n, s64 *time_ms){	ktime_t stime, etime;	struct dma_fence *fence;	int i, r; 	mutex_lock(&adev->mman.default_entity.lock);	stime = ktime_get();	for (i = 0; i < n; i++) {		r = amdgpu_copy_buffer(adev, &adev->mman.default_entity,				       saddr, daddr, size, NULL, &fence,				       false, 0);		if (r)			goto exit_do_move;		r = dma_fence_wait(fence, false);		dma_fence_put(fence);		if (r)			goto exit_do_move;	} exit_do_move:	mutex_unlock(&adev->mman.default_entity.lock);	etime = ktime_get();	*time_ms = ktime_ms_delta(etime, stime); 	return r;}  static void amdgpu_benchmark_log_results(struct amdgpu_device *adev,					 int n, unsigned size,					 s64 time_ms,					 unsigned sdomain, unsigned ddomain,					 char *kind){	s64 throughput = (n * (size >> 10)); 	throughput = div64_s64(throughput, time_ms); 	dev_info(adev->dev, " %s %u bo moves of %u kB from"		 " %d to %d in %lld ms, throughput: %lld Mb/s or %lld MB/s\n",		 kind, n, size >> 10, sdomain, ddomain, time_ms,		 throughput * 8, throughput);} static int amdgpu_benchmark_move(struct amdgpu_device *adev, unsigned size,				 unsigned sdomain, unsigned ddomain){	struct amdgpu_bo *dobj = NULL;	struct amdgpu_bo *sobj = NULL;	uint64_t saddr, daddr;	s64 time_ms;	int r, n; 	n = AMDGPU_BENCHMARK_ITERATIONS; 	r = amdgpu_bo_create_kernel(adev, size,				    PAGE_SIZE, sdomain,				    &sobj,				    &saddr,				    NULL);	if (r)		goto out_cleanup;	r = amdgpu_bo_create_kernel(adev, size,				    PAGE_SIZE, ddomain,				    &dobj,				    &daddr,				    NULL);	if (r)		goto out_cleanup; 	if (adev->mman.buffer_funcs) {		r = amdgpu_benchmark_do_move(adev, size, saddr, daddr, n, &time_ms);		if (r)			goto out_cleanup;		else			amdgpu_benchmark_log_results(adev, n, size, time_ms,						     sdomain, ddomain, "dma");	} out_cleanup:	/* Check error value now. The value can be overwritten when clean up.*/	if (r < 0)		dev_info(adev->dev, "Error while benchmarking BO move.\n"); 	if (sobj)		amdgpu_bo_free_kernel(&sobj, &saddr, NULL);	if (dobj)		amdgpu_bo_free_kernel(&dobj, &daddr, NULL);	return r;} int amdgpu_benchmark(struct amdgpu_device *adev, int test_number){	int i, r;	static const int common_modes[AMDGPU_BENCHMARK_COMMON_MODES_N] = {		640 * 480 * 4,		720 * 480 * 4,		800 * 600 * 4,		848 * 480 * 4,		1024 * 768 * 4,		1152 * 768 * 4,		1280 * 720 * 4,		1280 * 800 * 4,		1280 * 854 * 4,		1280 * 960 * 4,		1280 * 1024 * 4,		1440 * 900 * 4,		1400 * 1050 * 4,		1680 * 1050 * 4,		1600 * 1200 * 4,		1920 * 1080 * 4,		1920 * 1200 * 4	}; 	mutex_lock(&adev->benchmark_mutex);	switch (test_number) {	case 1:		dev_info(adev->dev,			 "benchmark test: %d (simple test, VRAM to GTT and GTT to VRAM)\n",			 test_number);		/* simple test, VRAM to GTT and GTT to VRAM */		r = amdgpu_benchmark_move(adev, 1024*1024, AMDGPU_GEM_DOMAIN_GTT,					  AMDGPU_GEM_DOMAIN_VRAM);		if (r)			goto done;		r = amdgpu_benchmark_move(adev, 1024*1024, AMDGPU_GEM_DOMAIN_VRAM,					  AMDGPU_GEM_DOMAIN_GTT);		if (r)			goto done;		break;	case 2:		dev_info(adev->dev,			 "benchmark test: %d (simple test, VRAM to VRAM)\n",			 test_number);		/* simple test, VRAM to VRAM */		r = amdgpu_benchmark_move(adev, 1024*1024, AMDGPU_GEM_DOMAIN_VRAM,					  AMDGPU_GEM_DOMAIN_VRAM);		if (r)			goto done;		break;	case 3:		dev_info(adev->dev,			 "benchmark test: %d (GTT to VRAM, buffer size sweep, powers of 2)\n",			 test_number);		/* GTT to VRAM, buffer size sweep, powers of 2 */		for (i = 1; i <= 16384; i <<= 1) {			r = amdgpu_benchmark_move(adev, i * AMDGPU_GPU_PAGE_SIZE,						  AMDGPU_GEM_DOMAIN_GTT,						  AMDGPU_GEM_DOMAIN_VRAM);			if (r)				goto done;		}		break;	case 4:		dev_info(adev->dev,			 "benchmark test: %d (VRAM to GTT, buffer size sweep, powers of 2)\n",			 test_number);		/* VRAM to GTT, buffer size sweep, powers of 2 */		for (i = 1; i <= 16384; i <<= 1) {			r = amdgpu_benchmark_move(adev, i * AMDGPU_GPU_PAGE_SIZE,						  AMDGPU_GEM_DOMAIN_VRAM,						  AMDGPU_GEM_DOMAIN_GTT);			if (r)				goto done;		}		break;	case 5:		dev_info(adev->dev,			 "benchmark test: %d (VRAM to VRAM, buffer size sweep, powers of 2)\n",			 test_number);		/* VRAM to VRAM, buffer size sweep, powers of 2 */		for (i = 1; i <= 16384; i <<= 1) {			r = amdgpu_benchmark_move(adev, i * AMDGPU_GPU_PAGE_SIZE,						  AMDGPU_GEM_DOMAIN_VRAM,						  AMDGPU_GEM_DOMAIN_VRAM);			if (r)				goto done;		}		break;	case 6:		dev_info(adev->dev,			 "benchmark test: %d (GTT to VRAM, buffer size sweep, common modes)\n",			 test_number);		/* GTT to VRAM, buffer size sweep, common modes */		for (i = 0; i < AMDGPU_BENCHMARK_COMMON_MODES_N; i++) {			r = amdgpu_benchmark_move(adev, common_modes[i],						  AMDGPU_GEM_DOMAIN_GTT,						  AMDGPU_GEM_DOMAIN_VRAM);			if (r)				goto done;		}		break;	case 7:		dev_info(adev->dev,			 "benchmark test: %d (VRAM to GTT, buffer size sweep, common modes)\n",			 test_number);		/* VRAM to GTT, buffer size sweep, common modes */		for (i = 0; i < AMDGPU_BENCHMARK_COMMON_MODES_N; i++) {			r = amdgpu_benchmark_move(adev, common_modes[i],						  AMDGPU_GEM_DOMAIN_VRAM,						  AMDGPU_GEM_DOMAIN_GTT);			if (r)				goto done;		}		break;	case 8:		dev_info(adev->dev,			 "benchmark test: %d (VRAM to VRAM, buffer size sweep, common modes)\n",			 test_number);		/* VRAM to VRAM, buffer size sweep, common modes */		for (i = 0; i < AMDGPU_BENCHMARK_COMMON_MODES_N; i++) {			r = amdgpu_benchmark_move(adev, common_modes[i],					      AMDGPU_GEM_DOMAIN_VRAM,					      AMDGPU_GEM_DOMAIN_VRAM);			if (r)				goto done;		}		break; 	default:		dev_info(adev->dev, "Unknown benchmark %d\n", test_number);		r = -EINVAL;		break;	} done:	mutex_unlock(&adev->benchmark_mutex); 	return r;}