aboutsummaryrefslogtreecommitdiff
path: root/sbin/devmatch/devmatch.c
diff options
context:
space:
mode:
authorHans Petter Selasky <hselasky@FreeBSD.org>2018-02-17 14:34:47 +0000
committerHans Petter Selasky <hselasky@FreeBSD.org>2018-02-17 14:34:47 +0000
commit201c73815f0514c49b2d2ad6f0ea5a3cae726212 (patch)
tree2b90c9489898ca9cae22bb0b5177b71e92907bb1 /sbin/devmatch/devmatch.c
parent4afa0076c53c62b260ce55c5aa235c53326ff409 (diff)
downloadsrc-201c73815f0514c49b2d2ad6f0ea5a3cae726212.tar.gz
src-201c73815f0514c49b2d2ad6f0ea5a3cae726212.zip
Fix USB driver matching in devmatch(8).
Multiple drivers can match on the same USB device and the order of loading decides which driver gets the device. Use the supplied mask value as an indication of priority, so that vendor specific device drivers are loaded before more generic ones. Sponsored by: Mellanox Technologies
Notes
Notes: svn path=/head/; revision=329458
Diffstat (limited to 'sbin/devmatch/devmatch.c')
-rw-r--r--sbin/devmatch/devmatch.c65
1 files changed, 63 insertions, 2 deletions
diff --git a/sbin/devmatch/devmatch.c b/sbin/devmatch/devmatch.c
index a2b51e4a015c..048cb30e508c 100644
--- a/sbin/devmatch/devmatch.c
+++ b/sbin/devmatch/devmatch.c
@@ -54,6 +54,14 @@ static struct option longopts[] = {
{ NULL, 0, NULL, 0 }
};
+#define DEVMATCH_MAX_HITS 256
+
+static struct match_data {
+ char *descr;
+ int priority;
+} match_data[DEVMATCH_MAX_HITS];
+
+static int hit_index;
static int all_flag;
static int dump_flag;
static char *linker_hints;
@@ -236,6 +244,35 @@ pnpval_as_str(const char *val, const char *pnpinfo)
return retval;
}
+static int
+match_data_compare(const void *_pa, const void *_pb)
+{
+ const struct match_data *pa = _pa;
+ const struct match_data *pb = _pb;
+
+ /* biggest value first */
+ if (pa->priority > pb->priority)
+ return (-1);
+ else if (pa->priority < pb->priority)
+ return (1);
+
+ /* then sort by string */
+ return (strcmp(pa->descr, pb->descr));
+}
+
+static int
+bitrev16(int input)
+{
+ int retval = 0;
+ int x;
+
+ for (x = 0; x != 16; x++) {
+ if ((input >> x) & 1)
+ retval |= (0x8000 >> x);
+ }
+ return (retval);
+}
+
static void
search_hints(const char *bus, const char *dev, const char *pnpinfo)
{
@@ -367,9 +404,20 @@ search_hints(const char *bus, const char *dev, const char *pnpinfo)
printf("\n");
else if (!notme) {
if (!unbound_flag) {
+ char *descr = NULL;
+
if (all_flag)
- printf("%s: ", *dev ? dev : "unattached" );
- printf("%s\n", lastmod);
+ asprintf(&descr, "%s: %s", *dev ? dev : "unattached", lastmod);
+ else
+ asprintf(&descr, "%s", lastmod);
+
+ if (descr != NULL && hit_index < DEVMATCH_MAX_HITS) {
+ match_data[hit_index].descr = descr;
+ match_data[hit_index].priority = bitrev16(mask);
+ hit_index++;
+ } else {
+ free(descr);
+ }
}
found++;
}
@@ -382,6 +430,19 @@ search_hints(const char *bus, const char *dev, const char *pnpinfo)
}
walker = (void *)(len - sizeof(int) + (intptr_t)walker);
}
+ if (hit_index != 0) {
+ /* sort hits by priority */
+ mergesort(match_data, hit_index, sizeof(match_data[0]), &match_data_compare);
+
+ /* printout */
+ for (i = 0; i != hit_index; i++) {
+ puts(match_data[i].descr);
+ free(match_data[i].descr);
+ }
+
+ /* reset hit_index */
+ hit_index = 0;
+ }
if (unbound_flag && found == 0 && *pnpinfo) {
if (verbose_flag)
printf("------------------------- ");