6c7b302
From b5dffbbac193aa640ffcfa0a431c21b862854e53 Mon Sep 17 00:00:00 2001
6c7b302
From: Hans De Goede <hdegoede@redhat.com>
6c7b302
Date: Mon, 12 Dec 2016 17:03:17 +0100
6c7b302
Subject: [PATCH xserver 6/6] xfree86: Add ModulePath support for OutputClass
6c7b302
 config Sections
6c7b302
6c7b302
Allow OutputClass config snippets to modify the module-path.
6c7b302
6c7b302
Note that any specified ModulePaths will be pre-pended to the normal
6c7b302
ModulePath. The idea behind this is that any output hardware specific
6c7b302
modules should have preference over the normal modules.
6c7b302
6c7b302
One use-case for this is the nvidia binary driver, this allows a
6c7b302
config snippet like this:
6c7b302
6c7b302
Section "OutputClass"
6c7b302
    MatchDriver "nvidia"
6c7b302
    Modulepath "/usr/lib64/nvidia/modules"
6c7b302
EndSection
6c7b302
6c7b302
To get the nvidia glx specific glx module loaded, but only when the
6c7b302
nvidia kernel driver is loaded.
6c7b302
6c7b302
Together with the glvnd work done recently, this allows the nouveau
6c7b302
+ mesa and nvidia-binary userspace stacks to co-exist on the same
6c7b302
system without any ldconfig / xorg.conf tweaking and the xserver will
6c7b302
automatically do the right thing depending on which kernel driver
6c7b302
(nouveau or nvidia) is loaded.
6c7b302
6c7b302
Reviewed-by: Adam Jackson <ajax@redhat.com>
6c7b302
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
6c7b302
---
6c7b302
 hw/xfree86/common/xf86platformBus.c | 23 +++++++++++++++++++++++
6c7b302
 hw/xfree86/loader/loadmod.c         |  1 +
6c7b302
 hw/xfree86/man/xorg.conf.man        | 16 ++++++++++++++++
6c7b302
 hw/xfree86/parser/OutputClass.c     | 15 +++++++++++++++
6c7b302
 hw/xfree86/parser/xf86Parser.h      |  1 +
6c7b302
 5 files changed, 56 insertions(+)
6c7b302
6c7b302
diff --git a/hw/xfree86/common/xf86platformBus.c b/hw/xfree86/common/xf86platformBus.c
6c7b302
index fc17d15..0b5795f 100644
6c7b302
--- a/hw/xfree86/common/xf86platformBus.c
6c7b302
+++ b/hw/xfree86/common/xf86platformBus.c
6c7b302
@@ -40,6 +40,7 @@
6c7b302
 #include "hotplug.h"
6c7b302
 #include "systemd-logind.h"
6c7b302
 
6c7b302
+#include "loaderProcs.h"
6c7b302
 #include "xf86.h"
6c7b302
 #include "xf86_OSproc.h"
6c7b302
 #include "xf86Priv.h"
6c7b302
@@ -287,6 +288,7 @@ xf86platformProbe(void)
6c7b302
     int i;
6c7b302
     Bool pci = TRUE;
6c7b302
     XF86ConfOutputClassPtr cl;
6c7b302
+    char *old_path, *path = NULL;
6c7b302
 
6c7b302
     config_odev_probe(xf86PlatformDeviceProbe);
6c7b302
 
6c7b302
@@ -300,8 +302,29 @@ xf86platformProbe(void)
6c7b302
         if (pci && (strncmp(busid, "pci:", 4) == 0)) {
6c7b302
             platform_find_pci_info(&xf86_platform_devices[i], busid);
6c7b302
         }
6c7b302
+
6c7b302
+        /*
6c7b302
+         * Deal with OutputClass ModulePath directives, these must be
6c7b302
+         * processed before we do any module loading.
6c7b302
+         */
6c7b302
+        for (cl = xf86configptr->conf_outputclass_lst; cl; cl = cl->list.next) {
6c7b302
+            if (!OutputClassMatches(cl, &xf86_platform_devices[i]))
6c7b302
+                continue;
6c7b302
+
6c7b302
+            if (cl->modulepath && xf86ModPathFrom != X_CMDLINE) {
6c7b302
+                old_path = path;
6c7b302
+                XNFasprintf(&path, "%s,%s", cl->modulepath,
6c7b302
+                            path ? path : xf86ModulePath);
6c7b302
+                free(old_path);
6c7b302
+                xf86Msg(X_CONFIG, "OutputClass \"%s\" ModulePath extended to \"%s\"\n",
6c7b302
+                        cl->identifier, path);
6c7b302
+                LoaderSetPath(path);
6c7b302
+            }
6c7b302
+        }
6c7b302
     }
6c7b302
 
6c7b302
+    free(path);
6c7b302
+
6c7b302
     /* First see if there is an OutputClass match marking a device as primary */
6c7b302
     for (i = 0; i < xf86_num_platform_devices; i++) {
6c7b302
         struct xf86_platform_device *dev = &xf86_platform_devices[i];
6c7b302
diff --git a/hw/xfree86/loader/loadmod.c b/hw/xfree86/loader/loadmod.c
6c7b302
index 8bf6836..940f5fc 100644
6c7b302
--- a/hw/xfree86/loader/loadmod.c
6c7b302
+++ b/hw/xfree86/loader/loadmod.c
6c7b302
@@ -184,6 +184,7 @@ LoaderSetPath(const char *path)
6c7b302
     if (!path)
6c7b302
         return;
6c7b302
 
6c7b302
+    FreeStringList(defaultPathList);
6c7b302
     defaultPathList = InitPathList(path);
6c7b302
 }
6c7b302
 
6c7b302
diff --git a/hw/xfree86/man/xorg.conf.man b/hw/xfree86/man/xorg.conf.man
6c7b302
index 79b71a8..00ebf56 100644
6c7b302
--- a/hw/xfree86/man/xorg.conf.man
6c7b302
+++ b/hw/xfree86/man/xorg.conf.man
6c7b302
@@ -1300,6 +1300,22 @@ This option specifies that the matched device should be treated as the
6c7b302
 primary GPU, replacing the selection of the GPU used as output by the
6c7b302
 firmware. If multiple output devices match an OutputClass section with
6c7b302
 the PrimaryGPU option set, the first one enumerated becomes the primary GPU.
6c7b302
+.PP
6c7b302
+A
6c7b302
+.B OutputClass
6c7b302
+Section may contain
6c7b302
+.B ModulePath
6c7b302
+entries. When an output device matches an
6c7b302
+.B OutputClass
6c7b302
+section, any
6c7b302
+.B ModulePath
6c7b302
+entries in that
6c7b302
+.B OutputClass
6c7b302
+are pre-pended to the search path for loadable Xorg server modules. See
6c7b302
+.B ModulePath
6c7b302
+in the
6c7b302
+.B Files
6c7b302
+section for more info.
6c7b302
 .SH "DEVICE SECTION"
6c7b302
 The config file may have multiple
6c7b302
 .B Device
6c7b302
diff --git a/hw/xfree86/parser/OutputClass.c b/hw/xfree86/parser/OutputClass.c
6c7b302
index f813ee6..01b348f 100644
6c7b302
--- a/hw/xfree86/parser/OutputClass.c
6c7b302
+++ b/hw/xfree86/parser/OutputClass.c
6c7b302
@@ -36,6 +36,7 @@ static const xf86ConfigSymTabRec OutputClassTab[] = {
6c7b302
     {ENDSECTION, "endsection"},
6c7b302
     {IDENTIFIER, "identifier"},
6c7b302
     {DRIVER, "driver"},
6c7b302
+    {MODULEPATH, "modulepath"},
6c7b302
     {OPTION, "option"},
6c7b302
     {MATCH_DRIVER, "matchdriver"},
6c7b302
     {-1, ""},
6c7b302
@@ -53,6 +54,7 @@ xf86freeOutputClassList(XF86ConfOutputClassPtr ptr)
6c7b302
         TestFree(ptr->identifier);
6c7b302
         TestFree(ptr->comment);
6c7b302
         TestFree(ptr->driver);
6c7b302
+        TestFree(ptr->modulepath);
6c7b302
 
6c7b302
         xorg_list_for_each_entry_safe(group, next, &ptr->match_driver, entry) {
6c7b302
             xorg_list_del(&group->entry);
6c7b302
@@ -115,6 +117,19 @@ xf86parseOutputClassSection(void)
6c7b302
             else
6c7b302
                 ptr->driver = xf86_lex_val.str;
6c7b302
             break;
6c7b302
+        case MODULEPATH:
6c7b302
+            if (xf86getSubToken(&(ptr->comment)) != STRING)
6c7b302
+                Error(QUOTE_MSG, "ModulePath");
6c7b302
+            if (ptr->modulepath) {
6c7b302
+                char *path;
6c7b302
+                XNFasprintf(&path, "%s,%s", ptr->modulepath, xf86_lex_val.str);
6c7b302
+                free(xf86_lex_val.str);
6c7b302
+                free(ptr->modulepath);
6c7b302
+                ptr->modulepath = path;
6c7b302
+            } else {
6c7b302
+                ptr->modulepath = xf86_lex_val.str;
6c7b302
+            }
6c7b302
+            break;
6c7b302
         case OPTION:
6c7b302
             ptr->option_lst = xf86parseOption(ptr->option_lst);
6c7b302
             break;
6c7b302
diff --git a/hw/xfree86/parser/xf86Parser.h b/hw/xfree86/parser/xf86Parser.h
6c7b302
index 897edab..e014048 100644
6c7b302
--- a/hw/xfree86/parser/xf86Parser.h
6c7b302
+++ b/hw/xfree86/parser/xf86Parser.h
6c7b302
@@ -337,6 +337,7 @@ typedef struct {
6c7b302
     GenericListRec list;
6c7b302
     char *identifier;
6c7b302
     char *driver;
6c7b302
+    char *modulepath;
6c7b302
     struct xorg_list match_driver;
6c7b302
     XF86OptionPtr option_lst;
6c7b302
     char *comment;
6c7b302
-- 
6c7b302
2.9.3
6c7b302