From patchwork Thu Oct 20 19:36:47 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Marius Vlad X-Patchwork-Id: 9387483 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id CD383607F0 for ; Thu, 20 Oct 2016 19:30:53 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id B842629BB2 for ; Thu, 20 Oct 2016 19:30:53 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id ACE9429BC6; Thu, 20 Oct 2016 19:30:53 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-4.2 required=2.0 tests=BAYES_00, RCVD_IN_DNSWL_MED autolearn=ham version=3.3.1 Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) (using TLSv1.2 with cipher DHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id 2C8BD29BB2 for ; Thu, 20 Oct 2016 19:30:51 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id E44146EC14; Thu, 20 Oct 2016 19:30:49 +0000 (UTC) X-Original-To: intel-gfx@lists.freedesktop.org Delivered-To: intel-gfx@lists.freedesktop.org Received: from mga14.intel.com (mga14.intel.com [192.55.52.115]) by gabe.freedesktop.org (Postfix) with ESMTPS id 2B88E6EC0F for ; Thu, 20 Oct 2016 19:30:40 +0000 (UTC) Received: from fmsmga004.fm.intel.com ([10.253.24.48]) by fmsmga103.fm.intel.com with ESMTP; 20 Oct 2016 12:30:33 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.31,372,1473145200"; d="scan'208";a="182028223" Received: from mcvlad-wk.rb.intel.com ([10.237.105.57]) by fmsmga004.fm.intel.com with ESMTP; 20 Oct 2016 12:30:32 -0700 From: Marius Vlad To: intel-gfx@lists.freedesktop.org Date: Thu, 20 Oct 2016 22:36:47 +0300 Message-Id: <20161020193649.11701-2-marius.c.vlad@intel.com> X-Mailer: git-send-email 2.9.3 In-Reply-To: <20161020193649.11701-1-marius.c.vlad@intel.com> References: <20161020193649.11701-1-marius.c.vlad@intel.com> Subject: [Intel-gfx] [PATCH i-g-t 1/3] lib/{igt_sysfs, igt_aux}: Make available to other users kick_fbcon() (unbind_fbcon()), and added helpers to igt_aux. X-BeenThere: intel-gfx@lists.freedesktop.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: Intel graphics driver community testing & development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Errors-To: intel-gfx-bounces@lists.freedesktop.org Sender: "Intel-gfx" X-Virus-Scanned: ClamAV using ClamSMTP Previously under unbind_fbcon(), disable/enable framebuffer console. lib/igt_aux: Added helpers to help convert sh scripts to C version. libkmod and procps interface. Signed-off-by: Marius Vlad --- configure.ac | 2 + lib/Makefile.am | 2 + lib/igt_aux.c | 278 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ lib/igt_aux.h | 7 ++ lib/igt_gvt.c | 43 +-------- lib/igt_sysfs.c | 54 +++++++++++ lib/igt_sysfs.h | 2 + 7 files changed, 347 insertions(+), 41 deletions(-) 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..d150818 100644 --- a/lib/igt_aux.c +++ b/lib/igt_aux.c @@ -51,6 +51,9 @@ #include #include +#include +#include + #include "drmtest.h" #include "i915_drm.h" #include "intel_chipset.h" @@ -1193,6 +1196,281 @@ 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, try = 5; + 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 (proc_info && + !strncasecmp(proc_info->cmd, comm, sizeof(proc_info->cmd))) { + switch (sig) { + case SIGTERM: + case SIGKILL: + do { + kill(proc_info->tid, sig); + } while (kill(proc_info->tid, 0) < 0 && try--); + + if (kill(proc_info->tid, 0) < 0) + err = -1; + break; + default: + if (kill(proc_info->tid, sig) < 0) + err = -1; + break; + } + + freeproc(proc_info); + break; + } + freeproc(proc_info); + } + + closeproc(proc); + return err; +} + +/** + * igt_kill: + * @sig: Signal to send. + * @pid: Process pid to send. + * @returns: 0 in case of success or -1 otherwise. + * + * This function is identical to igt_pkill() only that it searches the process + * table using @pid instead of comm name. + * + */ +int +igt_kill(int sig, pid_t pid) +{ + int err = 0, try = 5; + PROCTAB *proc; + proc_t *proc_info; + + proc = openproc(PROC_PID | PROC_FILLSTAT | PROC_FILLARG); + igt_assert(proc != NULL); + + while ((proc_info = readproc(proc, NULL))) { + if (proc_info && proc_info->tid == pid) { + switch (sig) { + case SIGTERM: + case SIGKILL: + do { + kill(proc_info->tid, sig); + } while (kill(proc_info->tid, 0) < 0 && try--); + + if (kill(proc_info->tid, 0) < 0) + err = -1; + break; + default: + if (kill(proc_info->tid, sig) < 0) + err = -1; + break; + } + freeproc(proc_info); + break; + } + freeproc(proc_info); + } + + closeproc(proc); + return err; +} + +static bool +igt_module_in_use(struct kmod_module *kmod) +{ + int err; + + err = kmod_module_get_initstate(kmod); + + /* if compiled builtin or does not exist */ + if (err == KMOD_MODULE_BUILTIN || err < 0) + return false; + + if (kmod_module_get_refcnt(kmod) != 0 || + kmod_module_get_holders(kmod) != NULL) + return true; + + + return false; +} + +/** + * igt_lsmod: + * @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. + * + */ +bool +igt_lsmod_has_module(const char *mod_name) +{ + struct kmod_list *mod, *list; + struct kmod_ctx *ctx; + bool ret = false; + + ctx = kmod_new(NULL, NULL); + igt_assert(ctx != NULL); + + if (kmod_module_new_from_loaded(ctx, &list) < 0) { + kmod_unref(ctx); + return ret; + } + + 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 = true; + break; + } + kmod_module_unref(kmod); + } + + kmod_module_unref_list(list); + kmod_unref(ctx); + + return ret; +} + + +/** + * igt_insmod: + * @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_insmod(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_rmmod: + * @mod_name: Module name. + * @force: A bool value to force removal. Note that his flag does not remove + * the module(s) that the module specified by @mod_name depends on. In other + * words you must igt_rmmod() the module(s) dependencies before calling it with + * @mod_name. + * @returns: 0 in case of success or -1 otherwise. + * + * Removes the module @mod_name. + * + */ +int +igt_rmmod(const char *mod_name, bool force) +{ + struct kmod_ctx *ctx; + struct kmod_module *kmod; + int err, flags = 0; + + 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; + } + + if (igt_module_in_use(kmod)) { + igt_info("Module %s is in use\n", mod_name); + err = -1; + goto out; + } + + if (force) { + flags |= KMOD_REMOVE_FORCE; + } + + 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..7946923 100644 --- a/lib/igt_aux.h +++ b/lib/igt_aux.h @@ -264,4 +264,11 @@ 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_kill(int sig, pid_t pid); + +bool igt_lsmod_has_module(const char *mod_name); +int igt_insmod(const char *mod_name, const char *opts); +int igt_rmmod(const char *mod_name, bool force); + #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 #include @@ -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 612de75..0803659 100644 --- a/lib/igt_sysfs.c +++ b/lib/igt_sysfs.c @@ -34,7 +34,11 @@ #include #include #include +#include +#include +#include +#include "igt_core.h" #include "igt_sysfs.h" /** @@ -391,3 +395,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__ */