Esempio n. 1
0
static void test_reimport_close_race(void)
{
	pthread_t *threads;
	int r, i, num_threads;
	int fds[2];
	int obj_count;
	void *status;
	uint32_t handle;
	int fake;

	/* Allocate exit handler fds in here so that we dont screw
	 * up the counts */
	fake = drm_open_driver(DRIVER_INTEL);

	gem_quiescent_gpu(fake);
	obj_count = get_object_count();

	num_threads = sysconf(_SC_NPROCESSORS_ONLN);

	threads = calloc(num_threads, sizeof(pthread_t));

	fds[0] = drm_open_driver(DRIVER_INTEL);

	handle = gem_create(fds[0], BO_SIZE);

	fds[1] = prime_handle_to_fd(fds[0], handle);

	for (i = 0; i < num_threads; i++) {
		r = pthread_create(&threads[i], NULL,
				   thread_fn_reimport_vs_close,
				   (void *)(uintptr_t)fds);
		igt_assert_eq(r, 0);
	}

	sleep(5);

	pls_die = 1;

	for (i = 0;  i < num_threads; i++) {
		pthread_join(threads[i], &status);
		igt_assert(status == 0);
	}

	close(fds[0]);
	close(fds[1]);

	gem_quiescent_gpu(fake);
	obj_count = get_object_count() - obj_count;

	igt_info("leaked %i objects\n", obj_count);

	close(fake);

	igt_assert_eq(obj_count, 0);
}
Esempio n. 2
0
static void
test_create_close(int fd)
{
	uint32_t handle;

	igt_info("Testing creating and closing an object.\n");

	handle = gem_create(fd, 16*1024);

	gem_close(fd, handle);
}
Esempio n. 3
0
static void
test_bad_close(int fd)
{
	struct drm_gem_close close_bo;
	int ret;

	igt_info("Testing error return on bad close ioctl.\n");

	close_bo.handle = 0x10101010;
	ret = ioctl(fd, DRM_IOCTL_GEM_CLOSE, &close_bo);

	igt_assert(ret == -1 && errno == EINVAL);
}
Esempio n. 4
0
static void dump_crtcs_fd(int drmfd)
{
	int i;
	drmModeRes *mode_resources = drmModeGetResources(drmfd);

	igt_info("CRTCs:\n");
	igt_info("id\tfb\tpos\tsize\n");
	for (i = 0; i < mode_resources->count_crtcs; i++) {
		drmModeCrtc *crtc;

		crtc = drmModeGetCrtc(drmfd, mode_resources->crtcs[i]);
		if (!crtc) {
			igt_warn("could not get crtc %i: %s\n", mode_resources->crtcs[i], strerror(errno));
			continue;
		}
		igt_info("%d\t%d\t(%d,%d)\t(%dx%d)\n", crtc->crtc_id, crtc->buffer_id, crtc->x, crtc->y, crtc->width, crtc->height);
		kmstest_dump_mode(&crtc->mode);

		drmModeFreeCrtc(crtc);
	}
	igt_info("\n");

	drmModeFreeResources(mode_resources);
}
Esempio n. 5
0
static void test_read_crc(data_t *data, int pipe, unsigned flags)
{
	igt_display_t *display = &data->display;
	int valid_connectors = 0;
	igt_output_t *output;

	igt_skip_on(pipe >= data->display.n_pipes);

	for_each_connected_output(display, output) {

		igt_info("%s: Testing connector %s using pipe %s\n",
			 igt_subtest_name(), igt_output_name(output),
			 kmstest_pipe_name(pipe));

		valid_connectors += test_read_crc_for_output(data, pipe, output, flags);
	}
Esempio n. 6
0
static void
set_stereo_mode(struct connector *c)
{
	int i, n;


	if (specified_mode_num != -1)
		n = 1;
	else
		n = c->connector->count_modes;

	for (i = 0; i < n; i++) {
		if (specified_mode_num == -1)
			c->mode = c->connector->modes[i];

		if (!c->mode_valid)
			continue;

		if (!(c->mode.flags & DRM_MODE_FLAG_3D_MASK))
			continue;

		igt_info("CRTC(%u): [%d]", c->crtc, i);
		kmstest_dump_mode(&c->mode);
		do_set_stereo_mode(c);

		if (qr_code) {
			set_single();
			pause();
		} else if (sleep_between_modes)
			sleep(sleep_between_modes);

		if (do_dpms) {
			kmstest_set_connector_dpms(drm_fd, c->connector, DRM_MODE_DPMS_OFF);
			sleep(sleep_between_modes);
			kmstest_set_connector_dpms(drm_fd, c->connector, DRM_MODE_DPMS_ON);
		}
	}

	drmModeFreeEncoder(c->encoder);
	drmModeFreeConnector(c->connector);
}
Esempio n. 7
0
static void test_connector(const char *test_name,
			   struct kmstest_connector_config *cconf,
			   enum test_flags flags)
{
	const uint32_t *formats;
	int format_count;
	int i;

	igt_get_all_formats(&formats, &format_count);
	for (i = 0; i < format_count; i++) {
		if (intel_gen(intel_get_drm_devid(drm_fd)) < 4
		    && formats[i] == DRM_FORMAT_XRGB2101010) {
			igt_info("gen2/3 don't support 10bpc, skipping\n");
			continue;
		}

		test_format(test_name,
			    cconf, &cconf->connector->modes[0],
			    formats[i], flags);
	}
}
static unsigned get_num_contexts(int fd)
{
	uint64_t ggtt_size;
	unsigned size;
	unsigned count;

	/* Compute the number of contexts we can allocate to fill the GGTT */
	if (intel_gen(intel_get_drm_devid(fd)) >= 8)
		ggtt_size = 1ull << 32;
	else
		ggtt_size = 1ull << 31;

	size = 64 << 10; /* Most gen require at least 64k for ctx */

	count = 3 * (ggtt_size / size) / 2;
	igt_info("Creating %lld contexts (assuming of size %lld)\n",
		 (long long)count, (long long)size);

	intel_require_memory(count, size, CHECK_RAM | CHECK_SWAP);
	return count;
}
Esempio n. 9
0
static void dump_connectors_fd(int drmfd)
{
	int i, j;

	drmModeRes *mode_resources = drmModeGetResources(drmfd);

	if (!mode_resources) {
		igt_warn("drmModeGetResources failed: %s\n", strerror(errno));
		return;
	}

	igt_info("Connectors:\n");
	igt_info("id\tencoder\tstatus\t\ttype\tsize (mm)\tmodes\n");
	for (i = 0; i < mode_resources->count_connectors; i++) {
		drmModeConnector *connector;

		connector = drmModeGetConnectorCurrent(drmfd,
						       mode_resources->connectors[i]);
		if (!connector) {
			igt_warn("could not get connector %i: %s\n", mode_resources->connectors[i], strerror(errno));
			continue;
		}

		igt_info("%d\t%d\t%s\t%s\t%dx%d\t\t%d\n", connector->connector_id, connector->encoder_id, kmstest_connector_status_str(connector->connection), kmstest_connector_type_str(connector->connector_type), connector->mmWidth, connector->mmHeight, connector->count_modes);

		if (!connector->count_modes)
			continue;

		igt_info("  modes:\n");
		igt_info("  name refresh (Hz) hdisp hss hse htot vdisp ""vss vse vtot flags type clock\n");
		for (j = 0; j < connector->count_modes; j++){
			igt_info("[%d]", j);
			kmstest_dump_mode(&connector->modes[j]);
		}

		drmModeFreeConnector(connector);
	}
	igt_info("\n");

	drmModeFreeResources(mode_resources);
}
Esempio n. 10
0
static void exec0(int fd)
{
	struct drm_i915_gem_execbuffer2 execbuf;
	struct drm_i915_gem_exec_object2 exec[1];
	uint32_t buf[2] = { MI_BATCH_BUFFER_END, 0 };

	/* Just try executing with a zero-length bo.
	 * We expect the kernel to either accept the nop batch, or reject it
	 * for the zero-length buffer, but never crash.
	 */

	exec[0].handle = gem_create(fd, 4096);
	gem_write(fd, exec[0].handle, 0, buf, sizeof(buf));
	exec[0].relocation_count = 0;
	exec[0].relocs_ptr = 0;
	exec[0].alignment = 0;
	exec[0].offset = 0;
	exec[0].flags = 0;
	exec[0].rsvd1 = 0;
	exec[0].rsvd2 = 0;

	execbuf.buffers_ptr = (uintptr_t)exec;
	execbuf.buffer_count = 1;
	execbuf.batch_start_offset = 0;
	execbuf.batch_len = sizeof(buf);
	execbuf.cliprects_ptr = 0;
	execbuf.num_cliprects = 0;
	execbuf.DR1 = 0;
	execbuf.DR4 = 0;
	execbuf.flags = 0;
	i915_execbuffer2_set_context_id(execbuf, 0);
	execbuf.rsvd2 = 0;

	igt_info("trying to run an empty batchbuffer\n");
	gem_exec(fd, &execbuf);

	gem_close(fd, exec[0].handle);
}
Esempio n. 11
0
static void vblank_wait(int fd, bool busy)
{
	union drm_wait_vblank vbl;
	struct timespec start, end;
	unsigned long sq, count = 0;
	struct drm_event_vblank buf;

	memset(&vbl, 0, sizeof(vbl));

	if (busy) {
		vbl.request.type = DRM_VBLANK_RELATIVE | DRM_VBLANK_EVENT;
		vbl.request.sequence = 72;
		do_ioctl(fd, DRM_IOCTL_WAIT_VBLANK, &vbl);
	}

	vbl.request.type = DRM_VBLANK_RELATIVE;
	vbl.request.sequence = 0;
	do_ioctl(fd, DRM_IOCTL_WAIT_VBLANK, &vbl);

	sq = vbl.reply.sequence;

	clock_gettime(CLOCK_MONOTONIC, &start);
	do {
		vbl.request.type = DRM_VBLANK_RELATIVE;
		vbl.request.sequence = 1;
		do_ioctl(fd, DRM_IOCTL_WAIT_VBLANK, &vbl);
		count++;
	} while ((vbl.reply.sequence - sq) <= 60);
	clock_gettime(CLOCK_MONOTONIC, &end);

	igt_info("Time to wait for %ld/%d vblanks (%s):		%7.3fµs\n",
		 count, (int)(vbl.reply.sequence - sq),
		 busy ? "busy" : "idle",
		 elapsed(&start, &end, count));

	if (busy)
		igt_assert_eq(read(fd, &buf, sizeof(buf)), sizeof(buf));
}
static void thread_performance(unsigned mask)
{
	const int loops = 4096;
	int n, count;
	int fd, num_fences;
	double linear[2], tiled[2];

	fd = drm_open_any();

	num_fences = gem_available_fences(fd);
	igt_require(num_fences > 0);

	for (count = 2; count < 4*num_fences; count *= 2) {
		const int nthreads = (mask & READ ? count : 0) + (mask & WRITE ? count : 0);
		struct timeval start, end;
		struct thread_performance readers[count];
		struct thread_performance writers[count];
		uint32_t handle[count];
		void *ptr[count];

		for (n = 0; n < count; n++) {
			handle[n] = gem_create(fd, OBJECT_SIZE);
			ptr[n] = gem_mmap(fd, handle[n], OBJECT_SIZE, PROT_READ | PROT_WRITE);
			igt_assert(ptr[n]);

			if (mask & READ) {
				readers[n].id = n;
				readers[n].direction = READ;
				readers[n].ptr = ptr;
				readers[n].count = count;
				readers[n].loops = loops;
			}

			if (mask & WRITE) {
				writers[n].id = count - n - 1;
				writers[n].direction = WRITE;
				writers[n].ptr = ptr;
				writers[n].count = count;
				writers[n].loops = loops;
			}
		}

		gettimeofday(&start, NULL);
		for (n = 0; n < count; n++) {
			if (mask & READ)
				pthread_create(&readers[n].thread, NULL, read_thread_performance, &readers[n]);
			if (mask & WRITE)
				pthread_create(&writers[n].thread, NULL, write_thread_performance, &writers[n]);
		}
		for (n = 0; n < count; n++) {
			if (mask & READ)
				pthread_join(readers[n].thread, NULL);
			if (mask & WRITE)
				pthread_join(writers[n].thread, NULL);
		}
		gettimeofday(&end, NULL);

		linear[count != 2] = nthreads * loops / elapsed(&start, &end) / (OBJECT_SIZE / 4096);
		igt_info("%s rate for %d linear surfaces, %d threads:	%7.3fMiB/s\n", direction_string(mask), count, nthreads, linear[count != 2]);

		for (n = 0; n < count; n++)
			gem_set_tiling(fd, handle[n], I915_TILING_X, 1024);

		gettimeofday(&start, NULL);
		for (n = 0; n < count; n++) {
			if (mask & READ)
				pthread_create(&readers[n].thread, NULL, read_thread_performance, &readers[n]);
			if (mask & WRITE)
				pthread_create(&writers[n].thread, NULL, write_thread_performance, &writers[n]);
		}
		for (n = 0; n < count; n++) {
			if (mask & READ)
				pthread_join(readers[n].thread, NULL);
			if (mask & WRITE)
				pthread_join(writers[n].thread, NULL);
		}
		gettimeofday(&end, NULL);

		tiled[count != 2] = nthreads * loops / elapsed(&start, &end) / (OBJECT_SIZE / 4096);
		igt_info("%s rate for %d tiled surfaces, %d threads:	%7.3fMiB/s\n", direction_string(mask), count, nthreads, tiled[count != 2]);

		for (n = 0; n < count; n++) {
			munmap(ptr[n], OBJECT_SIZE);
			gem_close(fd, handle[n]);
		}
	}

	errno = 0;
	igt_assert(linear[1] > 0.75 * linear[0]);
	igt_assert(tiled[1] > 0.75 * tiled[0]);
}
Esempio n. 13
0
static int negative_reloc_blt(int fd)
{
	const int gen = intel_gen(intel_get_drm_devid(fd));
	struct drm_i915_gem_execbuffer2 execbuf;
	struct drm_i915_gem_exec_object2 gem_exec[1024][2];
	struct drm_i915_gem_relocation_entry gem_reloc;
	uint32_t buf[1024], *b;
	int i;

	memset(&gem_reloc, 0, sizeof(gem_reloc));
	gem_reloc.offset = 4 * sizeof(uint32_t);
	gem_reloc.presumed_offset = ~0ULL;
	gem_reloc.delta = -4096;
	gem_reloc.target_handle = 0;
	gem_reloc.read_domains = I915_GEM_DOMAIN_RENDER;
	gem_reloc.write_domain = I915_GEM_DOMAIN_RENDER;

	for (i = 0; i < 1024; i++) {
		memset(gem_exec[i], 0, sizeof(gem_exec[i]));

		gem_exec[i][0].handle = gem_create(fd, 4096);
		gem_exec[i][0].flags = EXEC_OBJECT_NEEDS_FENCE;

		b = buf;
		*b++ = XY_COLOR_BLT_CMD_NOLEN |
			((gen >= 8) ? 5 : 4) |
			COLOR_BLT_WRITE_ALPHA | XY_COLOR_BLT_WRITE_RGB;
		*b++ = 0xf0 << 16 | 1 << 25 | 1 << 24 | 4096;
		*b++ = 1 << 16 | 0;
		*b++ = 2 << 16 | 1024;
		*b++ = ~0;
		if (gen >= 8)
			*b++ = ~0;
		*b++ = 0xc0ffee ^ i;
		*b++ = MI_BATCH_BUFFER_END;
		if ((b - buf) & 1)
			*b++ = 0;

		gem_exec[i][1].handle = gem_create(fd, 4096);
		gem_write(fd, gem_exec[i][1].handle, 0, buf, (b - buf) * sizeof(uint32_t));
		gem_exec[i][1].relocation_count = 1;
		gem_exec[i][1].relocs_ptr = (uintptr_t)&gem_reloc;
	}

	memset(&execbuf, 0, sizeof(execbuf));
	execbuf.buffer_count = 2;
	execbuf.batch_len = (b - buf) * sizeof(uint32_t);
	execbuf.flags = USE_LUT;
	if (gen >= 6)
		execbuf.flags |= I915_EXEC_BLT;

	for (i = 0; i < 1024; i++) {
		execbuf.buffers_ptr = (uintptr_t)gem_exec[i];
		gem_execbuf(fd, &execbuf);
	}

	for (i = 1024; i--;) {
		gem_read(fd, gem_exec[i][0].handle,
			 i*sizeof(uint32_t), buf + i, sizeof(uint32_t));
		gem_close(fd, gem_exec[i][0].handle);
		gem_close(fd, gem_exec[i][1].handle);
	}

	if (0) {
		for (i = 0; i < 1024; i += 8)
			igt_info("%08x %08x %08x %08x %08x %08x %08x %08x\n",
				 buf[i + 0], buf[i + 1], buf[i + 2], buf[i + 3],
				 buf[i + 4], buf[i + 5], buf[i + 6], buf[i + 7]);
	}
	for (i = 0; i < 1024; i++)
		igt_assert_eq(buf[i], 0xc0ffee ^ i);

	return 0;
}
Esempio n. 14
0
static void __attribute__((noreturn)) usage(char *name, char opt)
{
	igt_info("usage: %s [-hiasdpmtf]\n", name);
	igt_info("\t-i\tdump info\n");
	igt_info("\t-a\ttest all modes\n");
	igt_info("\t-s\t<duration>\tsleep between each mode test\n");
	igt_info("\t-d\t<depth>\tbit depth of scanout buffer\n");
	igt_info("\t-p\t<planew,h>,<crtcx,y>,<crtcw,h> test overlay plane\n");
	igt_info("\t-m\ttest the preferred mode\n");
	igt_info("\t-3\ttest all 3D modes\n");
	igt_info("\t-t\tuse a tiled framebuffer\n");
	igt_info("\t-j\tdo dpms off, optional arg to select dpms leve (1-3)\n");
	igt_info("\t-r\tprint a QR code on the screen whose content is \"pass\" for the automatic test\n");
	igt_info("\t-o\t<id of the display>,<number of the mode>\tonly test specified mode on the specified display\n");
	igt_info("\t-f\t<clock MHz>,<hdisp>,<hsync-start>,<hsync-end>,<htotal>,\n");
	igt_info("\t\t<vdisp>,<vsync-start>,<vsync-end>,<vtotal>\n");
	igt_info("\t\ttest force mode\n");
	igt_info("\tDefault is to test all modes.\n");
	exit((opt != 'h') ? -1 : 0);
}
Esempio n. 15
0
static void
set_mode(struct connector *c)
{
	unsigned int fb_id = 0;
	struct igt_fb fb_info[2] = { };
	int j, test_mode_num, current_fb = 0, old_fb = -1;

	test_mode_num = 1;
	if (force_mode){
		memcpy( &c->mode, &force_timing, sizeof(force_timing));
		c->mode.vrefresh =(force_timing.clock*1e3)/(force_timing.htotal*force_timing.vtotal);
		c->mode_valid = 1;
		sprintf(c->mode.name, "%dx%d", force_timing.hdisplay, force_timing.vdisplay);
	} else if (test_all_modes)
		test_mode_num = c->connector->count_modes;

	for (j = 0; j < test_mode_num; j++) {

		if (test_all_modes)
			c->mode = c->connector->modes[j];

		/* set_mode() only tests 2D modes */
		if (c->mode.flags & DRM_MODE_FLAG_3D_MASK)
			continue;

		if (!c->mode_valid)
			continue;

		width = c->mode.hdisplay;
		height = c->mode.vdisplay;

		fb_id = igt_create_pattern_fb(drm_fd, width, height,
					      igt_bpp_depth_to_drm_format(bpp, depth),
					      tiling, &fb_info[current_fb]);
		paint_output_info(c, &fb_info[current_fb]);
		paint_color_key(&fb_info[current_fb]);

		igt_info("CRTC(%u):[%d]", c->crtc, j);
		kmstest_dump_mode(&c->mode);
		if (drmModeSetCrtc(drm_fd, c->crtc, fb_id, 0, 0,
				   &c->id, 1, &c->mode)) {
			igt_warn("failed to set mode (%dx%d@%dHz): %s\n", width, height, c->mode.vrefresh, strerror(errno));
			igt_remove_fb(drm_fd, &fb_info[current_fb]);
			continue;
		}

		if (old_fb != -1)
			igt_remove_fb(drm_fd, &fb_info[old_fb]);
		old_fb = current_fb;
		current_fb = 1 - current_fb;

		if (sleep_between_modes && test_all_modes && !qr_code)
			sleep(sleep_between_modes);

		if (do_dpms) {
			kmstest_set_connector_dpms(drm_fd, c->connector, do_dpms);
			sleep(sleep_between_modes);
			kmstest_set_connector_dpms(drm_fd, c->connector, DRM_MODE_DPMS_ON);
		}

		if (qr_code){
			set_single();
			pause();
		}
	}

	if (test_all_modes && old_fb != -1)
		igt_remove_fb(drm_fd, &fb_info[old_fb]);

	drmModeFreeEncoder(c->encoder);
	drmModeFreeConnector(c->connector);
}
Esempio n. 16
0
static int test_format(const char *test_name,
		       struct kmstest_connector_config *cconf,
		       drmModeModeInfo *mode, uint32_t format,
		       enum test_flags flags)
{
	int width;
	int height;
	struct igt_fb fb[2];
	char *mode_format_str;
	char *cconf_str;
	int ret;

	ret = asprintf(&mode_format_str, "%s @ %dHz / %s",
		 mode->name, mode->vrefresh, igt_format_str(format));
	igt_assert_lt(0, ret);
	ret = asprintf(&cconf_str, "pipe %s, encoder %s, connector %s",
		       kmstest_pipe_name(cconf->pipe),
		       kmstest_encoder_type_str(cconf->encoder->encoder_type),
		       kmstest_connector_type_str(cconf->connector->connector_type));
	igt_assert_lt(0, ret);

	igt_info("Beginning test %s with %s on %s\n",
		 test_name, mode_format_str, cconf_str);

	width = mode->hdisplay;
	height = mode->vdisplay;

	if (!igt_create_fb(drm_fd, width, height, format,
			   LOCAL_DRM_FORMAT_MOD_NONE, &fb[0]))
		goto err1;

	if (!igt_create_fb(drm_fd, width, height, format,
			   LOCAL_DRM_FORMAT_MOD_NONE,	&fb[1]))
		goto err2;

	if (drmModeSetCrtc(drm_fd, cconf->crtc->crtc_id, fb[0].fb_id,
				 0, 0, &cconf->connector->connector_id, 1,
				 mode))
		goto err2;
	do_or_die(drmModePageFlip(drm_fd, cconf->crtc->crtc_id, fb[0].fb_id,
				  0, NULL));
	sleep(2);

	if (flags & TEST_DIRECT_RENDER) {
		paint_fb(&fb[0], test_name, mode_format_str, cconf_str);
	} else if (flags & TEST_GPU_BLIT) {
		paint_fb(&fb[1], test_name, mode_format_str, cconf_str);
		gpu_blit(&fb[0], &fb[1]);
	}
	sleep(5);

	igt_info("Test %s with %s on %s: PASSED\n",
		 test_name, mode_format_str, cconf_str);
	free(mode_format_str);
	free(cconf_str);

	igt_remove_fb(drm_fd, &fb[1]);
	igt_remove_fb(drm_fd, &fb[0]);

	return 0;

err2:
	igt_remove_fb(drm_fd, &fb[0]);
err1:
	igt_info("Test %s with %s on %s: SKIPPED\n",
		 test_name, mode_format_str, cconf_str);
	free(mode_format_str);
	free(cconf_str);

	return -1;
}
Esempio n. 17
0
int main(int argc, char **argv)
{
	int c;
	int ret = 0;
	GIOChannel *stdinchannel;
	GMainLoop *mainloop;
	float force_clock;
	bool opt_dump_info = false;
	struct option long_opts[] = {
		{"list-subtests", 0, 0, SUBTEST_OPTS},
		{"run-subtest", 1, 0, SUBTEST_OPTS},
		{"help-description", 0, 0, HELP_DESCRIPTION},
		{"help", 0, 0, 'h'},
		{"yb", 0, 0, Yb_OPT},
		{"yf", 0, 0, Yf_OPT},
		{ 0, 0, 0, 0 }
	};

	igt_skip_on_simulation();

	enter_exec_path( argv );

	while ((c = getopt_long(argc, argv, optstr, long_opts, NULL)) != -1) {
		switch (c) {
		case '3':
			test_stereo_modes = 1;
			break;
		case 'i':
			opt_dump_info = true;
			break;
		case 'a':
			test_all_modes = 1;
			break;
		case 'f':
			force_mode = 1;
			if(sscanf(optarg,"%f,%hu,%hu,%hu,%hu,%hu,%hu,%hu,%hu",
				&force_clock,&force_timing.hdisplay, &force_timing.hsync_start,&force_timing.hsync_end,&force_timing.htotal,
				&force_timing.vdisplay, &force_timing.vsync_start, &force_timing.vsync_end, &force_timing.vtotal)!= 9)
				usage(argv[0], c);
			force_timing.clock = force_clock*1000;

			break;
		case 's':
			sleep_between_modes = atoi(optarg);
			break;
		case 'j':
			do_dpms = atoi(optarg);
			if (do_dpms == 0)
				do_dpms = DRM_MODE_DPMS_OFF;
			break;
		case 'd':
			depth = atoi(optarg);
			igt_info("using depth %d\n", depth);
			break;
		case 'p':
			if (sscanf(optarg, "%d,%d,%d,%d,%d,%d", &plane_width,
				   &plane_height, &crtc_x, &crtc_y,
				   &crtc_w, &crtc_h) != 6)
				usage(argv[0], c);
			test_plane = 1;
			break;
		case 'm':
			test_preferred_mode = 1;
			break;
		case 't':
			tiling = LOCAL_I915_FORMAT_MOD_X_TILED;
			break;
		case 'y':
		case Yb_OPT:
			tiling = LOCAL_I915_FORMAT_MOD_Y_TILED;
			break;
		case Yf_OPT:
			tiling = LOCAL_I915_FORMAT_MOD_Yf_TILED;
			break;
		case 'r':
			qr_code = 1;
			break;
		case 'o':
			sscanf(optarg, "%d,%d", &specified_disp_id, &specified_mode_num);
			break;
		case SUBTEST_OPTS:
			/* invalid subtest options */
			exit(IGT_EXIT_INVALID);
			break;
		case HELP_DESCRIPTION:
			igt_info("Tests display functionality.");
			exit(0);
			break;
		default:
			/* fall through */
		case 'h':
			usage(argv[0], c);
			break;
		}
	}

	set_termio_mode();

	if (depth <= 8)
		bpp = 8;
	else if (depth <= 16)
		bpp = 16;
	else if (depth <= 32)
		bpp = 32;

	if (!test_all_modes && !force_mode && !test_preferred_mode &&
	    specified_mode_num == -1 && !test_stereo_modes)
		test_all_modes = 1;

	drm_fd = drm_open_driver(DRIVER_INTEL);

	if (test_stereo_modes &&
	    drmSetClientCap(drm_fd, DRM_CLIENT_CAP_STEREO_3D, 1) < 0) {
		igt_warn("DRM_CLIENT_CAP_STEREO_3D failed\n");
		goto out_close;
	}

	if (opt_dump_info) {
		dump_info();
		goto out_close;
	}

	kmstest_set_vt_graphics_mode();

	mainloop = g_main_loop_new(NULL, FALSE);
	if (!mainloop) {
		igt_warn("failed to create glib mainloop\n");
		ret = -1;
		goto out_close;
	}

	if (!testdisplay_setup_hotplug()) {
		igt_warn("failed to initialize hotplug support\n");
		goto out_mainloop;
	}

	stdinchannel = g_io_channel_unix_new(0);
	if (!stdinchannel) {
		igt_warn("failed to create stdin GIO channel\n");
		goto out_hotplug;
	}

	ret = g_io_add_watch(stdinchannel, G_IO_IN | G_IO_ERR, input_event,
			     NULL);
	if (ret < 0) {
		igt_warn("failed to add watch on stdin GIO channel\n");
		goto out_stdio;
	}

	ret = 0;

	if (!update_display()) {
		ret = 1;
		goto out_stdio;
	}

	if (test_all_modes)
		goto out_stdio;

	g_main_loop_run(mainloop);

out_stdio:
	g_io_channel_shutdown(stdinchannel, TRUE, NULL);
out_hotplug:
	testdisplay_cleanup_hotplug();
out_mainloop:
	g_main_loop_unref(mainloop);
out_close:
	close(drm_fd);

	igt_assert_eq(ret, 0);

	igt_exit();
}
Esempio n. 18
0
static void big_exec(int fd, uint32_t handle, int ring)
{
	struct drm_i915_gem_execbuffer2 execbuf;
	struct drm_i915_gem_exec_object2 *gem_exec;
	uint32_t ctx_id1, ctx_id2;
	int num_buffers = gem_available_aperture_size(fd) / 4096;
	int i;

	/* Make sure we only fill half of RAM with gem objects. */
	igt_require(intel_get_total_ram_mb() * 1024 / 2 > num_buffers * 4);

	gem_exec = calloc(num_buffers + 1, sizeof(*gem_exec));
	igt_assert(gem_exec);
	memset(gem_exec, 0, (num_buffers + 1) * sizeof(*gem_exec));


	ctx_id1 = gem_context_create(fd);
	ctx_id2 = gem_context_create(fd);

	gem_exec[0].handle = handle;


	execbuf.buffers_ptr = (uintptr_t)gem_exec;
	execbuf.buffer_count = num_buffers + 1;
	execbuf.batch_start_offset = 0;
	execbuf.batch_len = 8;
	execbuf.cliprects_ptr = 0;
	execbuf.num_cliprects = 0;
	execbuf.DR1 = 0;
	execbuf.DR4 = 0;
	execbuf.flags = ring;
	execbuf.rsvd2 = 0;

	execbuf.buffer_count = 1;
	i915_execbuffer2_set_context_id(execbuf, ctx_id1);
	do_ioctl(fd, DRM_IOCTL_I915_GEM_EXECBUFFER2, &execbuf);

	for (i = 0; i < num_buffers; i++) {
		uint32_t tmp_handle = gem_create(fd, 4096);

		gem_exec[i].handle = tmp_handle;
	}
	gem_exec[i].handle = handle;
	execbuf.buffer_count = i + 1;

	/* figure out how many buffers we can exactly fit */
	while (drmIoctl(fd, DRM_IOCTL_I915_GEM_EXECBUFFER2,
			&execbuf) != 0) {
		i--;
		gem_close(fd, gem_exec[i].handle);
		gem_exec[i].handle = handle;
		execbuf.buffer_count--;
		igt_info("trying buffer count %i\n", i - 1);
	}

	igt_info("reduced buffer count to %i from %i\n",
	       i - 1, num_buffers);

	/* double check that it works */
	do_ioctl(fd, DRM_IOCTL_I915_GEM_EXECBUFFER2, &execbuf);

	i915_execbuffer2_set_context_id(execbuf, ctx_id2);
	do_ioctl(fd, DRM_IOCTL_I915_GEM_EXECBUFFER2, &execbuf);
	gem_sync(fd, handle);
}
static void
store_dword_loop(int fd, int ring, int count, int divider)
{
	int i, val = 0;
	struct drm_i915_gem_execbuffer2 execbuf;
	struct drm_i915_gem_exec_object2 obj[2];
	struct drm_i915_gem_relocation_entry reloc[divider];
	uint32_t handle[divider];
	uint32_t *batch[divider];
	uint32_t *target;
	int gen = intel_gen(devid);

	memset(obj, 0, sizeof(obj));
	obj[0].handle = gem_create(fd, 4096);
	target = mmap_coherent(fd, obj[0].handle, 4096);

	memset(reloc, 0, sizeof(reloc));
	for (i = 0; i < divider; i++) {
		uint32_t *b;

		handle[i] = gem_create(fd, 4096);
		batch[i] = mmap_coherent(fd, handle[i], 4096);
		gem_set_domain(fd, handle[i], coherent_domain, coherent_domain);

		b = batch[i];
		*b++ = MI_STORE_DWORD_IMM;
		*b++ = 0;
		*b++ = 0;
		*b++ = 0;
		*b++ = MI_BATCH_BUFFER_END;

		reloc[i].target_handle = obj[0].handle;
		reloc[i].offset = 4;
		if (gen < 8)
			reloc[i].offset += 4;
		reloc[i].read_domains = I915_GEM_DOMAIN_INSTRUCTION;
		reloc[i].write_domain = I915_GEM_DOMAIN_INSTRUCTION;
		obj[1].relocation_count = 1;
	}

	memset(&execbuf, 0, sizeof(execbuf));
	execbuf.buffers_ptr = (uintptr_t)obj;
	execbuf.buffer_count = 2;
	execbuf.flags = ring;

	igt_info("running storedw loop on render with stall every %i batch\n", divider);

	for (i = 0; i < SLOW_QUICK(0x2000, 0x10); i++) {
		int j = i % divider;

		gem_set_domain(fd, handle[j], coherent_domain, coherent_domain);
		batch[j][3] = val;
		obj[1].handle = handle[j];
		obj[1].relocs_ptr = (uintptr_t)&reloc[j];
		gem_execbuf(fd, &execbuf);

		if (j == 0) {
			gem_set_domain(fd, obj[0].handle, coherent_domain, 0);
			igt_assert_f(*target == val,
				     "%d: value mismatch: stored 0x%08x, expected 0x%08x\n",
				     i, *target, val);
		}

		val++;
	}

	gem_set_domain(fd, obj[0].handle, coherent_domain, 0);
	igt_info("completed %d writes successfully, current value: 0x%08x\n",
		 i, target[0]);

	munmap(target, 4096);
	gem_close(fd, obj[0].handle);
	for (i = 0; i < divider; ++i) {
		munmap(batch[i], 4096);
		gem_close(fd, handle[i]);
	}
}
int main(int argc, char **argv)
{
	uint32_t *handle, *start_val;
	uint32_t start = 0;
	int i, fd, count;

	igt_simple_init(argc, argv);

	fd = drm_open_any();

	igt_require(IS_GEN3(intel_get_drm_devid(fd)));

	count = 0;
	if (argc > 1)
		count = atoi(argv[1]);
	if (count == 0)
		count = 3 * gem_aperture_size(fd) / (1024*1024) / 2;
	igt_info("Using %d 1MiB buffers\n", count);

	handle = malloc(sizeof(uint32_t)*count*2);
	start_val = handle + count;

	for (i = 0; i < count; i++) {
		handle[i] = create_bo(fd, start);
		start_val[i] = start;
		start += 1024 * 1024 / 4;
	}

	igt_info("Verifying initialisation...\n");
	for (i = 0; i < count; i++)
		check_bo(fd, handle[i], start_val[i]);

	igt_info("Cyclic blits, forward...\n");
	for (i = 0; i < count * 4; i++) {
		int src = i % count;
		int dst = (i + 1) % count;

		copy(fd, handle[dst], handle[src]);
		start_val[dst] = start_val[src];
	}
	for (i = 0; i < count; i++)
		check_bo(fd, handle[i], start_val[i]);

	igt_info("Cyclic blits, backward...\n");
	for (i = 0; i < count * 4; i++) {
		int src = (i + 1) % count;
		int dst = i % count;

		copy(fd, handle[dst], handle[src]);
		start_val[dst] = start_val[src];
	}
	for (i = 0; i < count; i++)
		check_bo(fd, handle[i], start_val[i]);

	igt_info("Random blits...\n");
	for (i = 0; i < count * 4; i++) {
		int src = random() % count;
		int dst = random() % count;

		if (src == dst)
			continue;

		copy(fd, handle[dst], handle[src]);
		start_val[dst] = start_val[src];
	}
	for (i = 0; i < count; i++)
		check_bo(fd, handle[i], start_val[i]);

	igt_exit();
}
Esempio n. 21
0
int main(int argc, char **argv)
{
	struct timeval start, end;
	uint8_t *buf;
	uint32_t handle;
	int size = OBJECT_SIZE;
	int loop, i, tiling;
	int fd;

	igt_simple_init(argc, argv);

	igt_skip_on_simulation();

	if (argc > 1)
		size = atoi(argv[1]);
	if (size == 0) {
		igt_warn("Invalid object size specified\n");
		return 1;
	}

	buf = malloc(size);
	memset(buf, 0, size);
	fd = drm_open_driver(DRIVER_INTEL);

	handle = gem_create(fd, size);
	igt_assert(handle);

	for (tiling = I915_TILING_NONE; tiling <= I915_TILING_Y; tiling++) {
		if (tiling != I915_TILING_NONE) {
			igt_info("\nSetting tiling mode to %s\n",
				 tiling == I915_TILING_X ? "X" : "Y");
			gem_set_tiling(fd, handle, tiling, 512);
		}

		if (tiling == I915_TILING_NONE) {
			gem_set_domain(fd, handle,
				       I915_GEM_DOMAIN_CPU,
				       I915_GEM_DOMAIN_CPU);

			{
				uint32_t *base = gem_mmap__cpu(fd, handle, 0, size, PROT_READ | PROT_WRITE);
				volatile uint32_t *ptr = base;
				int x = 0;

				for (i = 0; i < size/sizeof(*ptr); i++)
					x += ptr[i];

				/* force overtly clever gcc to actually compute x */
				ptr[0] = x;

				munmap(base, size);

				/* mmap read */
				gettimeofday(&start, NULL);
				for (loop = 0; loop < 1000; loop++) {
					base = gem_mmap__cpu(fd, handle, 0,
							     size,
							     PROT_READ | PROT_WRITE);
					ptr = base;
					x = 0;

					for (i = 0; i < size/sizeof(*ptr); i++)
						x += ptr[i];

					/* force overtly clever gcc to actually compute x */
					ptr[0] = x;

					munmap(base, size);
				}
				gettimeofday(&end, NULL);
				igt_info("Time to read %dk through a CPU map:		%7.3fµs\n",
					 size/1024, elapsed(&start, &end, loop));

				/* mmap write */
				gettimeofday(&start, NULL);
				for (loop = 0; loop < 1000; loop++) {
					base = gem_mmap__cpu(fd, handle, 0,
							     size,
							     PROT_READ | PROT_WRITE);
					ptr = base;

					for (i = 0; i < size/sizeof(*ptr); i++)
						ptr[i] = i;

					munmap(base, size);
				}
				gettimeofday(&end, NULL);
				igt_info("Time to write %dk through a CPU map:		%7.3fµs\n",
					 size/1024, elapsed(&start, &end, loop));

				gettimeofday(&start, NULL);
				for (loop = 0; loop < 1000; loop++) {
					base = gem_mmap__cpu(fd, handle, 0,
							     size,
							     PROT_READ | PROT_WRITE);
					memset(base, 0, size);
					munmap(base, size);
				}
				gettimeofday(&end, NULL);
				igt_info("Time to clear %dk through a CPU map:		%7.3fµs\n",
					 size/1024, elapsed(&start, &end, loop));

				gettimeofday(&start, NULL);
				base = gem_mmap__cpu(fd, handle, 0, size,
						     PROT_READ | PROT_WRITE);
				for (loop = 0; loop < 1000; loop++)
					memset(base, 0, size);
				munmap(base, size);
				gettimeofday(&end, NULL);
				igt_info("Time to clear %dk through a cached CPU map:	%7.3fµs\n",
					 size/1024, elapsed(&start, &end, loop));
			}

			/* CPU pwrite */
			gettimeofday(&start, NULL);
			for (loop = 0; loop < 1000; loop++)
				gem_write(fd, handle, 0, buf, size);
			gettimeofday(&end, NULL);
			igt_info("Time to pwrite %dk through the CPU:		%7.3fµs\n",
				 size/1024, elapsed(&start, &end, loop));

			/* CPU pread */
			gettimeofday(&start, NULL);
			for (loop = 0; loop < 1000; loop++)
				gem_read(fd, handle, 0, buf, size);
			gettimeofday(&end, NULL);
			igt_info("Time to pread %dk through the CPU:		%7.3fµs\n",
				 size/1024, elapsed(&start, &end, loop));
		}

		/* prefault into gtt */
		{
			uint32_t *base = gem_mmap__gtt(fd, handle, size, PROT_READ | PROT_WRITE);
			volatile uint32_t *ptr = base;
			int x = 0;

			for (i = 0; i < size/sizeof(*ptr); i++)
				x += ptr[i];

			/* force overtly clever gcc to actually compute x */
			ptr[0] = x;

			munmap(base, size);
		}
		/* mmap read */
		gettimeofday(&start, NULL);
		for (loop = 0; loop < 1000; loop++) {
			uint32_t *base = gem_mmap__gtt(fd, handle, size, PROT_READ | PROT_WRITE);
			volatile uint32_t *ptr = base;
			int x = 0;

			for (i = 0; i < size/sizeof(*ptr); i++)
				x += ptr[i];

			/* force overtly clever gcc to actually compute x */
			ptr[0] = x;

			munmap(base, size);
		}
		gettimeofday(&end, NULL);
		igt_info("Time to read %dk through a GTT map:		%7.3fµs\n",
			 size/1024, elapsed(&start, &end, loop));

		if (gem_mmap__has_wc(fd)) {
			gettimeofday(&start, NULL);
			for (loop = 0; loop < 1000; loop++) {
				uint32_t *base = gem_mmap__wc(fd, handle, 0, size, PROT_READ | PROT_WRITE);
				volatile uint32_t *ptr = base;
				int x = 0;

				for (i = 0; i < size/sizeof(*ptr); i++)
					x += ptr[i];

				/* force overtly clever gcc to actually compute x */
				ptr[0] = x;

				munmap(base, size);
			}
			gettimeofday(&end, NULL);
			igt_info("Time to read %dk through a WC map:		%7.3fµs\n",
					size/1024, elapsed(&start, &end, loop));
		}


		/* mmap write */
		gettimeofday(&start, NULL);
		for (loop = 0; loop < 1000; loop++) {
			uint32_t *base = gem_mmap__gtt(fd, handle, size, PROT_READ | PROT_WRITE);
			volatile uint32_t *ptr = base;

			for (i = 0; i < size/sizeof(*ptr); i++)
				ptr[i] = i;

			munmap(base, size);
		}
		gettimeofday(&end, NULL);
		igt_info("Time to write %dk through a GTT map:		%7.3fµs\n",
			 size/1024, elapsed(&start, &end, loop));

		if (gem_mmap__has_wc(fd)) {
			/* mmap write */
			gettimeofday(&start, NULL);
			for (loop = 0; loop < 1000; loop++) {
				uint32_t *base = gem_mmap__wc(fd, handle, 0, size, PROT_READ | PROT_WRITE);
				volatile uint32_t *ptr = base;

				for (i = 0; i < size/sizeof(*ptr); i++)
					ptr[i] = i;

				munmap(base, size);
			}
			gettimeofday(&end, NULL);
			igt_info("Time to write %dk through a WC map:		%7.3fµs\n",
					size/1024, elapsed(&start, &end, loop));
		}

		/* mmap clear */
		gettimeofday(&start, NULL);
		for (loop = 0; loop < 1000; loop++) {
			uint32_t *base = gem_mmap__gtt(fd, handle, size, PROT_READ | PROT_WRITE);
			memset(base, 0, size);
			munmap(base, size);
		}
		gettimeofday(&end, NULL);
		igt_info("Time to clear %dk through a GTT map:		%7.3fµs\n",
			 size/1024, elapsed(&start, &end, loop));

		if (gem_mmap__has_wc(fd)) {
			/* mmap clear */
			gettimeofday(&start, NULL);
			for (loop = 0; loop < 1000; loop++) {
				uint32_t *base = gem_mmap__wc(fd, handle, 0, size, PROT_READ | PROT_WRITE);
				memset(base, 0, size);
				munmap(base, size);
			}
			gettimeofday(&end, NULL);
			igt_info("Time to clear %dk through a WC map:		%7.3fµs\n",
					size/1024, elapsed(&start, &end, loop));
		}

		gettimeofday(&start, NULL);{
			uint32_t *base = gem_mmap__gtt(fd, handle, size, PROT_READ | PROT_WRITE);
			for (loop = 0; loop < 1000; loop++)
				memset(base, 0, size);
			munmap(base, size);
		} gettimeofday(&end, NULL);
		igt_info("Time to clear %dk through a cached GTT map:	%7.3fµs\n",
			 size/1024, elapsed(&start, &end, loop));

		if (gem_mmap__has_wc(fd)) {
			gettimeofday(&start, NULL);{
				uint32_t *base = gem_mmap__wc(fd, handle, 0, size, PROT_READ | PROT_WRITE);
				for (loop = 0; loop < 1000; loop++)
					memset(base, 0, size);
				munmap(base, size);
			} gettimeofday(&end, NULL);
			igt_info("Time to clear %dk through a cached WC map:	%7.3fµs\n",
					size/1024, elapsed(&start, &end, loop));
		}

		/* mmap read */
		gettimeofday(&start, NULL);
		for (loop = 0; loop < 1000; loop++) {
			uint32_t *base = gem_mmap__gtt(fd, handle, size, PROT_READ | PROT_WRITE);
			volatile uint32_t *ptr = base;
			int x = 0;

			for (i = 0; i < size/sizeof(*ptr); i++)
				x += ptr[i];

			/* force overtly clever gcc to actually compute x */
			ptr[0] = x;

			munmap(base, size);
		}
		gettimeofday(&end, NULL);
		igt_info("Time to read %dk (again) through a GTT map:	%7.3fµs\n",
			 size/1024, elapsed(&start, &end, loop));

		if (tiling == I915_TILING_NONE) {
			/* GTT pwrite */
			gettimeofday(&start, NULL);
			for (loop = 0; loop < 1000; loop++)
				gem_write(fd, handle, 0, buf, size);
			gettimeofday(&end, NULL);
			igt_info("Time to pwrite %dk through the GTT:		%7.3fµs\n",
				 size/1024, elapsed(&start, &end, loop));

			/* GTT pread */
			gettimeofday(&start, NULL);
			for (loop = 0; loop < 1000; loop++)
				gem_read(fd, handle, 0, buf, size);
			gettimeofday(&end, NULL);
			igt_info("Time to pread %dk through the GTT:		%7.3fµs\n",
				 size/1024, elapsed(&start, &end, loop));

			/* GTT pwrite, including clflush */
			gettimeofday(&start, NULL);
			for (loop = 0; loop < 1000; loop++) {
				gem_write(fd, handle, 0, buf, size);
				gem_sync(fd, handle);
			}
			gettimeofday(&end, NULL);
			igt_info("Time to pwrite %dk through the GTT (clflush):	%7.3fµs\n",
				 size/1024, elapsed(&start, &end, loop));

			/* GTT pread, including clflush */
			gettimeofday(&start, NULL);
			for (loop = 0; loop < 1000; loop++) {
				gem_sync(fd, handle);
				gem_read(fd, handle, 0, buf, size);
			}
			gettimeofday(&end, NULL);
			igt_info("Time to pread %dk through the GTT (clflush):	%7.3fµs\n",
				 size/1024, elapsed(&start, &end, loop));

			/* partial writes */
			igt_info("Now partial writes.\n");
			size /= 4;

			/* partial GTT pwrite, including clflush */
			gettimeofday(&start, NULL);
			for (loop = 0; loop < 1000; loop++) {
				gem_write(fd, handle, 0, buf, size);
				gem_sync(fd, handle);
			}
			gettimeofday(&end, NULL);
			igt_info("Time to pwrite %dk through the GTT (clflush):	%7.3fµs\n",
			       size/1024, elapsed(&start, &end, loop));

			/* partial GTT pread, including clflush */
			gettimeofday(&start, NULL);
			for (loop = 0; loop < 1000; loop++) {
				gem_sync(fd, handle);
				gem_read(fd, handle, 0, buf, size);
			}
			gettimeofday(&end, NULL);
			igt_info("Time to pread %dk through the GTT (clflush):	%7.3fµs\n",
			       size/1024, elapsed(&start, &end, loop));

			size *= 4;
		}
	}

	gem_close(fd, handle);
	close(fd);

	igt_exit();
}
Esempio n. 22
0
/* Simulates SNA behaviour using negative self-relocations for
 * STATE_BASE_ADDRESS command packets. If they wrap around (to values greater
 * than the total size of the GTT), the GPU will hang.
 * See https://bugs.freedesktop.org/show_bug.cgi?id=78533
 */
static int negative_reloc(int fd, unsigned flags)
{
	struct drm_i915_gem_execbuffer2 execbuf;
	struct drm_i915_gem_exec_object2 gem_exec[2];
	struct drm_i915_gem_relocation_entry gem_reloc[1000];
	uint64_t gtt_max = get_page_table_size(fd);
	uint32_t buf[1024] = {MI_BATCH_BUFFER_END};
	int i;

#define BIAS (256*1024)

	igt_require(intel_gen(intel_get_drm_devid(fd)) >= 7);

	memset(gem_exec, 0, sizeof(gem_exec));
	gem_exec[0].handle = gem_create(fd, 4096);
	gem_write(fd, gem_exec[0].handle, 0, buf, 8);

	gem_reloc[0].offset = 1024;
	gem_reloc[0].delta = 0;
	gem_reloc[0].target_handle = gem_exec[0].handle;
	gem_reloc[0].read_domains = I915_GEM_DOMAIN_COMMAND;

	gem_exec[1].handle = gem_create(fd, 4096);
	gem_write(fd, gem_exec[1].handle, 0, buf, 8);
	gem_exec[1].relocation_count = 1;
	gem_exec[1].relocs_ptr = (uintptr_t)gem_reloc;

	memset(&execbuf, 0, sizeof(execbuf));
	execbuf.buffers_ptr = (uintptr_t)gem_exec;
	execbuf.buffer_count = 2;
	execbuf.batch_len = 8;

	do_or_die(drmIoctl(fd,
			   DRM_IOCTL_I915_GEM_EXECBUFFER2,
			   &execbuf));
	gem_close(fd, gem_exec[1].handle);

	igt_info("Found offset %lld for 4k batch\n", (long long)gem_exec[0].offset);
	/*
	 * Ideally we'd like to be able to control where the kernel is going to
	 * place the buffer. We don't SKIP here because it causes the test
	 * to "randomly" flip-flop between the SKIP and PASS states.
	 */
	if (gem_exec[0].offset < BIAS) {
		igt_info("Offset is below BIAS, not testing anything\n");
		return 0;
	}

	memset(gem_reloc, 0, sizeof(gem_reloc));
	for (i = 0; i < sizeof(gem_reloc)/sizeof(gem_reloc[0]); i++) {
		gem_reloc[i].offset = 8 + 4*i;
		gem_reloc[i].delta = -BIAS*i/1024;
		gem_reloc[i].target_handle = flags & USE_LUT ? 0 : gem_exec[0].handle;
		gem_reloc[i].read_domains = I915_GEM_DOMAIN_COMMAND;
	}

	gem_exec[0].relocation_count = sizeof(gem_reloc)/sizeof(gem_reloc[0]);
	gem_exec[0].relocs_ptr = (uintptr_t)gem_reloc;

	execbuf.buffer_count = 1;
	execbuf.flags = flags & USE_LUT;
	do_or_die(drmIoctl(fd,
			   DRM_IOCTL_I915_GEM_EXECBUFFER2,
			   &execbuf));

	igt_info("Batch is now at offset %lld\n", (long long)gem_exec[0].offset);

	gem_read(fd, gem_exec[0].handle, 0, buf, sizeof(buf));
	gem_close(fd, gem_exec[0].handle);

	for (i = 0; i < sizeof(gem_reloc)/sizeof(gem_reloc[0]); i++)
		igt_assert(buf[2 + i] < gtt_max);

	return 0;
}
static void test_suspend_resume(void)
{
    igt_info("Suspending the device ...\n");
    igt_system_suspend_autoresume();
}
Esempio n. 24
0
static void render_timeout(int fd)
{
	drm_intel_bufmgr *bufmgr;
	struct intel_batchbuffer *batch;
	int64_t timeout = ENOUGH_WORK_IN_SECONDS * NSEC_PER_SEC;
	int64_t negative_timeout = -1;
	int ret;
	const bool do_signals = true; /* signals will seem to make the operation
				       * use less process CPU time */
	bool done = false;
	int i, iter = 1;

	igt_skip_on_simulation();

	bufmgr = drm_intel_bufmgr_gem_init(fd, 4096);
	drm_intel_bufmgr_gem_enable_reuse(bufmgr);
	batch = intel_batchbuffer_alloc(bufmgr, intel_get_drm_devid(fd));

	dst = drm_intel_bo_alloc(bufmgr, "dst", BUF_SIZE, 4096);
	dst2 = drm_intel_bo_alloc(bufmgr, "dst2", BUF_SIZE, 4096);

	igt_skip_on_f(gem_bo_wait_timeout(fd, dst->handle, &timeout) == -EINVAL,
		      "kernel doesn't support wait_timeout, skipping test\n");
	timeout = ENOUGH_WORK_IN_SECONDS * NSEC_PER_SEC;

	/* Figure out a rough number of fills required to consume 1 second of
	 * GPU work.
	 */
	do {
		struct timespec start, end;
		long diff;

#ifndef CLOCK_MONOTONIC_RAW
#define CLOCK_MONOTONIC_RAW CLOCK_MONOTONIC
#endif

		igt_assert(clock_gettime(CLOCK_MONOTONIC_RAW, &start) == 0);
		for (i = 0; i < iter; i++)
			blt_color_fill(batch, dst, BUF_PAGES);
		intel_batchbuffer_flush(batch);
		drm_intel_bo_wait_rendering(dst);
		igt_assert(clock_gettime(CLOCK_MONOTONIC_RAW, &end) == 0);

		diff = do_time_diff(&end, &start);
		igt_assert(diff >= 0);

		if ((diff / MSEC_PER_SEC) > ENOUGH_WORK_IN_SECONDS)
			done = true;
		else
			iter <<= 1;
	} while (!done && iter < 1000000);

	igt_assert_lt(iter, 1000000);

	igt_info("%d iters is enough work\n", iter);
	gem_quiescent_gpu(fd);
	if (do_signals)
		igt_fork_signal_helper();

	/* We should be able to do half as much work in the same amount of time,
	 * but because we might schedule almost twice as much as required, we
	 * might accidentally time out. Hence add some fudge. */
	for (i = 0; i < iter/3; i++)
		blt_color_fill(batch, dst2, BUF_PAGES);

	intel_batchbuffer_flush(batch);
	igt_assert(gem_bo_busy(fd, dst2->handle) == true);

	igt_assert_eq(gem_bo_wait_timeout(fd, dst2->handle, &timeout), 0);
	igt_assert(gem_bo_busy(fd, dst2->handle) == false);
	igt_assert_neq(timeout, 0);
	if (timeout ==  (ENOUGH_WORK_IN_SECONDS * NSEC_PER_SEC))
		igt_info("Buffer was already done!\n");
	else {
		igt_info("Finished with %" PRIu64 " time remaining\n", timeout);
	}

	/* check that polling with timeout=0 works. */
	timeout = 0;
	igt_assert_eq(gem_bo_wait_timeout(fd, dst2->handle, &timeout), 0);
	igt_assert_eq(timeout, 0);

	/* Now check that we correctly time out, twice the auto-tune load should
	 * be good enough. */
	timeout = ENOUGH_WORK_IN_SECONDS * NSEC_PER_SEC;
	for (i = 0; i < iter*2; i++)
		blt_color_fill(batch, dst2, BUF_PAGES);

	intel_batchbuffer_flush(batch);

	ret = gem_bo_wait_timeout(fd, dst2->handle, &timeout);
	igt_assert_eq(ret, -ETIME);
	igt_assert_eq(timeout, 0);
	igt_assert(gem_bo_busy(fd, dst2->handle) == true);

	/* check that polling with timeout=0 works. */
	timeout = 0;
	igt_assert_eq(gem_bo_wait_timeout(fd, dst2->handle, &timeout), -ETIME);
	igt_assert_eq(timeout, 0);


	/* Now check that we can pass negative (infinite) timeouts. */
	negative_timeout = -1;
	for (i = 0; i < iter; i++)
		blt_color_fill(batch, dst2, BUF_PAGES);

	intel_batchbuffer_flush(batch);

	igt_assert_eq(gem_bo_wait_timeout(fd, dst2->handle, &negative_timeout), 0);
	igt_assert_eq(negative_timeout, -1); /* infinity always remains */
	igt_assert(gem_bo_busy(fd, dst2->handle) == false);

	if (do_signals)
		igt_stop_signal_helper();
	drm_intel_bo_unreference(dst2);
	drm_intel_bo_unreference(dst);
	intel_batchbuffer_free(batch);
	drm_intel_bufmgr_destroy(bufmgr);
}