• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright © 2016 Intel Corporation
3  *
4  * Permission is hereby granted, free of charge, to any person obtaining a
5  * copy of this software and associated documentation files (the "Software"),
6  * to deal in the Software without restriction, including without limitation
7  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8  * and/or sell copies of the Software, and to permit persons to whom the
9  * Software is furnished to do so, subject to the following conditions:
10  *
11  * The above copyright notice and this permission notice (including the next
12  * paragraph) shall be included in all copies or substantial portions of the
13  * Software.
14  *
15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
21  * IN THE SOFTWARE.
22  */
23 
24 #include <signal.h>
25 #include <errno.h>
26 
27 #include "igt_aux.h"
28 #include "igt_core.h"
29 #include "igt_kmod.h"
30 #include "igt_sysfs.h"
31 
32 /**
33  * SECTION:igt_kmod
34  * @short_description: Wrappers around libkmod for module loading/unloading
35  * @title: kmod
36  * @include: igt.h
37  *
38  * This library provides helpers to load/unload module driver.
39  *
40  * Note on loading/reloading:
41  *
42  * Loading/unload/reloading the driver requires that resources to /dev/dri to
43  * be released (closed). A potential mistake would be to submit commands to the
44  * GPU by having a fd returned by @drm_open_driver, which is closed by atexit
45  * signal handler so reloading/unloading the driver will fail if performed
46  * afterwards. One possible solution to this issue is to use
47  * @__drm_open_driver() or use @igt_set_module_param() to set module parameters
48  * dynamically.
49  */
50 
squelch(void * data,int priority,const char * file,int line,const char * fn,const char * format,va_list args)51 static void squelch(void *data, int priority,
52 		    const char *file, int line, const char *fn,
53 		    const char *format, va_list args)
54 {
55 }
56 
kmod_ctx(void)57 static struct kmod_ctx *kmod_ctx(void)
58 {
59 	static struct kmod_ctx *ctx;
60 	const char **config_paths = NULL;
61 	char *config_paths_str;
62 	char *dirname;
63 
64 	if (ctx)
65 		goto out;
66 
67 	dirname = getenv("IGT_KMOD_DIRNAME");
68 	if (dirname)
69 		igt_debug("kmod dirname = %s\n", dirname);
70 
71 	config_paths_str = getenv("IGT_KMOD_CONFIG_PATHS");
72 	if (config_paths_str)
73 		igt_debug("kmod config paths = %s\n", config_paths_str);
74 
75 	if (config_paths_str) {
76 		unsigned count = !!strlen(config_paths_str);
77 		unsigned i;
78 		char* p;
79 
80 		p = config_paths_str;
81 		while ((p = strchr(p, ':'))) p++, count++;
82 
83 
84 		config_paths = malloc(sizeof(*config_paths) * (count + 1));
85 		igt_assert(config_paths != NULL);
86 
87 		p = config_paths_str;
88 		for (i = 0; i < count; ++i) {
89 			igt_assert(p != NULL);
90 			config_paths[i] = p;
91 
92 			if ((p = strchr(p, ':')))
93 				*p++ = '\0';
94 		}
95 		config_paths[i] = NULL;
96 	}
97 
98 	ctx = kmod_new(dirname, config_paths);
99 	igt_assert(ctx != NULL);
100 
101 	free(config_paths);
102 
103 	kmod_set_log_fn(ctx, squelch, NULL);
104 out:
105 	return ctx;
106 }
107 
108 /**
109  * igt_kmod_is_loaded:
110  * @mod_name: The name of the module.
111  *
112  * Returns: True in case the module has been found or false otherwise.
113  *
114  * Function to check the existance of module @mod_name in list of loaded kernel
115  * modules.
116  *
117  */
118 bool
igt_kmod_is_loaded(const char * mod_name)119 igt_kmod_is_loaded(const char *mod_name)
120 {
121 	struct kmod_ctx *ctx = kmod_ctx();
122 	struct kmod_list *mod, *list;
123 	bool ret = false;
124 
125 	if (kmod_module_new_from_loaded(ctx, &list) < 0)
126 		goto out;
127 
128 	kmod_list_foreach(mod, list) {
129 		struct kmod_module *kmod = kmod_module_get_module(mod);
130 		const char *kmod_name = kmod_module_get_name(kmod);
131 
132 		if (!strcmp(kmod_name, mod_name)) {
133 			kmod_module_unref(kmod);
134 			ret = true;
135 			break;
136 		}
137 		kmod_module_unref(kmod);
138 	}
139 	kmod_module_unref_list(list);
140 out:
141 	return ret;
142 }
143 
modprobe(struct kmod_module * kmod,const char * options)144 static int modprobe(struct kmod_module *kmod, const char *options)
145 {
146 	unsigned int flags;
147 
148 	flags = 0;
149 	if (options) /* force a fresh load to set the new options */
150 		flags |= KMOD_PROBE_FAIL_ON_LOADED;
151 
152 	return kmod_module_probe_insert_module(kmod, flags, options,
153 					       NULL, NULL, NULL);
154 }
155 
156 /**
157  * igt_kmod_load:
158  * @mod_name: The name of the module
159  * @opts: Parameters for the module. NULL in case no parameters
160  * are to be passed, or a '\0' terminated string otherwise.
161  *
162  * Returns: 0 in case of success or -errno in case the module could not
163  * be loaded.
164  *
165  * This function loads a kernel module using the name specified in @mod_name.
166  *
167  * @Note: This functions doesn't automatically resolve other module
168  * dependencies so make make sure you load the dependencies module(s) before
169  * this one.
170  */
171 int
igt_kmod_load(const char * mod_name,const char * opts)172 igt_kmod_load(const char *mod_name, const char *opts)
173 {
174 	struct kmod_ctx *ctx = kmod_ctx();
175 	struct kmod_module *kmod;
176 	int err = 0;
177 
178 	err = kmod_module_new_from_name(ctx, mod_name, &kmod);
179 	if (err < 0)
180 		goto out;
181 
182 	err = modprobe(kmod, opts);
183 	if (err < 0) {
184 		switch (err) {
185 		case -EEXIST:
186 			igt_debug("Module %s already inserted\n",
187 				  kmod_module_get_name(kmod));
188 			break;
189 		case -ENOENT:
190 			igt_debug("Unknown symbol in module %s or "
191 				  "unknown parameter\n",
192 				  kmod_module_get_name(kmod));
193 			break;
194 		default:
195 			igt_debug("Could not insert %s (%s)\n",
196 				  kmod_module_get_name(kmod), strerror(-err));
197 			break;
198 		}
199 	}
200 out:
201 	kmod_module_unref(kmod);
202 	return err < 0 ? err : 0;
203 }
204 
205 
206 /**
207  * igt_kmod_unload:
208  * @mod_name: Module name.
209  * @flags: flags are passed directly to libkmod and can be:
210  * KMOD_REMOVE_FORCE or KMOD_REMOVE_NOWAIT.
211  *
212  * Returns: 0 in case of success or -errno otherwise.
213  *
214  * Removes the module @mod_name.
215  *
216  */
217 int
igt_kmod_unload(const char * mod_name,unsigned int flags)218 igt_kmod_unload(const char *mod_name, unsigned int flags)
219 {
220 	struct kmod_ctx *ctx = kmod_ctx();
221 	struct kmod_module *kmod;
222 	int err;
223 
224 	err = kmod_module_new_from_name(ctx, mod_name, &kmod);
225 	if (err < 0) {
226 		igt_debug("Could not use module %s (%s)\n", mod_name,
227 			  strerror(-err));
228 		goto out;
229 	}
230 
231 	err = kmod_module_remove_module(kmod, flags);
232 	if (err < 0) {
233 		igt_debug("Could not remove module %s (%s)\n", mod_name,
234 			  strerror(-err));
235 	}
236 
237 out:
238 	kmod_module_unref(kmod);
239 	return err < 0 ? err : 0;
240 }
241 
242 /**
243  *
244  * igt_kmod_list_loaded: List all modules currently loaded.
245  *
246  */
247 void
igt_kmod_list_loaded(void)248 igt_kmod_list_loaded(void)
249 {
250 	struct kmod_ctx *ctx = kmod_ctx();
251 	struct kmod_list *module, *list;
252 
253 	if (kmod_module_new_from_loaded(ctx, &list) < 0)
254 		return;
255 
256 	igt_info("Module\t\t      Used by\n");
257 
258 	kmod_list_foreach(module, list) {
259 		struct kmod_module *kmod = kmod_module_get_module(module);
260 		struct kmod_list *module_deps, *module_deps_list;
261 
262 		igt_info("%-24s", kmod_module_get_name(kmod));
263 		module_deps_list = kmod_module_get_holders(kmod);
264 		if (module_deps_list) {
265 
266 			kmod_list_foreach(module_deps, module_deps_list) {
267 				struct kmod_module *kmod_dep;
268 
269 				kmod_dep = kmod_module_get_module(module_deps);
270 				igt_info("%s", kmod_module_get_name(kmod_dep));
271 
272 				if (kmod_list_next(module_deps_list, module_deps))
273 					igt_info(",");
274 
275 				kmod_module_unref(kmod_dep);
276 			}
277 		}
278 		kmod_module_unref_list(module_deps_list);
279 
280 		igt_info("\n");
281 		kmod_module_unref(kmod);
282 	}
283 
284 	kmod_module_unref_list(list);
285 }
286 
287 /**
288  * igt_i915_driver_load:
289  * @opts: options to pass to i915 driver
290  *
291  * Loads the i915 driver and its dependencies.
292  *
293  */
294 int
igt_i915_driver_load(const char * opts)295 igt_i915_driver_load(const char *opts)
296 {
297 	if (opts)
298 		igt_info("Reloading i915 with %s\n\n", opts);
299 
300 	if (igt_kmod_load("i915", opts)) {
301 		igt_warn("Could not load i915\n");
302 		return IGT_EXIT_FAILURE;
303 	}
304 
305 	bind_fbcon(true);
306 	igt_kmod_load("snd_hda_intel", NULL);
307 
308 	return IGT_EXIT_SUCCESS;
309 }
310 
311 /**
312  * igt_i915_driver_unload:
313  *
314  * Unloads the i915 driver and its dependencies.
315  *
316  */
317 int
igt_i915_driver_unload(void)318 igt_i915_driver_unload(void)
319 {
320 	/* unbind vt */
321 	bind_fbcon(false);
322 
323 	if (igt_kmod_is_loaded("snd_hda_intel")) {
324 		igt_terminate_process(SIGTERM, "alsactl");
325 
326 		/* unbind snd_hda_intel */
327 		kick_snd_hda_intel();
328 
329 		if (igt_kmod_unload("snd_hda_intel", 0)) {
330 			igt_warn("Could not unload snd_hda_intel\n");
331 			igt_kmod_list_loaded();
332 			igt_lsof("/dev/snd");
333 			return IGT_EXIT_FAILURE;
334 		}
335 	}
336 
337 	if (igt_kmod_is_loaded("snd_hdmi_lpe_audio")) {
338 		igt_terminate_process(SIGTERM, "alsactl");
339 
340 		if (igt_kmod_unload("snd_hdmi_lpe_audio", 0)) {
341 			igt_warn("Could not unload snd_hdmi_lpe_audio\n");
342 			igt_kmod_list_loaded();
343 			igt_lsof("/dev/snd");
344 			return IGT_EXIT_FAILURE;
345 		}
346 	}
347 
348 	/* gen5 */
349 	if (igt_kmod_is_loaded("intel_ips"))
350 		igt_kmod_unload("intel_ips", 0);
351 
352 	if (igt_kmod_is_loaded("i915")) {
353 		if (igt_kmod_unload("i915", 0)) {
354 			igt_warn("Could not unload i915\n");
355 			igt_kmod_list_loaded();
356 			igt_lsof("/dev/dri");
357 			return IGT_EXIT_SKIP;
358 		}
359 	}
360 
361 	if (igt_kmod_is_loaded("intel-gtt"))
362 		igt_kmod_unload("intel-gtt", 0);
363 
364 	igt_kmod_unload("drm_kms_helper", 0);
365 	igt_kmod_unload("drm", 0);
366 
367 	if (igt_kmod_is_loaded("i915")) {
368 		igt_warn("i915.ko still loaded!\n");
369 		return IGT_EXIT_FAILURE;
370 	}
371 
372 	return IGT_EXIT_SUCCESS;
373 }
374 
kmsg_dump(int fd)375 static void kmsg_dump(int fd)
376 {
377 	FILE *file;
378 
379 	file = NULL;
380 	if (fd != -1)
381 		file = fdopen(fd, "r");
382 	if (file) {
383 		size_t len = 0;
384 		char *line = NULL;
385 
386 		while (getline(&line, &len, file) != -1) {
387 			char *start = strchr(line, ':');
388 			if (start)
389 				igt_warn("%s", start + 2);
390 		}
391 
392 		free(line);
393 		fclose(file);
394 	} else {
395 		igt_warn("Unable to retrieve kernel log (from /dev/kmsg)\n");
396 	}
397 }
398 
tests_add(struct igt_kselftest_list * tl,struct igt_list * list)399 static void tests_add(struct igt_kselftest_list *tl, struct igt_list *list)
400 {
401 	struct igt_kselftest_list *pos;
402 
403 	igt_list_for_each(pos, list, link)
404 		if (pos->number > tl->number)
405 			break;
406 
407 	igt_list_add_tail(&tl->link, &pos->link);
408 }
409 
igt_kselftest_get_tests(struct kmod_module * kmod,const char * filter,struct igt_list * tests)410 void igt_kselftest_get_tests(struct kmod_module *kmod,
411 			     const char *filter,
412 			     struct igt_list *tests)
413 {
414 	const char *param_prefix = "igt__";
415 	const int prefix_len = strlen(param_prefix);
416 	struct kmod_list *d, *pre;
417 	struct igt_kselftest_list *tl;
418 
419 	pre = NULL;
420 	if (!kmod_module_get_info(kmod, &pre))
421 		return;
422 
423 	kmod_list_foreach(d, pre) {
424 		const char *key, *val;
425 		char *colon;
426 		int offset;
427 
428 		key = kmod_module_info_get_key(d);
429 		if (strcmp(key, "parmtype"))
430 			continue;
431 
432 		val = kmod_module_info_get_value(d);
433 		if (!val || strncmp(val, param_prefix, prefix_len))
434 			continue;
435 
436 		offset = strlen(val) + 1;
437 		tl = malloc(sizeof(*tl) + offset);
438 		if (!tl)
439 			continue;
440 
441 		memcpy(tl->param, val, offset);
442 		colon = strchr(tl->param, ':');
443 		*colon = '\0';
444 
445 		tl->number = 0;
446 		tl->name = tl->param + prefix_len;
447 		if (sscanf(tl->name, "%u__%n",
448 			   &tl->number, &offset) == 1)
449 			tl->name += offset;
450 
451 		if (filter && strncmp(tl->name, filter, strlen(filter))) {
452 			free(tl);
453 			continue;
454 		}
455 
456 		tests_add(tl, tests);
457 	}
458 	kmod_module_info_free_list(pre);
459 }
460 
open_parameters(const char * module_name)461 static int open_parameters(const char *module_name)
462 {
463 	char path[256];
464 
465 	snprintf(path, sizeof(path), "/sys/module/%s/parameters", module_name);
466 	return open(path, O_RDONLY);
467 }
468 
igt_kselftest_init(struct igt_kselftest * tst,const char * module_name)469 int igt_kselftest_init(struct igt_kselftest *tst,
470 		       const char *module_name)
471 {
472 	int err;
473 
474 	memset(tst, 0, sizeof(*tst));
475 
476 	tst->module_name = strdup(module_name);
477 	if (!tst->module_name)
478 		return 1;
479 
480 	tst->kmsg = -1;
481 
482 	err = kmod_module_new_from_name(kmod_ctx(), module_name, &tst->kmod);
483 	if (err)
484 		return err;
485 
486 	return 0;
487 }
488 
igt_kselftest_begin(struct igt_kselftest * tst)489 int igt_kselftest_begin(struct igt_kselftest *tst)
490 {
491 	int err;
492 
493 	if (strcmp(tst->module_name, "i915") == 0)
494 		igt_i915_driver_unload();
495 
496 	err = kmod_module_remove_module(tst->kmod, KMOD_REMOVE_FORCE);
497 	igt_require(err == 0 || err == -ENOENT);
498 
499 	tst->kmsg = open("/dev/kmsg", O_RDONLY | O_NONBLOCK);
500 
501 	return 0;
502 }
503 
igt_kselftest_execute(struct igt_kselftest * tst,struct igt_kselftest_list * tl,const char * options,const char * result)504 int igt_kselftest_execute(struct igt_kselftest *tst,
505 			  struct igt_kselftest_list *tl,
506 			  const char *options,
507 			  const char *result)
508 {
509 	char buf[1024];
510 	int err;
511 
512 	lseek(tst->kmsg, 0, SEEK_END);
513 
514 	snprintf(buf, sizeof(buf), "%s=1 %s", tl->param, options ?: "");
515 
516 	err = modprobe(tst->kmod, buf);
517 	if (err == 0 && result) {
518 		int dir = open_parameters(tst->module_name);
519 		igt_sysfs_scanf(dir, result, "%d", &err);
520 		close(dir);
521 	}
522 	if (err == -ENOTTY) /* special case */
523 		err = 0;
524 	if (err)
525 		kmsg_dump(tst->kmsg);
526 
527 	kmod_module_remove_module(tst->kmod, 0);
528 
529 	errno = 0;
530 	igt_assert_f(err == 0,
531 		     "kselftest \"%s %s\" failed: %s [%d]\n",
532 		     tst->module_name, buf, strerror(-err), -err);
533 
534 	return err;
535 }
536 
igt_kselftest_end(struct igt_kselftest * tst)537 void igt_kselftest_end(struct igt_kselftest *tst)
538 {
539 	kmod_module_remove_module(tst->kmod, KMOD_REMOVE_FORCE);
540 	close(tst->kmsg);
541 }
542 
igt_kselftest_fini(struct igt_kselftest * tst)543 void igt_kselftest_fini(struct igt_kselftest *tst)
544 {
545 	free(tst->module_name);
546 	kmod_module_unref(tst->kmod);
547 }
548 
igt_kselftests(const char * module_name,const char * options,const char * result,const char * filter)549 void igt_kselftests(const char *module_name,
550 		    const char *options,
551 		    const char *result,
552 		    const char *filter)
553 {
554 	struct igt_kselftest tst;
555 	IGT_LIST(tests);
556 	struct igt_kselftest_list *tl, *tn;
557 
558 	if (igt_kselftest_init(&tst, module_name) != 0)
559 		return;
560 
561 	igt_fixture
562 		igt_require(igt_kselftest_begin(&tst) == 0);
563 
564 	igt_kselftest_get_tests(tst.kmod, filter, &tests);
565 	igt_list_for_each_safe(tl, tn, &tests, link) {
566 		igt_subtest_f("%s", tl->name)
567 			igt_kselftest_execute(&tst, tl, options, result);
568 		free(tl);
569 	}
570 
571 	igt_fixture {
572 		igt_kselftest_end(&tst);
573 		igt_require(!igt_list_empty(&tests));
574 	}
575 
576 	igt_kselftest_fini(&tst);
577 }
578