diff options
author | Karol Kosik <kkosik@nvidia.com> | 2015-07-22 16:42:07 -0700 |
---|---|---|
committer | Eric Anholt <eric@anholt.net> | 2017-05-09 17:36:05 -0700 |
commit | 5d3b6cc221aff5b9322b31aa6f5ae922271bc7d8 (patch) | |
tree | 2898df2f960ed58c15229eacc09ec71a99613a52 | |
parent | 2388f5e583d4ab2ee12f2b087d381b64aed3f7d5 (diff) |
xfree86: Improved autoconfig drivers matching
Implementation of new drivers matching algorithm. New approach
doesn't add duplicate drivers and ease drivers matching phase.
v2: Re-commit the patch reverted in
2388f5e583d4ab2ee12f2b087d381b64aed3f7d5, with Aaron Plattner's
fix squashed in (by anholt).
Signed-off-by: Karol Kosik <kkosik@nvidia.com>
Signed-off-by: Aaron Plattner <aplattner@nvidia.com>
Signed-off-by: Eric Anholt <eric@anholt.net>
Reviewed-by: Aaron Plattner <aplattner@nvidia.com> (v1)
Reviewed-by: Emil Velikov <emil.l.velikov@gmail.com> (v1)
Tested-by: Peter Hutterer <peter.hutterer@who-t.net>
Tested-by: Eric Anholt <eric@anholt.net>
-rw-r--r-- | hw/xfree86/common/Makefile.am | 3 | ||||
-rw-r--r-- | hw/xfree86/common/meson.build | 1 | ||||
-rw-r--r-- | hw/xfree86/common/xf86AutoConfig.c | 126 | ||||
-rw-r--r-- | hw/xfree86/common/xf86MatchDrivers.h | 40 | ||||
-rw-r--r-- | hw/xfree86/common/xf86pciBus.c | 52 | ||||
-rw-r--r-- | hw/xfree86/common/xf86pciBus.h | 13 | ||||
-rw-r--r-- | hw/xfree86/common/xf86platformBus.c | 31 | ||||
-rw-r--r-- | hw/xfree86/common/xf86platformBus.h | 5 |
8 files changed, 153 insertions, 118 deletions
diff --git a/hw/xfree86/common/Makefile.am b/hw/xfree86/common/Makefile.am index caae7fd97..41758fd2e 100644 --- a/hw/xfree86/common/Makefile.am +++ b/hw/xfree86/common/Makefile.am @@ -58,7 +58,8 @@ sdk_HEADERS = compiler.h fourcc.h xf86.h xf86Module.h xf86Opt.h \ xf86PciInfo.h xf86Priv.h xf86Privstr.h \ xf86cmap.h xf86fbman.h xf86str.h xf86Xinput.h xisb.h \ $(XVSDKINCS) $(XF86VMODE_SDK) $(DGA_SDK) xorgVersion.h \ - xf86sbusBus.h xf86VGAarbiter.h xf86Optionstr.h xf86platformBus.h \ + xf86sbusBus.h xf86VGAarbiter.h xf86Optionstr.h \ + xf86platformBus.h xf86MatchDrivers.h \ xaarop.h DISTCLEANFILES = xf86Build.h diff --git a/hw/xfree86/common/meson.build b/hw/xfree86/common/meson.build index cdbc5e609..6ed3f5124 100644 --- a/hw/xfree86/common/meson.build +++ b/hw/xfree86/common/meson.build @@ -43,6 +43,7 @@ xorg_sdk_headers = [ 'xf86VGAarbiter.h', 'xf86Optionstr.h', 'xf86platformBus.h', + 'xf86MatchDrivers.h', 'xaarop.h', ] diff --git a/hw/xfree86/common/xf86AutoConfig.c b/hw/xfree86/common/xf86AutoConfig.c index c3e17beb7..0f4f05de9 100644 --- a/hw/xfree86/common/xf86AutoConfig.c +++ b/hw/xfree86/common/xf86AutoConfig.c @@ -37,6 +37,7 @@ #include "xf86Parser.h" #include "xf86tokens.h" #include "xf86Config.h" +#include "xf86MatchDrivers.h" #include "xf86Priv.h" #include "xf86_OSlib.h" #include "xf86platformBus.h" @@ -89,7 +90,7 @@ static const char **builtinConfig = NULL; static int builtinLines = 0; -static void listPossibleVideoDrivers(char *matches[], int nmatches); +static void listPossibleVideoDrivers(XF86MatchedDrivers *md); /* * A built-in config file is stored as an array of strings, with each string @@ -140,11 +141,33 @@ AppendToConfig(const char *s) AppendToList(s, &builtinConfig, &builtinLines); } +void +xf86AddMatchedDriver(XF86MatchedDrivers *md, const char *driver) +{ + int j; + int nmatches = md->nmatches; + + for (j = 0; j < nmatches; ++j) { + if (xf86NameCmp(md->matches[j], driver) == 0) { + // Driver already in matched drivers + return; + } + } + + if (nmatches < MATCH_DRIVERS_LIMIT) { + md->matches[nmatches] = xnfstrdup(driver); + md->nmatches++; + } + else { + xf86Msg(X_WARNING, "Too many drivers registered, can't add %s\n", driver); + } +} + Bool xf86AutoConfig(void) { - char *deviceList[20]; - char **p; + XF86MatchedDrivers md; + int i; const char **cp; char buf[1024]; ConfigStatus ret; @@ -158,24 +181,27 @@ xf86AutoConfig(void) return FALSE; } - listPossibleVideoDrivers(deviceList, 20); + listPossibleVideoDrivers(&md); - for (p = deviceList; *p; p++) { - snprintf(buf, sizeof(buf), BUILTIN_DEVICE_SECTION, *p, 0, *p); + for (i = 0; i < md.nmatches; i++) { + snprintf(buf, sizeof(buf), BUILTIN_DEVICE_SECTION, + md.matches[i], 0, md.matches[i]); AppendToConfig(buf); - snprintf(buf, sizeof(buf), BUILTIN_SCREEN_SECTION, *p, 0, *p, 0); + snprintf(buf, sizeof(buf), BUILTIN_SCREEN_SECTION, + md.matches[i], 0, md.matches[i], 0); AppendToConfig(buf); } AppendToConfig(BUILTIN_LAYOUT_SECTION_PRE); - for (p = deviceList; *p; p++) { - snprintf(buf, sizeof(buf), BUILTIN_LAYOUT_SCREEN_LINE, *p, 0); + for (i = 0; i < md.nmatches; i++) { + snprintf(buf, sizeof(buf), BUILTIN_LAYOUT_SCREEN_LINE, + md.matches[i], 0); AppendToConfig(buf); } AppendToConfig(BUILTIN_LAYOUT_SECTION_POST); - for (p = deviceList; *p; p++) { - free(*p); + for (i = 0; i < md.nmatches; i++) { + free(md.matches[i]); } xf86MsgVerb(X_DEFAULT, 0, @@ -199,22 +225,17 @@ xf86AutoConfig(void) } static void -listPossibleVideoDrivers(char *matches[], int nmatches) +listPossibleVideoDrivers(XF86MatchedDrivers *md) { - int i; - - for (i = 0; i < nmatches; i++) { - matches[i] = NULL; - } - i = 0; + md->nmatches = 0; #ifdef XSERVER_PLATFORM_BUS - i = xf86PlatformMatchDriver(matches, nmatches); + xf86PlatformMatchDriver(md); #endif #ifdef __sun /* Check for driver type based on /dev/fb type and if valid, use it instead of PCI bus probe results */ - if (xf86Info.consoleFd >= 0 && (i < (nmatches - 1))) { + if (xf86Info.consoleFd >= 0) { struct vis_identifier visid; const char *cp; int iret; @@ -240,7 +261,7 @@ listPossibleVideoDrivers(char *matches[], int nmatches) /* Special case from before the general case was set */ if (strcmp(visid.name, "NVDAnvda") == 0) { - matches[i++] = xnfstrdup("nvidia"); + xf86AddMatchedDriver(md, "nvidia"); } /* General case - split into vendor name (initial all-caps @@ -250,55 +271,48 @@ listPossibleVideoDrivers(char *matches[], int nmatches) /* find end of all uppercase vendor section */ } if ((cp != visid.name) && (*cp != '\0')) { - char *driverName = xnfstrdup(cp); char *vendorName = xnfstrdup(visid.name); vendorName[cp - visid.name] = '\0'; - matches[i++] = vendorName; - matches[i++] = driverName; + xf86AddMatchedDriver(md, vendorName); + xf86AddMatchedDriver(md, cp); + + free(vendorName); } } } } #endif #ifdef __sparc__ - if (i < (nmatches - 1)) - { - char *sbusDriver = sparcDriverName(); + char *sbusDriver = sparcDriverName(); - if (sbusDriver) - matches[i++] = xnfstrdup(sbusDriver); - } + if (sbusDriver) + xf86AddMatchedDriver(md, sbusDriver); #endif #ifdef XSERVER_LIBPCIACCESS - if (i < (nmatches - 1)) - i += xf86PciMatchDriver(&matches[i], nmatches - i); + xf86PciMatchDriver(md); #endif #if defined(__linux__) - matches[i++] = xnfstrdup("modesetting"); + xf86AddMatchedDriver(md, "modesetting"); #endif #if !defined(__sun) /* Fallback to platform default frame buffer driver */ - if (i < (nmatches - 1)) { #if !defined(__linux__) && defined(__sparc__) - matches[i++] = xnfstrdup("wsfb"); + xf86AddMatchedDriver(md, "wsfb"); #else - matches[i++] = xnfstrdup("fbdev"); + xf86AddMatchedDriver(md, "fbdev"); #endif - } #endif /* !__sun */ /* Fallback to platform default hardware */ - if (i < (nmatches - 1)) { #if defined(__i386__) || defined(__amd64__) || defined(__hurd__) - matches[i++] = xnfstrdup("vesa"); + xf86AddMatchedDriver(md, "vesa"); #elif defined(__sparc__) && !defined(__sun) - matches[i++] = xnfstrdup("sunffb"); + xf86AddMatchedDriver(md, "sunffb"); #endif - } } /* copy a screen section and enter the desired driver @@ -344,8 +358,8 @@ GDevPtr autoConfigDevice(GDevPtr preconf_device) { GDevPtr ptr = NULL; - char *matches[20]; /* If we have more than 20 drivers we're in trouble */ - int num_matches = 0, num_screens = 0, i; + XF86MatchedDrivers md; + int num_screens = 0, i; screenLayoutPtr slp; if (!xf86configptr) { @@ -372,10 +386,10 @@ autoConfigDevice(GDevPtr preconf_device) } if (!ptr->driver) { /* get all possible video drivers and count them */ - listPossibleVideoDrivers(matches, 20); - for (; matches[num_matches]; num_matches++) { + listPossibleVideoDrivers(&md); + for (i = 0; i < md.nmatches; i++) { xf86Msg(X_DEFAULT, "Matched %s as autoconfigured driver %d\n", - matches[num_matches], num_matches); + md.matches[i], i); } slp = xf86ConfigLayout.screens; @@ -385,12 +399,12 @@ autoConfigDevice(GDevPtr preconf_device) * minus one for the already existing first one * plus one for the terminating NULL */ for (; slp[num_screens].screen; num_screens++); - xf86ConfigLayout.screens = xnfcalloc(num_screens + num_matches, + xf86ConfigLayout.screens = xnfcalloc(num_screens + md.nmatches, sizeof(screenLayoutRec)); xf86ConfigLayout.screens[0] = slp[0]; /* do the first match and set that for the original first screen */ - ptr->driver = matches[0]; + ptr->driver = md.matches[0]; if (!xf86ConfigLayout.screens[0].screen->device) { xf86ConfigLayout.screens[0].screen->device = ptr; ptr->myScreenSection = xf86ConfigLayout.screens[0].screen; @@ -398,8 +412,8 @@ autoConfigDevice(GDevPtr preconf_device) /* for each other driver found, copy the first screen, insert it * into the list of screens and set the driver */ - for (i = 1; i < num_matches; i++) { - if (!copyScreen(slp[0].screen, ptr, i, matches[i])) + for (i = 1; i < md.nmatches; i++) { + if (!copyScreen(slp[0].screen, ptr, i, md.matches[i])) return NULL; } @@ -408,19 +422,17 @@ autoConfigDevice(GDevPtr preconf_device) * * TODO Handle rest of multiple screen sections */ for (i = 1; i < num_screens; i++) { - xf86ConfigLayout.screens[i + num_matches] = slp[i]; + xf86ConfigLayout.screens[i + md.nmatches] = slp[i]; } - xf86ConfigLayout.screens[num_screens + num_matches - 1].screen = + xf86ConfigLayout.screens[num_screens + md.nmatches - 1].screen = NULL; free(slp); } else { /* layout does not have any screens, not much to do */ - ptr->driver = matches[0]; - for (i = 1; matches[i]; i++) { - if (matches[i] != matches[0]) { - free(matches[i]); - } + ptr->driver = md.matches[0]; + for (i = 1; i < md.nmatches; i++) { + free(md.matches[i]); } } } diff --git a/hw/xfree86/common/xf86MatchDrivers.h b/hw/xfree86/common/xf86MatchDrivers.h new file mode 100644 index 000000000..4663af478 --- /dev/null +++ b/hw/xfree86/common/xf86MatchDrivers.h @@ -0,0 +1,40 @@ +/* + * Copyright © 2015 NVIDIA Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +#ifndef _xf86_match_drivers_h +#define _xf86_match_drivers_h + +#define MATCH_DRIVERS_LIMIT 20 + +typedef struct _XF86MatchedDrivers { + char *matches[MATCH_DRIVERS_LIMIT]; + int nmatches; +} XF86MatchedDrivers; + +/* + * prototypes + */ +void xf86AddMatchedDriver(XF86MatchedDrivers *, const char *); + +#endif /* _xf86_match_drivers_h */ + diff --git a/hw/xfree86/common/xf86pciBus.c b/hw/xfree86/common/xf86pciBus.c index 41460a0f8..0d0a76bc8 100644 --- a/hw/xfree86/common/xf86pciBus.c +++ b/hw/xfree86/common/xf86pciBus.c @@ -1063,9 +1063,8 @@ xf86ConfigPciEntity(ScrnInfoPtr pScrn, int scrnFlag, int entityIndex, return pScrn; } -int -xf86VideoPtrToDriverList(struct pci_device *dev, - char *returnList[], int returnListMax) +void +xf86VideoPtrToDriverList(struct pci_device *dev, XF86MatchedDrivers *md) { int i; @@ -1268,10 +1267,9 @@ xf86VideoPtrToDriverList(struct pci_device *dev, default: break; } - for (i = 0; (i < returnListMax) && (driverList[i] != NULL); i++) { - returnList[i] = xnfstrdup(driverList[i]); + for (i = 0; driverList[i] != NULL; i++) { + xf86AddMatchedDriver(md, driverList[i]); } - return i; /* Number of entries added */ } #ifdef __linux__ @@ -1295,23 +1293,23 @@ xchomp(char *line) * don't export their PCI ID's properly. If distros don't end up using this * feature it can and should be removed because the symbol-based resolution * scheme should be the primary one */ -int +void xf86MatchDriverFromFiles(uint16_t match_vendor, uint16_t match_chip, - char *matches[], int nmatches) + XF86MatchedDrivers *md) { DIR *idsdir; FILE *fp; struct dirent *direntry; - char *line = NULL; + char *line = NULL, *tmpMatch; size_t len; ssize_t read; char path_name[256], vendor_str[5], chip_str[5]; uint16_t vendor, chip; - int i = 0, j; + int j; idsdir = opendir(PCI_TXT_IDS_PATH); if (!idsdir) - return 0; + return; xf86Msg(X_INFO, "Scanning %s directory for additional PCI ID's supported by the drivers\n", @@ -1362,10 +1360,10 @@ xf86MatchDriverFromFiles(uint16_t match_vendor, uint16_t match_chip, } } if (vendor == match_vendor && chip == match_chip) { - matches[i] = + tmpMatch = (char *) malloc(sizeof(char) * strlen(direntry->d_name) - 3); - if (!matches[i]) { + if (!tmpMatch) { xf86Msg(X_ERROR, "Could not allocate space for the module name. Exiting.\n"); goto end; @@ -1375,16 +1373,17 @@ xf86MatchDriverFromFiles(uint16_t match_vendor, uint16_t match_chip, * taking off anything after the first '.' */ for (j = 0; j < (strlen(direntry->d_name) - 3); j++) { if (direntry->d_name[j] == '.') { - matches[i][j] = '\0'; + tmpMatch[j] = '\0'; break; } else { - matches[i][j] = direntry->d_name[j]; + tmpMatch[j] = direntry->d_name[j]; } } + xf86AddMatchedDriver(md, tmpMatch); xf86Msg(X_INFO, "Matched %s from file name %s\n", - matches[i], direntry->d_name); - i++; + tmpMatch, direntry->d_name); + free(tmpMatch); } } else { @@ -1398,18 +1397,12 @@ xf86MatchDriverFromFiles(uint16_t match_vendor, uint16_t match_chip, end: free(line); closedir(idsdir); - return i; } #endif /* __linux__ */ -/** - * @return The numbers of found devices that match with the current system - * drivers. - */ -int -xf86PciMatchDriver(char *matches[], int nmatches) +void +xf86PciMatchDriver(XF86MatchedDrivers *md) { - int i = 0; struct pci_device *info = NULL; struct pci_device_iterator *iter; @@ -1424,15 +1417,12 @@ xf86PciMatchDriver(char *matches[], int nmatches) pci_iterator_destroy(iter); #ifdef __linux__ if (info) - i += xf86MatchDriverFromFiles(info->vendor_id, info->device_id, - matches, nmatches); + xf86MatchDriverFromFiles(info->vendor_id, info->device_id, md); #endif - if ((info != NULL) && (i < nmatches)) { - i += xf86VideoPtrToDriverList(info, &(matches[i]), nmatches - i); + if (info != NULL) { + xf86VideoPtrToDriverList(info, md); } - - return i; } Bool diff --git a/hw/xfree86/common/xf86pciBus.h b/hw/xfree86/common/xf86pciBus.h index 45b5a0fee..14ae9760e 100644 --- a/hw/xfree86/common/xf86pciBus.h +++ b/hw/xfree86/common/xf86pciBus.h @@ -33,11 +33,13 @@ #ifndef _XF86_PCI_BUS_H #define _XF86_PCI_BUS_H +#include "xf86MatchDrivers.h" + void xf86PciProbe(void); Bool xf86PciAddMatchingDev(DriverPtr drvp); Bool xf86PciProbeDev(DriverPtr drvp); void xf86PciIsolateDevice(const char *argument); -int xf86PciMatchDriver(char *matches[], int nmatches); +void xf86PciMatchDriver(XF86MatchedDrivers *md); Bool xf86PciConfigure(void *busData, struct pci_device *pDev); void xf86PciConfigureNewDev(void *busData, struct pci_device *pVideo, GDevRec * GDev, int *chipset); @@ -47,10 +49,9 @@ void xf86PciConfigureNewDev(void *busData, struct pci_device *pVideo, ((x)->func == (y)->func) && \ ((x)->dev == (y)->dev)) -int +void xf86MatchDriverFromFiles(uint16_t match_vendor, uint16_t match_chip, - char *matches[], int nmatches); -int -xf86VideoPtrToDriverList(struct pci_device *dev, - char *returnList[], int returnListMax); + XF86MatchedDrivers *md); +void +xf86VideoPtrToDriverList(struct pci_device *dev, XF86MatchedDrivers *md); #endif /* _XF86_PCI_BUS_H */ diff --git a/hw/xfree86/common/xf86platformBus.c b/hw/xfree86/common/xf86platformBus.c index 0b5795fe7..844bf7e93 100644 --- a/hw/xfree86/common/xf86platformBus.c +++ b/hw/xfree86/common/xf86platformBus.c @@ -219,14 +219,10 @@ OutputClassMatches(const XF86ConfOutputClassPtr oclass, return TRUE; } -static int -xf86OutputClassDriverList(int index, char *matches[], int nmatches) +static void +xf86OutputClassDriverList(int index, XF86MatchedDrivers *md) { XF86ConfOutputClassPtr cl; - int i = 0; - - if (nmatches == 0) - return 0; for (cl = xf86configptr->conf_outputclass_lst; cl; cl = cl->list.next) { if (OutputClassMatches(cl, &xf86_platform_devices[index])) { @@ -236,24 +232,19 @@ xf86OutputClassDriverList(int index, char *matches[], int nmatches) cl->identifier, path); xf86Msg(X_NONE, "\tloading driver: %s\n", cl->driver); - matches[i++] = xstrdup(cl->driver); + xf86AddMatchedDriver(md, cl->driver); } - - if (i >= nmatches) - break; } - - return i; } /** * @return The numbers of found devices that match with the current system * drivers. */ -int -xf86PlatformMatchDriver(char *matches[], int nmatches) +void +xf86PlatformMatchDriver(XF86MatchedDrivers *md) { - int i, j = 0; + int i; struct pci_device *info = NULL; int pass = 0; @@ -265,21 +256,19 @@ xf86PlatformMatchDriver(char *matches[], int nmatches) else if (!xf86IsPrimaryPlatform(&xf86_platform_devices[i]) && (pass == 0)) continue; - j += xf86OutputClassDriverList(i, &matches[j], nmatches - j); + xf86OutputClassDriverList(i, md); info = xf86_platform_devices[i].pdev; #ifdef __linux__ if (info) - j += xf86MatchDriverFromFiles(info->vendor_id, info->device_id, - &matches[j], nmatches - j); + xf86MatchDriverFromFiles(info->vendor_id, info->device_id, md); #endif - if ((info != NULL) && (j < nmatches)) { - j += xf86VideoPtrToDriverList(info, &(matches[j]), nmatches - j); + if (info != NULL) { + xf86VideoPtrToDriverList(info, md); } } } - return j; } int diff --git a/hw/xfree86/common/xf86platformBus.h b/hw/xfree86/common/xf86platformBus.h index 70d9ec888..1e75e6352 100644 --- a/hw/xfree86/common/xf86platformBus.h +++ b/hw/xfree86/common/xf86platformBus.h @@ -25,6 +25,7 @@ #define XF86_PLATFORM_BUS_H #include "hotplug.h" +#include "xf86MatchDrivers.h" struct xf86_platform_device { struct OdevAttributes *attribs; @@ -153,8 +154,8 @@ _xf86_get_platform_device_int_attrib(struct xf86_platform_device *device, int at extern _X_EXPORT Bool xf86PlatformDeviceCheckBusID(struct xf86_platform_device *device, const char *busid); -extern _X_EXPORT int -xf86PlatformMatchDriver(char *matches[], int nmatches); +extern _X_EXPORT void +xf86PlatformMatchDriver(XF86MatchedDrivers *); extern void xf86platformVTProbe(void); extern void xf86platformPrimary(void); |