1d722e3fbSopenharmony_ci/*
2d722e3fbSopenharmony_ci * Copyright 2021 Advanced Micro Devices, Inc.
3d722e3fbSopenharmony_ci *
4d722e3fbSopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a
5d722e3fbSopenharmony_ci * copy of this software and associated documentation files (the "Software"),
6d722e3fbSopenharmony_ci * to deal in the Software without restriction, including without limitation
7d722e3fbSopenharmony_ci * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8d722e3fbSopenharmony_ci * and/or sell copies of the Software, and to permit persons to whom the
9d722e3fbSopenharmony_ci * Software is furnished to do so, subject to the following conditions:
10d722e3fbSopenharmony_ci *
11d722e3fbSopenharmony_ci * The above copyright notice and this permission notice shall be included in
12d722e3fbSopenharmony_ci * all copies or substantial portions of the Software.
13d722e3fbSopenharmony_ci *
14d722e3fbSopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15d722e3fbSopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16d722e3fbSopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
17d722e3fbSopenharmony_ci * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
18d722e3fbSopenharmony_ci * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19d722e3fbSopenharmony_ci * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20d722e3fbSopenharmony_ci * OTHER DEALINGS IN THE SOFTWARE.
21d722e3fbSopenharmony_ci *
22d722e3fbSopenharmony_ci*/
23d722e3fbSopenharmony_ci
24d722e3fbSopenharmony_ci#include <stdio.h>
25d722e3fbSopenharmony_ci#include <sys/types.h>
26d722e3fbSopenharmony_ci#include <sys/stat.h>
27d722e3fbSopenharmony_ci#include <fcntl.h>
28d722e3fbSopenharmony_ci#include <stdarg.h>
29d722e3fbSopenharmony_ci#include <string.h>
30d722e3fbSopenharmony_ci#include <errno.h>
31d722e3fbSopenharmony_ci#include <unistd.h>
32d722e3fbSopenharmony_ci#include <stdlib.h>
33d722e3fbSopenharmony_ci
34d722e3fbSopenharmony_ci#include "drm.h"
35d722e3fbSopenharmony_ci#include "xf86drmMode.h"
36d722e3fbSopenharmony_ci#include "xf86drm.h"
37d722e3fbSopenharmony_ci#include "amdgpu.h"
38d722e3fbSopenharmony_ci#include "amdgpu_drm.h"
39d722e3fbSopenharmony_ci#include "amdgpu_internal.h"
40d722e3fbSopenharmony_ci
41d722e3fbSopenharmony_ci#define MAX_CARDS_SUPPORTED	4
42d722e3fbSopenharmony_ci#define NUM_BUFFER_OBJECTS	1024
43d722e3fbSopenharmony_ci
44d722e3fbSopenharmony_ci#define SDMA_PACKET(op, sub_op, e)      ((((e) & 0xFFFF) << 16) |  \
45d722e3fbSopenharmony_ci					(((sub_op) & 0xFF) << 8) | \
46d722e3fbSopenharmony_ci					(((op) & 0xFF) << 0))
47d722e3fbSopenharmony_ci
48d722e3fbSopenharmony_ci#define SDMA_OPCODE_COPY				  1
49d722e3fbSopenharmony_ci#       define SDMA_COPY_SUB_OPCODE_LINEAR		0
50d722e3fbSopenharmony_ci
51d722e3fbSopenharmony_ci
52d722e3fbSopenharmony_ci#define SDMA_PACKET_SI(op, b, t, s, cnt)	((((op) & 0xF) << 28) | \
53d722e3fbSopenharmony_ci						(((b) & 0x1) << 26) |	\
54d722e3fbSopenharmony_ci						(((t) & 0x1) << 23) |	\
55d722e3fbSopenharmony_ci						(((s) & 0x1) << 22) |	\
56d722e3fbSopenharmony_ci						(((cnt) & 0xFFFFF) << 0))
57d722e3fbSopenharmony_ci#define SDMA_OPCODE_COPY_SI     3
58d722e3fbSopenharmony_ci
59d722e3fbSopenharmony_ci
60d722e3fbSopenharmony_ci/** Help string for command line parameters */
61d722e3fbSopenharmony_cistatic const char usage[] =
62d722e3fbSopenharmony_ci	"Usage: %s [-?h] [-b v|g|vg size] "
63d722e3fbSopenharmony_ci	"[-c from to size count]\n"
64d722e3fbSopenharmony_ci	"where:\n"
65d722e3fbSopenharmony_ci	"	b - Allocate a BO in VRAM, GTT or VRAM|GTT of size bytes.\n"
66d722e3fbSopenharmony_ci	"	    This flag can be used multiple times. The first bo will\n"
67d722e3fbSopenharmony_ci	"	    have id `1`, then second id `2`, ...\n"
68d722e3fbSopenharmony_ci	"       c - Copy size bytes from BO (bo_id1) to BO (bo_id2), count times\n"
69d722e3fbSopenharmony_ci	"       h - Display this help\n"
70d722e3fbSopenharmony_ci	"\n"
71d722e3fbSopenharmony_ci	"Sizes can be postfixes with k, m or g for kilo, mega and gigabyte scaling\n";
72d722e3fbSopenharmony_ci
73d722e3fbSopenharmony_ci/** Specified options strings for getopt */
74d722e3fbSopenharmony_cistatic const char options[]   = "?hb:c:";
75d722e3fbSopenharmony_ci
76d722e3fbSopenharmony_ci/* Open AMD devices.
77d722e3fbSopenharmony_ci * Returns the fd of the first device it could open.
78d722e3fbSopenharmony_ci */
79d722e3fbSopenharmony_cistatic int amdgpu_open_device(void)
80d722e3fbSopenharmony_ci{
81d722e3fbSopenharmony_ci	drmDevicePtr devices[MAX_CARDS_SUPPORTED];
82d722e3fbSopenharmony_ci	unsigned int i;
83d722e3fbSopenharmony_ci	int drm_count;
84d722e3fbSopenharmony_ci
85d722e3fbSopenharmony_ci	drm_count = drmGetDevices2(0, devices, MAX_CARDS_SUPPORTED);
86d722e3fbSopenharmony_ci	if (drm_count < 0) {
87d722e3fbSopenharmony_ci		fprintf(stderr, "drmGetDevices2() returned an error %d\n",
88d722e3fbSopenharmony_ci			drm_count);
89d722e3fbSopenharmony_ci		return drm_count;
90d722e3fbSopenharmony_ci	}
91d722e3fbSopenharmony_ci
92d722e3fbSopenharmony_ci	for (i = 0; i < drm_count; i++) {
93d722e3fbSopenharmony_ci		drmVersionPtr version;
94d722e3fbSopenharmony_ci		int fd;
95d722e3fbSopenharmony_ci
96d722e3fbSopenharmony_ci		/* If this is not PCI device, skip*/
97d722e3fbSopenharmony_ci		if (devices[i]->bustype != DRM_BUS_PCI)
98d722e3fbSopenharmony_ci			continue;
99d722e3fbSopenharmony_ci
100d722e3fbSopenharmony_ci		/* If this is not AMD GPU vender ID, skip*/
101d722e3fbSopenharmony_ci		if (devices[i]->deviceinfo.pci->vendor_id != 0x1002)
102d722e3fbSopenharmony_ci			continue;
103d722e3fbSopenharmony_ci
104d722e3fbSopenharmony_ci		if (!(devices[i]->available_nodes & 1 << DRM_NODE_RENDER))
105d722e3fbSopenharmony_ci			continue;
106d722e3fbSopenharmony_ci
107d722e3fbSopenharmony_ci		fd = open(devices[i]->nodes[DRM_NODE_RENDER], O_RDWR | O_CLOEXEC);
108d722e3fbSopenharmony_ci
109d722e3fbSopenharmony_ci		/* This node is not available. */
110d722e3fbSopenharmony_ci		if (fd < 0) continue;
111d722e3fbSopenharmony_ci
112d722e3fbSopenharmony_ci		version = drmGetVersion(fd);
113d722e3fbSopenharmony_ci		if (!version) {
114d722e3fbSopenharmony_ci			fprintf(stderr,
115d722e3fbSopenharmony_ci				"Warning: Cannot get version for %s."
116d722e3fbSopenharmony_ci				"Error is %s\n",
117d722e3fbSopenharmony_ci				devices[i]->nodes[DRM_NODE_RENDER],
118d722e3fbSopenharmony_ci				strerror(errno));
119d722e3fbSopenharmony_ci			close(fd);
120d722e3fbSopenharmony_ci			continue;
121d722e3fbSopenharmony_ci		}
122d722e3fbSopenharmony_ci
123d722e3fbSopenharmony_ci		if (strcmp(version->name, "amdgpu")) {
124d722e3fbSopenharmony_ci			/* This is not AMDGPU driver, skip.*/
125d722e3fbSopenharmony_ci			drmFreeVersion(version);
126d722e3fbSopenharmony_ci			close(fd);
127d722e3fbSopenharmony_ci			continue;
128d722e3fbSopenharmony_ci		}
129d722e3fbSopenharmony_ci
130d722e3fbSopenharmony_ci		drmFreeVersion(version);
131d722e3fbSopenharmony_ci		drmFreeDevices(devices, drm_count);
132d722e3fbSopenharmony_ci		return fd;
133d722e3fbSopenharmony_ci	}
134d722e3fbSopenharmony_ci
135d722e3fbSopenharmony_ci	return -1;
136d722e3fbSopenharmony_ci}
137d722e3fbSopenharmony_ci
138d722e3fbSopenharmony_ciamdgpu_device_handle device_handle;
139d722e3fbSopenharmony_ciamdgpu_context_handle context_handle;
140d722e3fbSopenharmony_ci
141d722e3fbSopenharmony_ciamdgpu_bo_handle resources[NUM_BUFFER_OBJECTS];
142d722e3fbSopenharmony_ciuint64_t virtual[NUM_BUFFER_OBJECTS];
143d722e3fbSopenharmony_ciunsigned int num_buffers;
144d722e3fbSopenharmony_ciuint32_t *pm4;
145d722e3fbSopenharmony_ci
146d722e3fbSopenharmony_ciint alloc_bo(uint32_t domain, uint64_t size)
147d722e3fbSopenharmony_ci{
148d722e3fbSopenharmony_ci	struct amdgpu_bo_alloc_request request = {};
149d722e3fbSopenharmony_ci	amdgpu_bo_handle bo;
150d722e3fbSopenharmony_ci	amdgpu_va_handle va;
151d722e3fbSopenharmony_ci	uint64_t addr;
152d722e3fbSopenharmony_ci	int r;
153d722e3fbSopenharmony_ci
154d722e3fbSopenharmony_ci	if (num_buffers >= NUM_BUFFER_OBJECTS)
155d722e3fbSopenharmony_ci		return -ENOSPC;
156d722e3fbSopenharmony_ci
157d722e3fbSopenharmony_ci	request.alloc_size = size;
158d722e3fbSopenharmony_ci	request.phys_alignment = 0;
159d722e3fbSopenharmony_ci	request.preferred_heap = domain;
160d722e3fbSopenharmony_ci	request.flags = 0;
161d722e3fbSopenharmony_ci	r = amdgpu_bo_alloc(device_handle, &request, &bo);
162d722e3fbSopenharmony_ci	if (r)
163d722e3fbSopenharmony_ci		return r;
164d722e3fbSopenharmony_ci
165d722e3fbSopenharmony_ci	r = amdgpu_va_range_alloc(device_handle, amdgpu_gpu_va_range_general,
166d722e3fbSopenharmony_ci				  size, 0, 0, &addr, &va, 0);
167d722e3fbSopenharmony_ci	if (r)
168d722e3fbSopenharmony_ci		return r;
169d722e3fbSopenharmony_ci
170d722e3fbSopenharmony_ci	r = amdgpu_bo_va_op_raw(device_handle, bo, 0, size, addr,
171d722e3fbSopenharmony_ci				AMDGPU_VM_PAGE_READABLE | AMDGPU_VM_PAGE_WRITEABLE |
172d722e3fbSopenharmony_ci				AMDGPU_VM_PAGE_EXECUTABLE, AMDGPU_VA_OP_MAP);
173d722e3fbSopenharmony_ci	if (r)
174d722e3fbSopenharmony_ci		return r;
175d722e3fbSopenharmony_ci
176d722e3fbSopenharmony_ci	resources[num_buffers] = bo;
177d722e3fbSopenharmony_ci	virtual[num_buffers] = addr;
178d722e3fbSopenharmony_ci	fprintf(stdout, "Allocated BO number %u at 0x%lx, domain 0x%x, size %lu\n",
179d722e3fbSopenharmony_ci		num_buffers++, addr, domain, size);
180d722e3fbSopenharmony_ci	return 0;
181d722e3fbSopenharmony_ci}
182d722e3fbSopenharmony_ci
183d722e3fbSopenharmony_ciint submit_ib(uint32_t from, uint32_t to, uint64_t size, uint32_t count)
184d722e3fbSopenharmony_ci{
185d722e3fbSopenharmony_ci	struct amdgpu_cs_request ibs_request;
186d722e3fbSopenharmony_ci	struct amdgpu_cs_fence fence_status;
187d722e3fbSopenharmony_ci	struct amdgpu_cs_ib_info ib_info;
188d722e3fbSopenharmony_ci	uint64_t copied = size, delta;
189d722e3fbSopenharmony_ci	struct timespec start, stop;
190d722e3fbSopenharmony_ci
191d722e3fbSopenharmony_ci	uint64_t src = virtual[from];
192d722e3fbSopenharmony_ci	uint64_t dst = virtual[to];
193d722e3fbSopenharmony_ci	uint32_t expired;
194d722e3fbSopenharmony_ci	int i, r;
195d722e3fbSopenharmony_ci
196d722e3fbSopenharmony_ci	i = 0;
197d722e3fbSopenharmony_ci	while (size) {
198d722e3fbSopenharmony_ci		uint64_t bytes = size < 0x40000 ? size : 0x40000;
199d722e3fbSopenharmony_ci
200d722e3fbSopenharmony_ci		if (device_handle->info.family_id == AMDGPU_FAMILY_SI) {
201d722e3fbSopenharmony_ci			pm4[i++] = SDMA_PACKET_SI(SDMA_OPCODE_COPY_SI, 0, 0, 0,
202d722e3fbSopenharmony_ci						  bytes);
203d722e3fbSopenharmony_ci			pm4[i++] = 0xffffffff & dst;
204d722e3fbSopenharmony_ci			pm4[i++] = 0xffffffff & src;
205d722e3fbSopenharmony_ci			pm4[i++] = (0xffffffff00000000 & dst) >> 32;
206d722e3fbSopenharmony_ci			pm4[i++] = (0xffffffff00000000 & src) >> 32;
207d722e3fbSopenharmony_ci		} else {
208d722e3fbSopenharmony_ci			pm4[i++] = SDMA_PACKET(SDMA_OPCODE_COPY,
209d722e3fbSopenharmony_ci					       SDMA_COPY_SUB_OPCODE_LINEAR,
210d722e3fbSopenharmony_ci					       0);
211d722e3fbSopenharmony_ci			if ( device_handle->info.family_id >= AMDGPU_FAMILY_AI)
212d722e3fbSopenharmony_ci				pm4[i++] = bytes - 1;
213d722e3fbSopenharmony_ci			else
214d722e3fbSopenharmony_ci				pm4[i++] = bytes;
215d722e3fbSopenharmony_ci			pm4[i++] = 0;
216d722e3fbSopenharmony_ci			pm4[i++] = 0xffffffff & src;
217d722e3fbSopenharmony_ci			pm4[i++] = (0xffffffff00000000 & src) >> 32;
218d722e3fbSopenharmony_ci			pm4[i++] = 0xffffffff & dst;
219d722e3fbSopenharmony_ci			pm4[i++] = (0xffffffff00000000 & dst) >> 32;
220d722e3fbSopenharmony_ci		}
221d722e3fbSopenharmony_ci
222d722e3fbSopenharmony_ci		size -= bytes;
223d722e3fbSopenharmony_ci		src += bytes;
224d722e3fbSopenharmony_ci		dst += bytes;
225d722e3fbSopenharmony_ci	}
226d722e3fbSopenharmony_ci
227d722e3fbSopenharmony_ci	memset(&ib_info, 0, sizeof(ib_info));
228d722e3fbSopenharmony_ci	ib_info.ib_mc_address = virtual[0];
229d722e3fbSopenharmony_ci	ib_info.size = i;
230d722e3fbSopenharmony_ci
231d722e3fbSopenharmony_ci	memset(&ibs_request, 0, sizeof(ibs_request));
232d722e3fbSopenharmony_ci	ibs_request.ip_type = AMDGPU_HW_IP_DMA;
233d722e3fbSopenharmony_ci	ibs_request.ring = 0;
234d722e3fbSopenharmony_ci	ibs_request.number_of_ibs = 1;
235d722e3fbSopenharmony_ci	ibs_request.ibs = &ib_info;
236d722e3fbSopenharmony_ci	ibs_request.fence_info.handle = NULL;
237d722e3fbSopenharmony_ci
238d722e3fbSopenharmony_ci	r = clock_gettime(CLOCK_MONOTONIC, &start);
239d722e3fbSopenharmony_ci	if (r)
240d722e3fbSopenharmony_ci		return errno;
241d722e3fbSopenharmony_ci
242d722e3fbSopenharmony_ci	r = amdgpu_bo_list_create(device_handle, num_buffers, resources, NULL,
243d722e3fbSopenharmony_ci				  &ibs_request.resources);
244d722e3fbSopenharmony_ci	if (r)
245d722e3fbSopenharmony_ci		return r;
246d722e3fbSopenharmony_ci
247d722e3fbSopenharmony_ci	for (i = 0; i < count; ++i) {
248d722e3fbSopenharmony_ci		r = amdgpu_cs_submit(context_handle, 0, &ibs_request, 1);
249d722e3fbSopenharmony_ci		if (r)
250d722e3fbSopenharmony_ci			return r;
251d722e3fbSopenharmony_ci	}
252d722e3fbSopenharmony_ci
253d722e3fbSopenharmony_ci	r = amdgpu_bo_list_destroy(ibs_request.resources);
254d722e3fbSopenharmony_ci	if (r)
255d722e3fbSopenharmony_ci		return r;
256d722e3fbSopenharmony_ci
257d722e3fbSopenharmony_ci	memset(&fence_status, 0, sizeof(fence_status));
258d722e3fbSopenharmony_ci	fence_status.ip_type = ibs_request.ip_type;
259d722e3fbSopenharmony_ci	fence_status.ip_instance = 0;
260d722e3fbSopenharmony_ci	fence_status.ring = ibs_request.ring;
261d722e3fbSopenharmony_ci	fence_status.context = context_handle;
262d722e3fbSopenharmony_ci	fence_status.fence = ibs_request.seq_no;
263d722e3fbSopenharmony_ci	r = amdgpu_cs_query_fence_status(&fence_status,
264d722e3fbSopenharmony_ci					 AMDGPU_TIMEOUT_INFINITE,
265d722e3fbSopenharmony_ci					 0, &expired);
266d722e3fbSopenharmony_ci	if (r)
267d722e3fbSopenharmony_ci		return r;
268d722e3fbSopenharmony_ci
269d722e3fbSopenharmony_ci	r = clock_gettime(CLOCK_MONOTONIC, &stop);
270d722e3fbSopenharmony_ci	if (r)
271d722e3fbSopenharmony_ci		return errno;
272d722e3fbSopenharmony_ci
273d722e3fbSopenharmony_ci	delta = stop.tv_nsec + stop.tv_sec * 1000000000UL;
274d722e3fbSopenharmony_ci	delta -= start.tv_nsec + start.tv_sec * 1000000000UL;
275d722e3fbSopenharmony_ci
276d722e3fbSopenharmony_ci	fprintf(stdout, "Submitted %u IBs to copy from %u(%lx) to %u(%lx) %lu bytes took %lu usec\n",
277d722e3fbSopenharmony_ci		count, from, virtual[from], to, virtual[to], copied, delta / 1000);
278d722e3fbSopenharmony_ci	return 0;
279d722e3fbSopenharmony_ci}
280d722e3fbSopenharmony_ci
281d722e3fbSopenharmony_civoid next_arg(int argc, char **argv, const char *msg)
282d722e3fbSopenharmony_ci{
283d722e3fbSopenharmony_ci	optarg = argv[optind++];
284d722e3fbSopenharmony_ci	if (optind > argc || optarg[0] == '-') {
285d722e3fbSopenharmony_ci		fprintf(stderr, "%s\n", msg);
286d722e3fbSopenharmony_ci		exit(EXIT_FAILURE);
287d722e3fbSopenharmony_ci	}
288d722e3fbSopenharmony_ci}
289d722e3fbSopenharmony_ci
290d722e3fbSopenharmony_ciuint64_t parse_size(void)
291d722e3fbSopenharmony_ci{
292d722e3fbSopenharmony_ci	uint64_t size;
293d722e3fbSopenharmony_ci	char ext[2];
294d722e3fbSopenharmony_ci
295d722e3fbSopenharmony_ci	ext[0] = 0;
296d722e3fbSopenharmony_ci	if (sscanf(optarg, "%li%1[kmgKMG]", &size, ext) < 1) {
297d722e3fbSopenharmony_ci		fprintf(stderr, "Can't parse size arg: %s\n", optarg);
298d722e3fbSopenharmony_ci		exit(EXIT_FAILURE);
299d722e3fbSopenharmony_ci	}
300d722e3fbSopenharmony_ci	switch (ext[0]) {
301d722e3fbSopenharmony_ci	case 'k':
302d722e3fbSopenharmony_ci	case 'K':
303d722e3fbSopenharmony_ci		size *= 1024;
304d722e3fbSopenharmony_ci		break;
305d722e3fbSopenharmony_ci	case 'm':
306d722e3fbSopenharmony_ci	case 'M':
307d722e3fbSopenharmony_ci		size *= 1024 * 1024;
308d722e3fbSopenharmony_ci		break;
309d722e3fbSopenharmony_ci	case 'g':
310d722e3fbSopenharmony_ci	case 'G':
311d722e3fbSopenharmony_ci		size *= 1024 * 1024 * 1024;
312d722e3fbSopenharmony_ci		break;
313d722e3fbSopenharmony_ci	default:
314d722e3fbSopenharmony_ci		break;
315d722e3fbSopenharmony_ci	}
316d722e3fbSopenharmony_ci	return size;
317d722e3fbSopenharmony_ci}
318d722e3fbSopenharmony_ci
319d722e3fbSopenharmony_ciint main(int argc, char **argv)
320d722e3fbSopenharmony_ci{
321d722e3fbSopenharmony_ci	uint32_t major_version, minor_version;
322d722e3fbSopenharmony_ci	uint32_t domain, from, to, count;
323d722e3fbSopenharmony_ci       	uint64_t size;
324d722e3fbSopenharmony_ci	int fd, r, c;
325d722e3fbSopenharmony_ci
326d722e3fbSopenharmony_ci	fd = amdgpu_open_device();
327d722e3fbSopenharmony_ci       	if (fd < 0) {
328d722e3fbSopenharmony_ci		perror("Cannot open AMDGPU device");
329d722e3fbSopenharmony_ci		exit(EXIT_FAILURE);
330d722e3fbSopenharmony_ci	}
331d722e3fbSopenharmony_ci
332d722e3fbSopenharmony_ci	r = amdgpu_device_initialize(fd, &major_version, &minor_version, &device_handle);
333d722e3fbSopenharmony_ci	if (r) {
334d722e3fbSopenharmony_ci		fprintf(stderr, "amdgpu_device_initialize returned %d\n", r);
335d722e3fbSopenharmony_ci		exit(EXIT_FAILURE);
336d722e3fbSopenharmony_ci	}
337d722e3fbSopenharmony_ci
338d722e3fbSopenharmony_ci	r = amdgpu_cs_ctx_create(device_handle, &context_handle);
339d722e3fbSopenharmony_ci	if (r) {
340d722e3fbSopenharmony_ci		fprintf(stderr, "amdgpu_cs_ctx_create returned %d\n", r);
341d722e3fbSopenharmony_ci		exit(EXIT_FAILURE);
342d722e3fbSopenharmony_ci	}
343d722e3fbSopenharmony_ci
344d722e3fbSopenharmony_ci	if (argc == 1) {
345d722e3fbSopenharmony_ci		fprintf(stderr, usage, argv[0]);
346d722e3fbSopenharmony_ci		exit(EXIT_FAILURE);
347d722e3fbSopenharmony_ci	}
348d722e3fbSopenharmony_ci
349d722e3fbSopenharmony_ci	r = alloc_bo(AMDGPU_GEM_DOMAIN_GTT, 2ULL * 1024 * 1024);
350d722e3fbSopenharmony_ci	if (r) {
351d722e3fbSopenharmony_ci		fprintf(stderr, "Buffer allocation failed with %d\n", r);
352d722e3fbSopenharmony_ci		exit(EXIT_FAILURE);
353d722e3fbSopenharmony_ci	}
354d722e3fbSopenharmony_ci
355d722e3fbSopenharmony_ci	r = amdgpu_bo_cpu_map(resources[0], (void **)&pm4);
356d722e3fbSopenharmony_ci	if (r) {
357d722e3fbSopenharmony_ci		fprintf(stderr, "Buffer mapping failed with %d\n", r);
358d722e3fbSopenharmony_ci		exit(EXIT_FAILURE);
359d722e3fbSopenharmony_ci	}
360d722e3fbSopenharmony_ci
361d722e3fbSopenharmony_ci	opterr = 0;
362d722e3fbSopenharmony_ci	while ((c = getopt(argc, argv, options)) != -1) {
363d722e3fbSopenharmony_ci		switch (c) {
364d722e3fbSopenharmony_ci		case 'b':
365d722e3fbSopenharmony_ci			if (!strcmp(optarg, "v"))
366d722e3fbSopenharmony_ci				domain = AMDGPU_GEM_DOMAIN_VRAM;
367d722e3fbSopenharmony_ci			else if (!strcmp(optarg, "g"))
368d722e3fbSopenharmony_ci				domain = AMDGPU_GEM_DOMAIN_GTT;
369d722e3fbSopenharmony_ci			else if (!strcmp(optarg, "vg"))
370d722e3fbSopenharmony_ci				domain = AMDGPU_GEM_DOMAIN_VRAM | AMDGPU_GEM_DOMAIN_GTT;
371d722e3fbSopenharmony_ci			else {
372d722e3fbSopenharmony_ci				fprintf(stderr, "Invalid domain: %s\n", optarg);
373d722e3fbSopenharmony_ci				exit(EXIT_FAILURE);
374d722e3fbSopenharmony_ci			}
375d722e3fbSopenharmony_ci			next_arg(argc, argv, "Missing buffer size");
376d722e3fbSopenharmony_ci			size = parse_size();
377d722e3fbSopenharmony_ci			if (size < getpagesize()) {
378d722e3fbSopenharmony_ci				fprintf(stderr, "Buffer size to small %lu\n", size);
379d722e3fbSopenharmony_ci				exit(EXIT_FAILURE);
380d722e3fbSopenharmony_ci			}
381d722e3fbSopenharmony_ci			r = alloc_bo(domain, size);
382d722e3fbSopenharmony_ci			if (r) {
383d722e3fbSopenharmony_ci				fprintf(stderr, "Buffer allocation failed with %d\n", r);
384d722e3fbSopenharmony_ci				exit(EXIT_FAILURE);
385d722e3fbSopenharmony_ci			}
386d722e3fbSopenharmony_ci			break;
387d722e3fbSopenharmony_ci		case 'c':
388d722e3fbSopenharmony_ci			if (sscanf(optarg, "%u", &from) != 1) {
389d722e3fbSopenharmony_ci				fprintf(stderr, "Can't parse from buffer: %s\n", optarg);
390d722e3fbSopenharmony_ci				exit(EXIT_FAILURE);
391d722e3fbSopenharmony_ci			}
392d722e3fbSopenharmony_ci			next_arg(argc, argv, "Missing to buffer");
393d722e3fbSopenharmony_ci			if (sscanf(optarg, "%u", &to) != 1) {
394d722e3fbSopenharmony_ci				fprintf(stderr, "Can't parse to buffer: %s\n", optarg);
395d722e3fbSopenharmony_ci				exit(EXIT_FAILURE);
396d722e3fbSopenharmony_ci			}
397d722e3fbSopenharmony_ci			next_arg(argc, argv, "Missing size");
398d722e3fbSopenharmony_ci			size = parse_size();
399d722e3fbSopenharmony_ci			next_arg(argc, argv, "Missing count");
400d722e3fbSopenharmony_ci			count = parse_size();
401d722e3fbSopenharmony_ci			r = submit_ib(from, to, size, count);
402d722e3fbSopenharmony_ci			if (r) {
403d722e3fbSopenharmony_ci				fprintf(stderr, "IB submission failed with %d\n", r);
404d722e3fbSopenharmony_ci				exit(EXIT_FAILURE);
405d722e3fbSopenharmony_ci			}
406d722e3fbSopenharmony_ci			break;
407d722e3fbSopenharmony_ci		case '?':
408d722e3fbSopenharmony_ci		case 'h':
409d722e3fbSopenharmony_ci			fprintf(stderr, usage, argv[0]);
410d722e3fbSopenharmony_ci			exit(EXIT_SUCCESS);
411d722e3fbSopenharmony_ci		default:
412d722e3fbSopenharmony_ci			fprintf(stderr, usage, argv[0]);
413d722e3fbSopenharmony_ci			exit(EXIT_FAILURE);
414d722e3fbSopenharmony_ci		}
415d722e3fbSopenharmony_ci	}
416d722e3fbSopenharmony_ci
417d722e3fbSopenharmony_ci	return EXIT_SUCCESS;
418d722e3fbSopenharmony_ci}
419