diff mbox

[i-g-t,1/3,v2] lib/{igt_sysfs, igt_aux}: Make available to other users kick_fbcon() (unbind_fbcon()), and added helpers to igt_aux.

Message ID 20161025204438.2864-2-marius.c.vlad@intel.com (mailing list archive)
State New, archived
Headers show

Commit Message

Marius Vlad Oct. 25, 2016, 8:44 p.m. UTC
Previously under unbind_fbcon(), to disable/enable framebuffer console.

lib/igt_aux: Added helpers to help convert sh scripts to C version. libkmod
and procps interface.

v2:
- Renamed libkmod helpers (Chris Wilson)
- Removed SIGTERM/SIGKILL case where we repeatedly tried to terminate the
process: just call kill(2) once (Chris Wilson)
- Removed redundant check in igt_kmod_unload(), igt_module_in_use() (Chris
Wilson)
- Pass flags to igt_kmod_unload() from the caller (Chris Wilson)
- Removed useless function igt_kill() which acts just as kill(2) (Chris
Wilson)

Signed-off-by: Marius Vlad <marius.c.vlad@intel.com>
---
 configure.ac    |   2 +
 lib/Makefile.am |   2 +
 lib/igt_aux.c   | 185 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 lib/igt_aux.h   |   6 ++
 lib/igt_gvt.c   |  43 +------------
 lib/igt_sysfs.c |  54 +++++++++++++++++
 lib/igt_sysfs.h |   2 +
 7 files changed, 253 insertions(+), 41 deletions(-)

Comments

Chris Wilson Oct. 25, 2016, 8:50 p.m. UTC | #1
On Tue, Oct 25, 2016 at 11:44:36PM +0300, Marius Vlad wrote:
> +int
> +igt_pkill(int sig, const char *comm)
> +{
> +	int err = 0;
> +	PROCTAB *proc;
> +	proc_t *proc_info;
> +
> +	proc = openproc(PROC_FILLCOM | PROC_FILLSTAT | PROC_FILLARG);
> +	igt_assert(proc != NULL);
> +
> +	while ((proc_info = readproc(proc, NULL))) {
> +		if (!strncasecmp(proc_info->cmd, comm, sizeof(proc_info->cmd))) {
> +
> +			if (kill(proc_info->tid, sig) < 0)
> +				err = -1;

err = -errno;

(we like to keep kernel conventions where nicely applicable)

> +
> +			freeproc(proc_info);
> +			break;
> +		}
> +		freeproc(proc_info);
> +	}
> +
> +	closeproc(proc);
> +	return err;
> +}

> +int

bool

> +igt_kmod_is_loaded(const char *mod_name)
> +{
> +	struct kmod_list *mod, *list;
> +	struct kmod_ctx *ctx;
> +	int ret = 0;
> +
> +	ctx = kmod_new(NULL, NULL);
> +	igt_assert(ctx != NULL);
> +
> +	if (kmod_module_new_from_loaded(ctx, &list) < 0) {
> +		kmod_unref(ctx);
> +		return -1;

Too confusing! :)

	if (kmod_module_new_from_loaded(ctx, &list) < 0)
		goto out;

> +	}
> +
> +	kmod_list_foreach(mod, list) {
> +		struct kmod_module *kmod = kmod_module_get_module(mod);
> +		const char *kmod_name = kmod_module_get_name(kmod);
> +
> +		if (!strncasecmp(kmod_name, mod_name, strlen(kmod_name))) {

strncasecmp? So what happens if we load i915 and I915_bpo ?

> +			kmod_module_unref(kmod);
> +			ret = 1;
> +			break;
> +		}
> +		kmod_module_unref(kmod);
> +	}
> +
> +	kmod_module_unref_list(list);

out:
> +	kmod_unref(ctx);
> +
> +	return ret;
> +}

> +int
> +igt_kmod_load(const char *mod_name, const char *opts)
> +{
> +	struct kmod_ctx *ctx;
> +	struct kmod_module *kmod;
> +	int err = 0;
> +
> +	ctx = kmod_new(NULL, NULL);
> +	igt_assert(ctx != NULL);
> +
> +
> +	err = kmod_module_new_from_name(ctx, mod_name, &kmod);
> +	if (err < 0) {
> +		goto out;
> +	}
> +
> +	err = kmod_module_insert_module(kmod, 0, opts);
> +	if (err < 0) {
> +		switch (err) {
> +		case -EEXIST:
> +			igt_info("Module %s already inserted\n",
> +				 kmod_module_get_name(kmod));
> +			err = -1;

Don't reduce the information, just return err; (as elsewhere)

Not sure if igt_info() makes sense, it will be noise for those expecting
and handling the error.

> +			break;
> +		case -ENOENT:
> +			igt_info("Unknown symbol in module %s or "
> +				 "unknown parameter\n",
> +				 kmod_module_get_name(kmod));
> +			err = -1;
> +			break;
> +		default:
> +			igt_info("Could not insert %s (%s)\n",
> +				 kmod_module_get_name(kmod), strerror(-err));
> +			err = -1;
> +			break;
> +		}
> +	}
> +out:
> +	kmod_module_unref(kmod);
> +	kmod_unref(ctx);
> +
> +	return err;
> +}
> +
diff mbox

Patch

diff --git a/configure.ac b/configure.ac
index 735cfd5..2c6e49d 100644
--- a/configure.ac
+++ b/configure.ac
@@ -121,6 +121,8 @@  AC_SUBST(ASSEMBLER_WARN_CFLAGS)
 
 PKG_CHECK_MODULES(DRM, [libdrm])
 PKG_CHECK_MODULES(PCIACCESS, [pciaccess >= 0.10])
+PKG_CHECK_MODULES(KMOD, [libkmod])
+PKG_CHECK_MODULES(PROCPS, [libprocps])
 
 case "$target_cpu" in
 	x86*|i?86)
diff --git a/lib/Makefile.am b/lib/Makefile.am
index 4c0893d..e1737bd 100644
--- a/lib/Makefile.am
+++ b/lib/Makefile.am
@@ -34,6 +34,8 @@  AM_CFLAGS += $(CAIRO_CFLAGS)
 libintel_tools_la_LIBADD = \
 	$(DRM_LIBS) \
 	$(PCIACCESS_LIBS) \
+	$(PROCPS_LIBS) \
+	$(KMOD_LIBS) \
 	$(CAIRO_LIBS) \
 	$(LIBUDEV_LIBS) \
 	$(LIBUNWIND_LIBS) \
diff --git a/lib/igt_aux.c b/lib/igt_aux.c
index 421f6d4..9e94315 100644
--- a/lib/igt_aux.c
+++ b/lib/igt_aux.c
@@ -51,6 +51,9 @@ 
 #include <termios.h>
 #include <assert.h>
 
+#include <proc/readproc.h>
+#include <libkmod.h>
+
 #include "drmtest.h"
 #include "i915_drm.h"
 #include "intel_chipset.h"
@@ -1193,6 +1196,188 @@  void igt_set_module_param_int(const char *name, int val)
 	igt_set_module_param(name, str);
 }
 
+/**
+ * igt_pkill:
+ * @sig: Signal to send
+ * @name: Name of process in the form found in /proc/pid/comm (limited to 15
+ * chars)
+ * @returns: 0 in case the process is not found running or the signal has been
+ * sent successfully or -1 otherwise.
+ *
+ * This function sends the signal @sig for a process found in process table
+ * with name @comm.
+ */
+int
+igt_pkill(int sig, const char *comm)
+{
+	int err = 0;
+	PROCTAB *proc;
+	proc_t *proc_info;
+
+	proc = openproc(PROC_FILLCOM | PROC_FILLSTAT | PROC_FILLARG);
+	igt_assert(proc != NULL);
+
+	while ((proc_info = readproc(proc, NULL))) {
+		if (!strncasecmp(proc_info->cmd, comm, sizeof(proc_info->cmd))) {
+
+			if (kill(proc_info->tid, sig) < 0)
+				err = -1;
+
+			freeproc(proc_info);
+			break;
+		}
+		freeproc(proc_info);
+	}
+
+	closeproc(proc);
+	return err;
+}
+
+/**
+ * igt_kmod_is_loaded:
+ * @mod_name: The name of the module.
+ * @returns: True in case the module has been found or false otherwise.
+ *
+ *
+ * Function to check the existance of module @mod_name in list of loaded kernel
+ * modules.
+ *
+ */
+int
+igt_kmod_is_loaded(const char *mod_name)
+{
+	struct kmod_list *mod, *list;
+	struct kmod_ctx *ctx;
+	int ret = 0;
+
+	ctx = kmod_new(NULL, NULL);
+	igt_assert(ctx != NULL);
+
+	if (kmod_module_new_from_loaded(ctx, &list) < 0) {
+		kmod_unref(ctx);
+		return -1;
+	}
+
+	kmod_list_foreach(mod, list) {
+		struct kmod_module *kmod = kmod_module_get_module(mod);
+		const char *kmod_name = kmod_module_get_name(kmod);
+
+		if (!strncasecmp(kmod_name, mod_name, strlen(kmod_name))) {
+			kmod_module_unref(kmod);
+			ret = 1;
+			break;
+		}
+		kmod_module_unref(kmod);
+	}
+
+	kmod_module_unref_list(list);
+	kmod_unref(ctx);
+
+	return ret;
+}
+
+/**
+ * igt_kmod_load:
+ * @mod_name: The name of the module
+ * @opts: Parameters for the module. NULL in case no parameters
+ * are to be passed, or a '\0' terminated string otherwise.
+ * @returns: 0 in case of success or -1 in case the module could not
+ * be loaded.
+ *
+ * This function loads a kernel module using the name specified in @mod_name.
+ *
+ * @Note: This functions doesn't automatically resolve other module
+ * dependencies so make make sure you load the dependencies module(s) before
+ * this one.
+ */
+int
+igt_kmod_load(const char *mod_name, const char *opts)
+{
+	struct kmod_ctx *ctx;
+	struct kmod_module *kmod;
+	int err = 0;
+
+	ctx = kmod_new(NULL, NULL);
+	igt_assert(ctx != NULL);
+
+
+	err = kmod_module_new_from_name(ctx, mod_name, &kmod);
+	if (err < 0) {
+		goto out;
+	}
+
+	err = kmod_module_insert_module(kmod, 0, opts);
+	if (err < 0) {
+		switch (err) {
+		case -EEXIST:
+			igt_info("Module %s already inserted\n",
+				 kmod_module_get_name(kmod));
+			err = -1;
+			break;
+		case -ENOENT:
+			igt_info("Unknown symbol in module %s or "
+				 "unknown parameter\n",
+				 kmod_module_get_name(kmod));
+			err = -1;
+			break;
+		default:
+			igt_info("Could not insert %s (%s)\n",
+				 kmod_module_get_name(kmod), strerror(-err));
+			err = -1;
+			break;
+		}
+	}
+out:
+	kmod_module_unref(kmod);
+	kmod_unref(ctx);
+
+	return err;
+}
+
+
+/**
+ * igt_kmod_unload:
+ * @mod_name: Module name.
+ * @flags: flags are passed directly to libkmod and can be:
+ * KMOD_REMOVE_FORCE or KMOD_REMOVE_NOWAIT.
+ * @returns: 0 in case of success or -1 otherwise.
+ *
+ * Removes the module @mod_name.
+ *
+ */
+int
+igt_kmod_unload(const char *mod_name, unsigned int flags)
+{
+	struct kmod_ctx *ctx;
+	struct kmod_module *kmod;
+	int err;
+
+	ctx = kmod_new(NULL, NULL);
+	igt_assert(ctx != NULL);
+
+	err = kmod_module_new_from_name(ctx, mod_name, &kmod);
+	if (err < 0) {
+		igt_info("Could not use module %s (%s)\n", mod_name,
+				strerror(-err));
+		err = -1;
+		goto out;
+	}
+
+	err = kmod_module_remove_module(kmod, flags);
+	if (err < 0) {
+		igt_info("Could not remove module %s (%s)\n", mod_name,
+				strerror(-err));
+		err = -1;
+	}
+
+out:
+	kmod_module_unref(kmod);
+	kmod_unref(ctx);
+
+	return err;
+}
+
+
 static struct igt_siglatency {
 	timer_t timer;
 	struct timespec target;
diff --git a/lib/igt_aux.h b/lib/igt_aux.h
index d30196b..6dd9bb3 100644
--- a/lib/igt_aux.h
+++ b/lib/igt_aux.h
@@ -264,4 +264,10 @@  double igt_stop_siglatency(struct igt_mean *result);
 void igt_set_module_param(const char *name, const char *val);
 void igt_set_module_param_int(const char *name, int val);
 
+int igt_pkill(int sig, const char *comm);
+
+int igt_kmod_is_loaded(const char *mod_name);
+int igt_kmod_load(const char *mod_name, const char *opts);
+int igt_kmod_unload(const char *mod_name, unsigned int flags);
+
 #endif /* IGT_AUX_H */
diff --git a/lib/igt_gvt.c b/lib/igt_gvt.c
index 0f332d1..8bbf9bd 100644
--- a/lib/igt_gvt.c
+++ b/lib/igt_gvt.c
@@ -23,6 +23,7 @@ 
 
 #include "igt.h"
 #include "igt_gvt.h"
+#include "igt_sysfs.h"
 
 #include <dirent.h>
 #include <unistd.h>
@@ -46,49 +47,9 @@  static bool is_gvt_enabled(void)
 	return enabled;
 }
 
-static void unbind_fbcon(void)
-{
-	char buf[128];
-	const char *path = "/sys/class/vtconsole";
-	DIR *dir;
-	struct dirent *vtcon;
-
-	dir = opendir(path);
-	if (!dir)
-		return;
-
-	while ((vtcon = readdir(dir))) {
-		int fd, len;
-
-		if (strncmp(vtcon->d_name, "vtcon", 5))
-			continue;
-
-		sprintf(buf, "%s/%s/name", path, vtcon->d_name);
-		fd = open(buf, O_RDONLY);
-		if (fd < 0)
-			continue;
-
-		len = read(fd, buf, sizeof(buf) - 1);
-		close(fd);
-		if (len >= 0)
-			buf[len] = '\0';
-
-		if (strstr(buf, "frame buffer device")) {
-			sprintf(buf, "%s/%s/bind", path, vtcon->d_name);
-			fd = open(buf, O_WRONLY);
-			if (fd != -1) {
-				igt_ignore_warn(write(fd, "1\n", 2));
-				close(fd);
-			}
-			break;
-		}
-	}
-	closedir(dir);
-}
-
 static void unload_i915(void)
 {
-	unbind_fbcon();
+	kick_fbcon(false);
 	/* pkill alsact */
 
 	igt_ignore_warn(system("/sbin/modprobe -s -r i915"));
diff --git a/lib/igt_sysfs.c b/lib/igt_sysfs.c
index c19821d..64a95de 100644
--- a/lib/igt_sysfs.c
+++ b/lib/igt_sysfs.c
@@ -34,7 +34,11 @@ 
 #include <fcntl.h>
 #include <unistd.h>
 #include <i915_drm.h>
+#include <dirent.h>
+#include <unistd.h>
+#include <fcntl.h>
 
+#include "igt_core.h"
 #include "igt_sysfs.h"
 
 /**
@@ -392,3 +396,53 @@  bool igt_sysfs_set_boolean(int dir, const char *attr, bool value)
 {
 	return igt_sysfs_printf(dir, attr, "%d", value) == 1;
 }
+
+/**
+ * kick_fbcon:
+ * @enable: boolean value
+ *
+ * This functions enables/disables the text console running on top of the
+ * framebuffer device.
+ */
+void kick_fbcon(bool enable)
+{
+	char buf[128];
+	const char *path = "/sys/class/vtconsole";
+	DIR *dir;
+	struct dirent *vtcon;
+
+	dir = opendir(path);
+	if (!dir)
+		return;
+
+	while ((vtcon = readdir(dir))) {
+		int fd, len;
+
+		if (strncmp(vtcon->d_name, "vtcon", 5))
+			continue;
+
+		sprintf(buf, "%s/%s/name", path, vtcon->d_name);
+		fd = open(buf, O_RDONLY);
+		if (fd < 0)
+			continue;
+
+		len = read(fd, buf, sizeof(buf) - 1);
+		close(fd);
+		if (len >= 0)
+			buf[len] = '\0';
+
+		if (strstr(buf, "frame buffer device")) {
+			sprintf(buf, "%s/%s/bind", path, vtcon->d_name);
+			fd = open(buf, O_WRONLY);
+			if (fd != -1) {
+				if (enable)
+					igt_ignore_warn(write(fd, "1\n", 2));
+				else
+					igt_ignore_warn(write(fd, "0\n", 2));
+				close(fd);
+			}
+			break;
+		}
+	}
+	closedir(dir);
+}
diff --git a/lib/igt_sysfs.h b/lib/igt_sysfs.h
index 4820066..a141894 100644
--- a/lib/igt_sysfs.h
+++ b/lib/igt_sysfs.h
@@ -43,4 +43,6 @@  bool igt_sysfs_set_u32(int dir, const char *attr, uint32_t value);
 bool igt_sysfs_get_boolean(int dir, const char *attr);
 bool igt_sysfs_set_boolean(int dir, const char *attr, bool value);
 
+void kick_fbcon(bool enable);
+
 #endif /* __IGT_SYSFS_H__ */