Skip to content

Commit

Permalink
Fix USB driver matching in devmatch(8).
Browse files Browse the repository at this point in the history
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
  • Loading branch information
hselasky committed Feb 17, 2018
1 parent 7e9e084 commit 1dab672
Showing 1 changed file with 63 additions and 2 deletions.
65 changes: 63 additions & 2 deletions sbin/devmatch/devmatch.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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)
{
Expand Down Expand Up @@ -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++;
}
Expand All @@ -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("------------------------- ");
Expand Down

0 comments on commit 1dab672

Please sign in to comment.