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