diff --git a/lib/igt_core.c b/lib/igt_core.c
index 8a1a249..6dd7af3 100644
--- a/lib/igt_core.c
+++ b/lib/igt_core.c
@@ -501,7 +501,8 @@ static int common_init(int *argc, char **argv,
 		       const char *extra_short_opts,
 		       struct option *extra_long_opts,
 		       const char *help_str,
-		       igt_opt_handler_t extra_opt_handler)
+		       igt_opt_handler_t extra_opt_handler,
+		       void *handler_data)
 {
 	int c, option_index = 0, i, x;
 	static struct option long_options[] = {
@@ -627,7 +628,7 @@ static int common_init(int *argc, char **argv,
 			ret = -2;
 			goto out;
 		default:
-			ret = extra_opt_handler(c, option_index);
+			ret = extra_opt_handler(c, option_index, handler_data);
 			if (ret)
 				goto out;
 		}
@@ -683,6 +684,7 @@ out:
  * @extra_long_opts: getopt_long() compliant list with additional long options
  * @help_str: help string for the additional options
  * @extra_opt_handler: handler for the additional options
+ * @handler_data: user data given to @extra_opt_handler when invoked
  *
  * This function handles the subtest related cmdline options and allows an
  * arbitrary set of additional options. This is useful for tests which have
@@ -698,13 +700,14 @@ int igt_subtest_init_parse_opts(int *argc, char **argv,
 				const char *extra_short_opts,
 				struct option *extra_long_opts,
 				const char *help_str,
-				igt_opt_handler_t extra_opt_handler)
+				igt_opt_handler_t extra_opt_handler,
+				void *handler_data)
 {
 	int ret;
 
 	test_with_subtests = true;
 	ret = common_init(argc, argv, extra_short_opts, extra_long_opts,
-			  help_str, extra_opt_handler);
+			  help_str, extra_opt_handler, handler_data);
 
 	return ret;
 }
@@ -719,6 +722,7 @@ enum igt_log_level igt_log_level = IGT_LOG_INFO;
  * @extra_long_opts: getopt_long() compliant list with additional long options
  * @help_str: help string for the additional options
  * @extra_opt_handler: handler for the additional options
+ * @handler_data: user data given to @extra_opt_handler when invoked
  *
  * This initializes a simple test without any support for subtests and allows
  * an arbitrary set of additional options.
@@ -727,10 +731,11 @@ void igt_simple_init_parse_opts(int *argc, char **argv,
 				const char *extra_short_opts,
 				struct option *extra_long_opts,
 				const char *help_str,
-				igt_opt_handler_t extra_opt_handler)
+				igt_opt_handler_t extra_opt_handler,
+				void *handler_data)
 {
 	common_init(argc, argv, extra_short_opts, extra_long_opts, help_str,
-		    extra_opt_handler);
+		    extra_opt_handler, handler_data);
 }
 
 /*
diff --git a/lib/igt_core.h b/lib/igt_core.h
index b15d9ff..d79f6d2 100644
--- a/lib/igt_core.h
+++ b/lib/igt_core.h
@@ -113,7 +113,7 @@ void __igt_fixture_end(void) __attribute__((noreturn));
 
 /* subtest infrastructure */
 jmp_buf igt_subtest_jmpbuf;
-typedef int (*igt_opt_handler_t)(int opt, int opt_index);
+typedef int (*igt_opt_handler_t)(int opt, int opt_index, void *data);
 #ifndef __GTK_DOC_IGNORE__ /* gtkdoc wants to document this forward decl */
 struct option;
 #endif
@@ -121,7 +121,8 @@ int igt_subtest_init_parse_opts(int *argc, char **argv,
 				const char *extra_short_opts,
 				struct option *extra_long_opts,
 				const char *help_str,
-				igt_opt_handler_t extra_opt_handler);
+				igt_opt_handler_t extra_opt_handler,
+				void *handler_data);
 
 
 /**
@@ -137,7 +138,8 @@ int igt_subtest_init_parse_opts(int *argc, char **argv,
  * #igt_main block instead of stitching the test's main() function together
  * manually.
  */
-#define igt_subtest_init(argc, argv) igt_subtest_init_parse_opts(&argc, argv, NULL, NULL, NULL, NULL);
+#define igt_subtest_init(argc, argv) \
+	igt_subtest_init_parse_opts(&argc, argv, NULL, NULL, NULL, NULL, NULL);
 
 bool __igt_run_subtest(const char *subtest_name);
 #define __igt_tokencat2(x, y) x ## y
@@ -202,7 +204,8 @@ bool igt_only_list_subtests(void);
 #define igt_main \
 	static void igt_tokencat(__real_main, __LINE__)(void); \
 	int main(int argc, char **argv) { \
-		igt_subtest_init_parse_opts(&argc, argv, NULL, NULL, NULL, NULL); \
+		igt_subtest_init_parse_opts(&argc, argv, NULL, NULL, NULL, \
+					    NULL, NULL); \
 		igt_tokencat(__real_main, __LINE__)(); \
 		igt_exit(); \
 	} \
@@ -214,7 +217,8 @@ void igt_simple_init_parse_opts(int *argc, char **argv,
 				const char *extra_short_opts,
 				struct option *extra_long_opts,
 				const char *help_str,
-				igt_opt_handler_t extra_opt_handler);
+				igt_opt_handler_t extra_opt_handler,
+				void *handler_data);
 
 /**
  * igt_simple_init:
@@ -227,7 +231,8 @@ void igt_simple_init_parse_opts(int *argc, char **argv,
  * #igt_simple_main block instead of stitching the test's main() function together
  * manually.
  */
-#define igt_simple_init(argc, argv) igt_simple_init_parse_opts(&argc, argv, NULL, NULL, NULL, NULL);
+#define igt_simple_init(argc, argv) \
+	igt_simple_init_parse_opts(&argc, argv, NULL, NULL, NULL, NULL, NULL);
 
 /**
  * igt_simple_main:
@@ -239,7 +244,8 @@ void igt_simple_init_parse_opts(int *argc, char **argv,
 #define igt_simple_main \
 	static void igt_tokencat(__real_main, __LINE__)(void); \
 	int main(int argc, char **argv) { \
-		igt_simple_init_parse_opts(&argc, argv, NULL, NULL, NULL, NULL); \
+		igt_simple_init_parse_opts(&argc, argv, NULL, NULL, NULL, \
+					   NULL, NULL); \
 		igt_tokencat(__real_main, __LINE__)(); \
 		igt_exit(); \
 	} \
diff --git a/tests/gem_ctx_basic.c b/tests/gem_ctx_basic.c
index 9e9d925..9aad7f8 100644
--- a/tests/gem_ctx_basic.c
+++ b/tests/gem_ctx_basic.c
@@ -120,7 +120,7 @@ static void *work(void *arg)
 	pthread_exit(NULL);
 }
 
-static int opt_handler(int opt, int opt_index)
+static int opt_handler(int opt, int opt_index, void *data)
 {
 	switch (opt) {
 		case 'i':
@@ -145,7 +145,7 @@ int main(int argc, char *argv[])
 	int i;
 
 	igt_simple_init_parse_opts(&argc, argv, "i:c:n:mu", NULL, NULL,
-				   opt_handler);
+				   opt_handler, NULL);
 
 	fd = drm_open_any_render();
 	devid = intel_get_drm_devid(fd);
diff --git a/tests/gem_render_copy.c b/tests/gem_render_copy.c
index df1ac88..ee37f8a 100644
--- a/tests/gem_render_copy.c
+++ b/tests/gem_render_copy.c
@@ -120,7 +120,7 @@ scratch_buf_check(data_t *data, struct igt_buf *buf, int x, int y,
 		     color, val, x, y);
 }
 
-static int opt_handler(int opt, int opt_index)
+static int opt_handler(int opt, int opt_index, void *data)
 {
 	if (opt == 'd') {
 		opt_dump_png = true;
@@ -141,7 +141,8 @@ int main(int argc, char **argv)
 	igt_render_copyfunc_t render_copy = NULL;
 	int opt_dump_aub = igt_aub_dump_enabled();
 
-	igt_simple_init_parse_opts(&argc, argv, "da", NULL, NULL, opt_handler);
+	igt_simple_init_parse_opts(&argc, argv, "da", NULL, NULL,
+				   opt_handler, NULL);
 
 	igt_fixture {
 		data.drm_fd = drm_open_any_render();
diff --git a/tests/gem_seqno_wrap.c b/tests/gem_seqno_wrap.c
index 43da450..d7d56ed 100644
--- a/tests/gem_seqno_wrap.c
+++ b/tests/gem_seqno_wrap.c
@@ -434,7 +434,7 @@ static void background_run_once(void)
 		sleep(3);
 }
 
-static int parse_options(int opt, int opt_index)
+static int parse_options(int opt, int opt_index, void *data)
 {
 	switch(opt) {
 		case 'b':
@@ -504,7 +504,7 @@ int main(int argc, char **argv)
 	options.buffers = 10;
 
 	igt_simple_init_parse_opts(&argc, argv, "n:bvt:dp:ri:", long_options,
-				   help, parse_options);
+				   help, parse_options, NULL);
 
 	card_index = drm_get_card();
 
diff --git a/tests/gem_stress.c b/tests/gem_stress.c
index 804684f..472263d 100644
--- a/tests/gem_stress.c
+++ b/tests/gem_stress.c
@@ -624,7 +624,7 @@ static void sanitize_tiles_per_buf(void)
 		options.tiles_per_buf = options.scratch_buf_size / TILE_BYTES(options.tile_size);
 }
 
-static int parse_options(int opt, int opt_index)
+static int parse_options(int opt, int opt_index, void *data)
 {
 	int tmp;
 
@@ -855,7 +855,7 @@ int main(int argc, char **argv)
 	options.check_render_cpyfn = 0;
 
 	igt_simple_init_parse_opts(&argc, argv,"ds:g:c:t:rbuxmo:fp:",
-				   long_options, NULL, parse_options);
+				   long_options, NULL, parse_options, NULL);
 
 	drm_fd = drm_open_any();
 	devid = intel_get_drm_devid(drm_fd);
diff --git a/tests/kms_psr_sink_crc.c b/tests/kms_psr_sink_crc.c
index f5f95f4..099391b 100644
--- a/tests/kms_psr_sink_crc.c
+++ b/tests/kms_psr_sink_crc.c
@@ -537,7 +537,7 @@ static void dpms_off_on(data_t data)
 				   DRM_MODE_DPMS_ON);
 }
 
-static int opt_handler(int opt, int opt_index)
+static int opt_handler(int opt, int opt_index, void *data)
 {
 	switch (opt) {
 	case 'n':
@@ -562,7 +562,7 @@ int main(int argc, char *argv[])
 	enum operations op;
 
 	igt_subtest_init_parse_opts(&argc, argv, "", long_options,
-				    help_str, opt_handler);
+				    help_str, opt_handler, NULL);
 	igt_skip_on_simulation();
 
 	igt_fixture {
diff --git a/tests/kms_setmode.c b/tests/kms_setmode.c
index 5520dcc..82769ab 100644
--- a/tests/kms_setmode.c
+++ b/tests/kms_setmode.c
@@ -662,7 +662,7 @@ static void run_test(const struct test_config *tconf)
 		test_combinations(tconf, connector_num);
 }
 
-static int opt_handler(int opt, int opt_index)
+static int opt_handler(int opt, int opt_index, void *data)
 {
 	switch (opt) {
 	case 'd':
@@ -700,7 +700,7 @@ int main(int argc, char **argv)
 	int ret;
 
 	ret = igt_subtest_init_parse_opts(&argc, argv, "dt:", NULL, help_str,
-					  opt_handler);
+					  opt_handler, NULL);
 	if (ret < 0)
 		return ret == -1 ? 0 : ret;
 
diff --git a/tests/pm_rpm.c b/tests/pm_rpm.c
index 1a93fe8..a1f4013 100644
--- a/tests/pm_rpm.c
+++ b/tests/pm_rpm.c
@@ -1791,7 +1791,7 @@ static void fences_subtest(bool dpms)
 int rounds = 40;
 bool stay = false;
 
-static int opt_handler(int opt, int opt_index)
+static int opt_handler(int opt, int opt_index, void *data)
 {
 	switch (opt) {
 	case 'q':
@@ -1819,7 +1819,7 @@ int main(int argc, char *argv[])
 	};
 
 	igt_subtest_init_parse_opts(&argc, argv, "", long_options,
-				    help_str, opt_handler);
+				    help_str, opt_handler, NULL);
 
 	/* Skip instead of failing in case the machine is not prepared to reach
 	 * PC8+. We don't want bug reports from cases where the machine is just
