2005-04-16 22:20:36 +00:00
|
|
|
/* Simple code to turn various tables in an ELF file into alias definitions.
|
|
|
|
* This deals with kernel datastructures where they should be
|
|
|
|
* dealt with: in the kernel source.
|
|
|
|
*
|
|
|
|
* Copyright 2002-2003 Rusty Russell, IBM Corporation
|
|
|
|
* 2003 Kai Germaschewski
|
|
|
|
*
|
|
|
|
*
|
|
|
|
* This software may be used and distributed according to the terms
|
|
|
|
* of the GNU General Public License, incorporated herein by reference.
|
|
|
|
*/
|
|
|
|
|
2024-11-19 23:56:41 +00:00
|
|
|
#include <stdarg.h>
|
|
|
|
#include <stdio.h>
|
|
|
|
|
|
|
|
#include "list.h"
|
|
|
|
#include "xalloc.h"
|
|
|
|
|
2005-04-16 22:20:36 +00:00
|
|
|
#include "modpost.h"
|
2013-01-20 16:58:47 +00:00
|
|
|
#include "devicetable-offsets.h"
|
2005-04-16 22:20:36 +00:00
|
|
|
|
|
|
|
/* We use the ELF typedefs for kernel_ulong_t but bite the bullet and
|
|
|
|
* use either stdint.h or inttypes.h for the rest. */
|
|
|
|
#if KERNEL_ELFCLASS == ELFCLASS32
|
|
|
|
typedef Elf32_Addr kernel_ulong_t;
|
2005-12-07 20:40:34 +00:00
|
|
|
#define BITS_PER_LONG 32
|
2005-04-16 22:20:36 +00:00
|
|
|
#else
|
|
|
|
typedef Elf64_Addr kernel_ulong_t;
|
2005-12-07 20:40:34 +00:00
|
|
|
#define BITS_PER_LONG 64
|
2005-04-16 22:20:36 +00:00
|
|
|
#endif
|
|
|
|
#ifdef __sun__
|
|
|
|
#include <inttypes.h>
|
|
|
|
#else
|
|
|
|
#include <stdint.h>
|
|
|
|
#endif
|
|
|
|
|
2005-07-06 19:44:41 +00:00
|
|
|
#include <ctype.h>
|
2012-01-12 23:02:15 +00:00
|
|
|
#include <stdbool.h>
|
2005-07-06 19:44:41 +00:00
|
|
|
|
2024-11-19 23:56:41 +00:00
|
|
|
/**
|
|
|
|
* module_alias_printf - add auto-generated MODULE_ALIAS()
|
|
|
|
*
|
|
|
|
* @mod: module
|
|
|
|
* @append_wildcard: append '*' for future extension if not exist yet
|
|
|
|
* @fmt: printf(3)-like format
|
|
|
|
*/
|
|
|
|
static void __attribute__((format (printf, 3, 4)))
|
|
|
|
module_alias_printf(struct module *mod, bool append_wildcard,
|
|
|
|
const char *fmt, ...)
|
|
|
|
{
|
modpost: deduplicate MODULE_ALIAS() for all drivers
MODULE_DEVICE_TABLE(pnp_card, ...) may have duplicated IDs. For
instance, snd_ad1816a_pnpids[] in sound/isa/ad1816a/ad1816a.c includes
multiple occurrences of the "ADS7180" string within its .devs fields.
Currently, do_pnp_card_entries() handles deduplication on its own, but
this logic should be moved to a common helper function, as drivers in
other subsystems might also have similar duplication issues.
For example, drivers/media/i2c/s5c73m3/s5c73m3.mod.c contains duplicated
MODULE_ALIAS() entries because both s5c73m3-core.c and s5c73m3-spi.c
define the same compatible string.
This commit eliminates redundant MODULE_ALIAS() entries across all
drivers.
[Before]
$ grep MODULE_ALIAS drivers/media/i2c/s5c73m3/s5c73m3.mod.c
MODULE_ALIAS("i2c:S5C73M3");
MODULE_ALIAS("of:N*T*Csamsung,s5c73m3");
MODULE_ALIAS("of:N*T*Csamsung,s5c73m3C*");
MODULE_ALIAS("of:N*T*Csamsung,s5c73m3");
MODULE_ALIAS("of:N*T*Csamsung,s5c73m3C*");
[After]
$ grep MODULE_ALIAS drivers/media/i2c/s5c73m3/s5c73m3.mod.c
MODULE_ALIAS("i2c:S5C73M3");
MODULE_ALIAS("of:N*T*Csamsung,s5c73m3");
MODULE_ALIAS("of:N*T*Csamsung,s5c73m3C*");
Signed-off-by: Masahiro Yamada <masahiroy@kernel.org>
2024-11-19 23:56:42 +00:00
|
|
|
struct module_alias *new, *als;
|
2024-11-19 23:56:41 +00:00
|
|
|
size_t len;
|
|
|
|
int n;
|
|
|
|
va_list ap;
|
|
|
|
|
|
|
|
/* Determine required size. */
|
|
|
|
va_start(ap, fmt);
|
|
|
|
n = vsnprintf(NULL, 0, fmt, ap);
|
|
|
|
va_end(ap);
|
|
|
|
|
|
|
|
if (n < 0) {
|
|
|
|
error("vsnprintf failed\n");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
len = n + 1; /* extra byte for '\0' */
|
|
|
|
|
|
|
|
if (append_wildcard)
|
|
|
|
len++; /* extra byte for '*' */
|
|
|
|
|
|
|
|
new = xmalloc(sizeof(*new) + len);
|
|
|
|
|
|
|
|
/* Now, really print it to the allocated buffer */
|
|
|
|
va_start(ap, fmt);
|
|
|
|
n = vsnprintf(new->str, len, fmt, ap);
|
|
|
|
va_end(ap);
|
|
|
|
|
|
|
|
if (n < 0) {
|
|
|
|
error("vsnprintf failed\n");
|
|
|
|
free(new);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (append_wildcard && (n == 0 || new->str[n - 1] != '*')) {
|
|
|
|
new->str[n] = '*';
|
|
|
|
new->str[n + 1] = '\0';
|
|
|
|
}
|
|
|
|
|
modpost: deduplicate MODULE_ALIAS() for all drivers
MODULE_DEVICE_TABLE(pnp_card, ...) may have duplicated IDs. For
instance, snd_ad1816a_pnpids[] in sound/isa/ad1816a/ad1816a.c includes
multiple occurrences of the "ADS7180" string within its .devs fields.
Currently, do_pnp_card_entries() handles deduplication on its own, but
this logic should be moved to a common helper function, as drivers in
other subsystems might also have similar duplication issues.
For example, drivers/media/i2c/s5c73m3/s5c73m3.mod.c contains duplicated
MODULE_ALIAS() entries because both s5c73m3-core.c and s5c73m3-spi.c
define the same compatible string.
This commit eliminates redundant MODULE_ALIAS() entries across all
drivers.
[Before]
$ grep MODULE_ALIAS drivers/media/i2c/s5c73m3/s5c73m3.mod.c
MODULE_ALIAS("i2c:S5C73M3");
MODULE_ALIAS("of:N*T*Csamsung,s5c73m3");
MODULE_ALIAS("of:N*T*Csamsung,s5c73m3C*");
MODULE_ALIAS("of:N*T*Csamsung,s5c73m3");
MODULE_ALIAS("of:N*T*Csamsung,s5c73m3C*");
[After]
$ grep MODULE_ALIAS drivers/media/i2c/s5c73m3/s5c73m3.mod.c
MODULE_ALIAS("i2c:S5C73M3");
MODULE_ALIAS("of:N*T*Csamsung,s5c73m3");
MODULE_ALIAS("of:N*T*Csamsung,s5c73m3C*");
Signed-off-by: Masahiro Yamada <masahiroy@kernel.org>
2024-11-19 23:56:42 +00:00
|
|
|
/* avoid duplication */
|
|
|
|
list_for_each_entry(als, &mod->aliases, node) {
|
|
|
|
if (!strcmp(als->str, new->str)) {
|
|
|
|
free(new);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-11-19 23:56:41 +00:00
|
|
|
list_add_tail(&new->node, &mod->aliases);
|
|
|
|
}
|
|
|
|
|
2005-04-16 22:20:36 +00:00
|
|
|
typedef uint32_t __u32;
|
|
|
|
typedef uint16_t __u16;
|
|
|
|
typedef unsigned char __u8;
|
2022-11-25 10:12:49 +00:00
|
|
|
|
|
|
|
/* UUID types for backward compatibility, don't use in new code */
|
2019-08-27 11:14:37 +00:00
|
|
|
typedef struct {
|
|
|
|
__u8 b[16];
|
|
|
|
} guid_t;
|
|
|
|
|
2019-01-29 05:49:35 +00:00
|
|
|
typedef struct {
|
|
|
|
__u8 b[16];
|
|
|
|
} uuid_t;
|
2022-11-25 10:12:49 +00:00
|
|
|
|
2019-02-19 19:59:49 +00:00
|
|
|
#define UUID_STRING_LEN 36
|
2005-04-16 22:20:36 +00:00
|
|
|
|
2022-11-25 10:12:49 +00:00
|
|
|
/* MEI UUID type, don't use anywhere else */
|
|
|
|
typedef struct {
|
|
|
|
__u8 b[16];
|
|
|
|
} uuid_le;
|
|
|
|
|
2005-04-16 22:20:36 +00:00
|
|
|
/* Big exception to the "don't include kernel headers into userspace, which
|
2006-03-03 15:46:04 +00:00
|
|
|
* even potentially has different endianness and word sizes, since
|
2005-04-16 22:20:36 +00:00
|
|
|
* we handle those differences explicitly below */
|
|
|
|
#include "../../include/linux/mod_devicetable.h"
|
|
|
|
|
2012-01-12 23:02:16 +00:00
|
|
|
struct devtable {
|
2024-11-19 23:56:52 +00:00
|
|
|
const char *device_id;
|
2012-01-12 23:02:16 +00:00
|
|
|
unsigned long id_size;
|
2024-11-19 23:56:45 +00:00
|
|
|
void (*do_entry)(struct module *mod, void *symval);
|
2012-01-12 23:02:16 +00:00
|
|
|
};
|
|
|
|
|
2013-01-20 16:58:47 +00:00
|
|
|
/* Define a variable f that holds the value of field f of struct devid
|
|
|
|
* based at address m.
|
|
|
|
*/
|
|
|
|
#define DEF_FIELD(m, devid, f) \
|
|
|
|
typeof(((struct devid *)0)->f) f = TO_NATIVE(*(typeof(f) *)((m) + OFF_##devid##_##f))
|
2018-10-24 04:03:52 +00:00
|
|
|
|
2013-01-20 16:58:47 +00:00
|
|
|
/* Define a variable f that holds the address of field f of struct devid
|
|
|
|
* based at address m. Due to the way typeof works, for a field of type
|
|
|
|
* T[N] the variable has type T(*)[N], _not_ T*.
|
|
|
|
*/
|
|
|
|
#define DEF_FIELD_ADDR(m, devid, f) \
|
2024-11-19 23:56:43 +00:00
|
|
|
typeof(((struct devid *)0)->f) *f = ((m) + OFF_##devid##_##f)
|
2013-01-20 16:58:47 +00:00
|
|
|
|
2005-04-16 22:20:36 +00:00
|
|
|
#define ADD(str, sep, cond, field) \
|
|
|
|
do { \
|
|
|
|
strcat(str, sep); \
|
|
|
|
if (cond) \
|
|
|
|
sprintf(str + strlen(str), \
|
|
|
|
sizeof(field) == 1 ? "%02X" : \
|
|
|
|
sizeof(field) == 2 ? "%04X" : \
|
|
|
|
sizeof(field) == 4 ? "%08X" : "", \
|
|
|
|
field); \
|
|
|
|
else \
|
|
|
|
sprintf(str + strlen(str), "*"); \
|
|
|
|
} while(0)
|
|
|
|
|
2015-05-28 00:17:27 +00:00
|
|
|
static inline void add_uuid(char *str, uuid_le uuid)
|
2015-05-07 12:54:02 +00:00
|
|
|
{
|
|
|
|
int len = strlen(str);
|
|
|
|
|
2015-09-10 07:17:59 +00:00
|
|
|
sprintf(str + len, "%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x",
|
|
|
|
uuid.b[3], uuid.b[2], uuid.b[1], uuid.b[0],
|
|
|
|
uuid.b[5], uuid.b[4], uuid.b[7], uuid.b[6],
|
|
|
|
uuid.b[8], uuid.b[9], uuid.b[10], uuid.b[11],
|
|
|
|
uuid.b[12], uuid.b[13], uuid.b[14], uuid.b[15]);
|
2015-05-07 12:54:02 +00:00
|
|
|
}
|
|
|
|
|
2021-10-29 15:28:56 +00:00
|
|
|
static inline void add_guid(char *str, guid_t guid)
|
|
|
|
{
|
|
|
|
int len = strlen(str);
|
|
|
|
|
|
|
|
sprintf(str + len, "%02X%02X%02X%02X-%02X%02X-%02X%02X-%02X%02X-%02X%02X%02X%02X%02X%02X",
|
|
|
|
guid.b[3], guid.b[2], guid.b[1], guid.b[0],
|
|
|
|
guid.b[5], guid.b[4], guid.b[7], guid.b[6],
|
|
|
|
guid.b[8], guid.b[9], guid.b[10], guid.b[11],
|
|
|
|
guid.b[12], guid.b[13], guid.b[14], guid.b[15]);
|
|
|
|
}
|
|
|
|
|
2005-04-22 22:07:01 +00:00
|
|
|
/* USB is special because the bcdDevice can be matched against a numeric range */
|
2012-05-18 19:27:43 +00:00
|
|
|
/* Looks like "usb:vNpNdNdcNdscNdpNicNiscNipNinN" */
|
2013-01-20 16:58:47 +00:00
|
|
|
static void do_usb_entry(void *symval,
|
2005-04-22 22:07:01 +00:00
|
|
|
unsigned int bcdDevice_initial, int bcdDevice_initial_digits,
|
|
|
|
unsigned char range_lo, unsigned char range_hi,
|
2009-11-19 01:11:23 +00:00
|
|
|
unsigned char max, struct module *mod)
|
2005-04-16 22:20:36 +00:00
|
|
|
{
|
2005-04-22 22:07:01 +00:00
|
|
|
char alias[500];
|
2013-01-20 16:58:47 +00:00
|
|
|
DEF_FIELD(symval, usb_device_id, match_flags);
|
|
|
|
DEF_FIELD(symval, usb_device_id, idVendor);
|
|
|
|
DEF_FIELD(symval, usb_device_id, idProduct);
|
|
|
|
DEF_FIELD(symval, usb_device_id, bcdDevice_lo);
|
|
|
|
DEF_FIELD(symval, usb_device_id, bDeviceClass);
|
|
|
|
DEF_FIELD(symval, usb_device_id, bDeviceSubClass);
|
|
|
|
DEF_FIELD(symval, usb_device_id, bDeviceProtocol);
|
|
|
|
DEF_FIELD(symval, usb_device_id, bInterfaceClass);
|
|
|
|
DEF_FIELD(symval, usb_device_id, bInterfaceSubClass);
|
|
|
|
DEF_FIELD(symval, usb_device_id, bInterfaceProtocol);
|
|
|
|
DEF_FIELD(symval, usb_device_id, bInterfaceNumber);
|
|
|
|
|
2005-04-16 22:20:36 +00:00
|
|
|
strcpy(alias, "usb:");
|
2013-01-20 16:58:47 +00:00
|
|
|
ADD(alias, "v", match_flags&USB_DEVICE_ID_MATCH_VENDOR,
|
|
|
|
idVendor);
|
|
|
|
ADD(alias, "p", match_flags&USB_DEVICE_ID_MATCH_PRODUCT,
|
|
|
|
idProduct);
|
2005-04-22 22:07:01 +00:00
|
|
|
|
|
|
|
strcat(alias, "d");
|
|
|
|
if (bcdDevice_initial_digits)
|
|
|
|
sprintf(alias + strlen(alias), "%0*X",
|
|
|
|
bcdDevice_initial_digits, bcdDevice_initial);
|
|
|
|
if (range_lo == range_hi)
|
2009-11-19 01:11:23 +00:00
|
|
|
sprintf(alias + strlen(alias), "%X", range_lo);
|
|
|
|
else if (range_lo > 0 || range_hi < max) {
|
|
|
|
if (range_lo > 0x9 || range_hi < 0xA)
|
|
|
|
sprintf(alias + strlen(alias),
|
|
|
|
"[%X-%X]",
|
|
|
|
range_lo,
|
|
|
|
range_hi);
|
|
|
|
else {
|
|
|
|
sprintf(alias + strlen(alias),
|
|
|
|
range_lo < 0x9 ? "[%X-9" : "[%X",
|
|
|
|
range_lo);
|
|
|
|
sprintf(alias + strlen(alias),
|
2014-02-07 18:15:11 +00:00
|
|
|
range_hi > 0xA ? "A-%X]" : "%X]",
|
|
|
|
range_hi);
|
2009-11-19 01:11:23 +00:00
|
|
|
}
|
|
|
|
}
|
2013-01-20 16:58:47 +00:00
|
|
|
if (bcdDevice_initial_digits < (sizeof(bcdDevice_lo) * 2 - 1))
|
2005-04-22 22:07:01 +00:00
|
|
|
strcat(alias, "*");
|
|
|
|
|
2013-01-20 16:58:47 +00:00
|
|
|
ADD(alias, "dc", match_flags&USB_DEVICE_ID_MATCH_DEV_CLASS,
|
|
|
|
bDeviceClass);
|
|
|
|
ADD(alias, "dsc", match_flags&USB_DEVICE_ID_MATCH_DEV_SUBCLASS,
|
|
|
|
bDeviceSubClass);
|
|
|
|
ADD(alias, "dp", match_flags&USB_DEVICE_ID_MATCH_DEV_PROTOCOL,
|
|
|
|
bDeviceProtocol);
|
|
|
|
ADD(alias, "ic", match_flags&USB_DEVICE_ID_MATCH_INT_CLASS,
|
|
|
|
bInterfaceClass);
|
|
|
|
ADD(alias, "isc", match_flags&USB_DEVICE_ID_MATCH_INT_SUBCLASS,
|
|
|
|
bInterfaceSubClass);
|
|
|
|
ADD(alias, "ip", match_flags&USB_DEVICE_ID_MATCH_INT_PROTOCOL,
|
|
|
|
bInterfaceProtocol);
|
|
|
|
ADD(alias, "in", match_flags&USB_DEVICE_ID_MATCH_INT_NUMBER,
|
|
|
|
bInterfaceNumber);
|
2005-04-22 22:07:01 +00:00
|
|
|
|
2024-11-19 23:56:41 +00:00
|
|
|
module_alias_printf(mod, true, "%s", alias);
|
2005-04-22 22:07:01 +00:00
|
|
|
}
|
|
|
|
|
2009-11-19 01:15:28 +00:00
|
|
|
/* Handles increment/decrement of BCD formatted integers */
|
|
|
|
/* Returns the previous value, so it works like i++ or i-- */
|
|
|
|
static unsigned int incbcd(unsigned int *bcd,
|
|
|
|
int inc,
|
|
|
|
unsigned char max,
|
|
|
|
size_t chars)
|
|
|
|
{
|
|
|
|
unsigned int init = *bcd, i, j;
|
|
|
|
unsigned long long c, dec = 0;
|
|
|
|
|
|
|
|
/* If bcd is not in BCD format, just increment */
|
|
|
|
if (max > 0x9) {
|
|
|
|
*bcd += inc;
|
|
|
|
return init;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Convert BCD to Decimal */
|
|
|
|
for (i=0 ; i < chars ; i++) {
|
|
|
|
c = (*bcd >> (i << 2)) & 0xf;
|
|
|
|
c = c > 9 ? 9 : c; /* force to bcd just in case */
|
|
|
|
for (j=0 ; j < i ; j++)
|
|
|
|
c = c * 10;
|
|
|
|
dec += c;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Do our increment/decrement */
|
|
|
|
dec += inc;
|
|
|
|
*bcd = 0;
|
|
|
|
|
|
|
|
/* Convert back to BCD */
|
|
|
|
for (i=0 ; i < chars ; i++) {
|
|
|
|
for (c=1,j=0 ; j < i ; j++)
|
|
|
|
c = c * 10;
|
|
|
|
c = (dec / c) % 10;
|
|
|
|
*bcd += c << (i << 2);
|
|
|
|
}
|
|
|
|
return init;
|
|
|
|
}
|
|
|
|
|
2024-11-19 23:56:49 +00:00
|
|
|
static void do_usb_entry_multi(struct module *mod, void *symval)
|
2005-04-22 22:07:01 +00:00
|
|
|
{
|
|
|
|
unsigned int devlo, devhi;
|
2009-11-19 01:11:23 +00:00
|
|
|
unsigned char chi, clo, max;
|
2005-04-22 22:07:01 +00:00
|
|
|
int ndigits;
|
|
|
|
|
2013-01-20 16:58:47 +00:00
|
|
|
DEF_FIELD(symval, usb_device_id, match_flags);
|
|
|
|
DEF_FIELD(symval, usb_device_id, idVendor);
|
|
|
|
DEF_FIELD(symval, usb_device_id, idProduct);
|
|
|
|
DEF_FIELD(symval, usb_device_id, bcdDevice_lo);
|
|
|
|
DEF_FIELD(symval, usb_device_id, bcdDevice_hi);
|
|
|
|
DEF_FIELD(symval, usb_device_id, bDeviceClass);
|
|
|
|
DEF_FIELD(symval, usb_device_id, bInterfaceClass);
|
2005-04-22 22:07:01 +00:00
|
|
|
|
2013-01-20 16:58:47 +00:00
|
|
|
devlo = match_flags & USB_DEVICE_ID_MATCH_DEV_LO ?
|
|
|
|
bcdDevice_lo : 0x0U;
|
|
|
|
devhi = match_flags & USB_DEVICE_ID_MATCH_DEV_HI ?
|
|
|
|
bcdDevice_hi : ~0x0U;
|
2005-04-22 22:07:01 +00:00
|
|
|
|
2009-11-19 01:11:23 +00:00
|
|
|
/* Figure out if this entry is in bcd or hex format */
|
|
|
|
max = 0x9; /* Default to decimal format */
|
2013-01-20 16:58:47 +00:00
|
|
|
for (ndigits = 0 ; ndigits < sizeof(bcdDevice_lo) * 2 ; ndigits++) {
|
2009-11-19 01:11:23 +00:00
|
|
|
clo = (devlo >> (ndigits << 2)) & 0xf;
|
|
|
|
chi = ((devhi > 0x9999 ? 0x9999 : devhi) >> (ndigits << 2)) & 0xf;
|
|
|
|
if (clo > max || chi > max) {
|
|
|
|
max = 0xf;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2005-04-22 22:07:01 +00:00
|
|
|
/*
|
|
|
|
* Some modules (visor) have empty slots as placeholder for
|
|
|
|
* run-time specification that results in catch-all alias
|
|
|
|
*/
|
2013-01-20 16:58:47 +00:00
|
|
|
if (!(idVendor | idProduct | bDeviceClass | bInterfaceClass))
|
2005-04-22 22:07:01 +00:00
|
|
|
return;
|
|
|
|
|
|
|
|
/* Convert numeric bcdDevice range into fnmatch-able pattern(s) */
|
2013-01-20 16:58:47 +00:00
|
|
|
for (ndigits = sizeof(bcdDevice_lo) * 2 - 1; devlo <= devhi; ndigits--) {
|
2005-04-22 22:07:01 +00:00
|
|
|
clo = devlo & 0xf;
|
|
|
|
chi = devhi & 0xf;
|
2009-11-19 01:11:23 +00:00
|
|
|
if (chi > max) /* If we are in bcd mode, truncate if necessary */
|
|
|
|
chi = max;
|
2005-04-22 22:07:01 +00:00
|
|
|
devlo >>= 4;
|
|
|
|
devhi >>= 4;
|
|
|
|
|
|
|
|
if (devlo == devhi || !ndigits) {
|
2013-01-20 16:58:47 +00:00
|
|
|
do_usb_entry(symval, devlo, ndigits, clo, chi, max, mod);
|
2005-04-22 22:07:01 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2009-11-19 01:11:23 +00:00
|
|
|
if (clo > 0x0)
|
2013-01-20 16:58:47 +00:00
|
|
|
do_usb_entry(symval,
|
2009-11-19 01:15:28 +00:00
|
|
|
incbcd(&devlo, 1, max,
|
2013-01-20 16:58:47 +00:00
|
|
|
sizeof(bcdDevice_lo) * 2),
|
2009-11-19 01:15:28 +00:00
|
|
|
ndigits, clo, max, max, mod);
|
2005-04-22 22:07:01 +00:00
|
|
|
|
2009-11-19 01:11:23 +00:00
|
|
|
if (chi < max)
|
2013-01-20 16:58:47 +00:00
|
|
|
do_usb_entry(symval,
|
2009-11-19 01:15:28 +00:00
|
|
|
incbcd(&devhi, -1, max,
|
2013-01-20 16:58:47 +00:00
|
|
|
sizeof(bcdDevice_lo) * 2),
|
2009-11-19 01:15:28 +00:00
|
|
|
ndigits, 0x0, chi, max, mod);
|
2005-04-22 22:07:01 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-11-19 23:56:48 +00:00
|
|
|
static void do_of_entry(struct module *mod, void *symval)
|
modpost: fix module autoloading for OF devices with generic compatible property
Since the wildcard at the end of OF module aliases is gone, autoloading
of modules that don't match a device's last (most generic) compatible
value fails.
For example the CODA960 VPU on i.MX6Q has the SoC specific compatible
"fsl,imx6q-vpu" and the generic compatible "cnm,coda960". Since the
driver currently only works with knowledge about the SoC specific
integration, it doesn't list "cnm,cod960" in the module device table.
This results in the device compatible
"of:NvpuT<NULL>Cfsl,imx6q-vpuCcnm,coda960" not matching the module alias
"of:N*T*Cfsl,imx6q-vpu" anymore, whereas before commit 2f632369ab79
("modpost: don't add a trailing wildcard for OF module aliases") it
matched the module alias "of:N*T*Cfsl,imx6q-vpu*".
This patch adds two module aliases for each compatible, one without the
wildcard and one with "C*" appended.
$ modinfo coda | grep imx6q
alias: of:N*T*Cfsl,imx6q-vpuC*
alias: of:N*T*Cfsl,imx6q-vpu
Fixes: 2f632369ab79 ("modpost: don't add a trailing wildcard for OF module aliases")
Link: http://lkml.kernel.org/r/1462203339-15340-1-git-send-email-p.zabel@pengutronix.de
Signed-off-by: Philipp Zabel <p.zabel@pengutronix.de>
Cc: Javier Martinez Canillas <javier@osg.samsung.com>
Cc: Brian Norris <computersforpeace@gmail.com>
Cc: Sjoerd Simons <sjoerd.simons@collabora.co.uk>
Cc: Rusty Russell <rusty@rustcorp.com.au>
Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Cc: <stable@vger.kernel.org> [4.5+]
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2016-05-05 23:22:29 +00:00
|
|
|
{
|
|
|
|
char alias[500];
|
|
|
|
int len;
|
|
|
|
char *tmp;
|
|
|
|
|
|
|
|
DEF_FIELD_ADDR(symval, of_device_id, name);
|
|
|
|
DEF_FIELD_ADDR(symval, of_device_id, type);
|
|
|
|
DEF_FIELD_ADDR(symval, of_device_id, compatible);
|
|
|
|
|
|
|
|
len = sprintf(alias, "of:N%sT%s", (*name)[0] ? *name : "*",
|
|
|
|
(*type)[0] ? *type : "*");
|
|
|
|
|
2016-06-06 16:48:38 +00:00
|
|
|
if ((*compatible)[0])
|
modpost: fix module autoloading for OF devices with generic compatible property
Since the wildcard at the end of OF module aliases is gone, autoloading
of modules that don't match a device's last (most generic) compatible
value fails.
For example the CODA960 VPU on i.MX6Q has the SoC specific compatible
"fsl,imx6q-vpu" and the generic compatible "cnm,coda960". Since the
driver currently only works with knowledge about the SoC specific
integration, it doesn't list "cnm,cod960" in the module device table.
This results in the device compatible
"of:NvpuT<NULL>Cfsl,imx6q-vpuCcnm,coda960" not matching the module alias
"of:N*T*Cfsl,imx6q-vpu" anymore, whereas before commit 2f632369ab79
("modpost: don't add a trailing wildcard for OF module aliases") it
matched the module alias "of:N*T*Cfsl,imx6q-vpu*".
This patch adds two module aliases for each compatible, one without the
wildcard and one with "C*" appended.
$ modinfo coda | grep imx6q
alias: of:N*T*Cfsl,imx6q-vpuC*
alias: of:N*T*Cfsl,imx6q-vpu
Fixes: 2f632369ab79 ("modpost: don't add a trailing wildcard for OF module aliases")
Link: http://lkml.kernel.org/r/1462203339-15340-1-git-send-email-p.zabel@pengutronix.de
Signed-off-by: Philipp Zabel <p.zabel@pengutronix.de>
Cc: Javier Martinez Canillas <javier@osg.samsung.com>
Cc: Brian Norris <computersforpeace@gmail.com>
Cc: Sjoerd Simons <sjoerd.simons@collabora.co.uk>
Cc: Rusty Russell <rusty@rustcorp.com.au>
Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Cc: <stable@vger.kernel.org> [4.5+]
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2016-05-05 23:22:29 +00:00
|
|
|
sprintf(&alias[len], "%sC%s", (*type)[0] ? "*" : "",
|
|
|
|
*compatible);
|
|
|
|
|
|
|
|
/* Replace all whitespace with underscores */
|
|
|
|
for (tmp = alias; tmp && *tmp; tmp++)
|
|
|
|
if (isspace(*tmp))
|
|
|
|
*tmp = '_';
|
|
|
|
|
2024-11-19 23:56:41 +00:00
|
|
|
module_alias_printf(mod, false, "%s", alias);
|
|
|
|
module_alias_printf(mod, false, "%sC*", alias);
|
modpost: fix module autoloading for OF devices with generic compatible property
Since the wildcard at the end of OF module aliases is gone, autoloading
of modules that don't match a device's last (most generic) compatible
value fails.
For example the CODA960 VPU on i.MX6Q has the SoC specific compatible
"fsl,imx6q-vpu" and the generic compatible "cnm,coda960". Since the
driver currently only works with knowledge about the SoC specific
integration, it doesn't list "cnm,cod960" in the module device table.
This results in the device compatible
"of:NvpuT<NULL>Cfsl,imx6q-vpuCcnm,coda960" not matching the module alias
"of:N*T*Cfsl,imx6q-vpu" anymore, whereas before commit 2f632369ab79
("modpost: don't add a trailing wildcard for OF module aliases") it
matched the module alias "of:N*T*Cfsl,imx6q-vpu*".
This patch adds two module aliases for each compatible, one without the
wildcard and one with "C*" appended.
$ modinfo coda | grep imx6q
alias: of:N*T*Cfsl,imx6q-vpuC*
alias: of:N*T*Cfsl,imx6q-vpu
Fixes: 2f632369ab79 ("modpost: don't add a trailing wildcard for OF module aliases")
Link: http://lkml.kernel.org/r/1462203339-15340-1-git-send-email-p.zabel@pengutronix.de
Signed-off-by: Philipp Zabel <p.zabel@pengutronix.de>
Cc: Javier Martinez Canillas <javier@osg.samsung.com>
Cc: Brian Norris <computersforpeace@gmail.com>
Cc: Sjoerd Simons <sjoerd.simons@collabora.co.uk>
Cc: Rusty Russell <rusty@rustcorp.com.au>
Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Cc: <stable@vger.kernel.org> [4.5+]
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2016-05-05 23:22:29 +00:00
|
|
|
}
|
|
|
|
|
2008-05-19 13:50:01 +00:00
|
|
|
/* Looks like: hid:bNvNpN */
|
2024-11-19 23:56:45 +00:00
|
|
|
static void do_hid_entry(struct module *mod, void *symval)
|
2008-05-19 13:50:01 +00:00
|
|
|
{
|
2024-11-19 23:56:45 +00:00
|
|
|
char alias[256] = {};
|
|
|
|
|
2013-01-20 16:58:47 +00:00
|
|
|
DEF_FIELD(symval, hid_device_id, bus);
|
|
|
|
DEF_FIELD(symval, hid_device_id, group);
|
|
|
|
DEF_FIELD(symval, hid_device_id, vendor);
|
|
|
|
DEF_FIELD(symval, hid_device_id, product);
|
2008-05-19 13:50:01 +00:00
|
|
|
|
2013-01-20 16:58:47 +00:00
|
|
|
ADD(alias, "b", bus != HID_BUS_ANY, bus);
|
|
|
|
ADD(alias, "g", group != HID_GROUP_ANY, group);
|
|
|
|
ADD(alias, "v", vendor != HID_ANY_ID, vendor);
|
|
|
|
ADD(alias, "p", product != HID_ANY_ID, product);
|
2008-05-19 13:50:01 +00:00
|
|
|
|
2024-11-19 23:56:45 +00:00
|
|
|
module_alias_printf(mod, false, "hid:%s", alias);
|
2008-05-19 13:50:01 +00:00
|
|
|
}
|
|
|
|
|
2005-04-16 22:20:36 +00:00
|
|
|
/* Looks like: ieee1394:venNmoNspNverN */
|
2024-11-19 23:56:45 +00:00
|
|
|
static void do_ieee1394_entry(struct module *mod, void *symval)
|
2005-04-16 22:20:36 +00:00
|
|
|
{
|
2024-11-19 23:56:45 +00:00
|
|
|
char alias[256] = {};
|
|
|
|
|
2013-01-20 16:58:47 +00:00
|
|
|
DEF_FIELD(symval, ieee1394_device_id, match_flags);
|
|
|
|
DEF_FIELD(symval, ieee1394_device_id, vendor_id);
|
|
|
|
DEF_FIELD(symval, ieee1394_device_id, model_id);
|
|
|
|
DEF_FIELD(symval, ieee1394_device_id, specifier_id);
|
|
|
|
DEF_FIELD(symval, ieee1394_device_id, version);
|
2005-04-16 22:20:36 +00:00
|
|
|
|
2013-01-20 16:58:47 +00:00
|
|
|
ADD(alias, "ven", match_flags & IEEE1394_MATCH_VENDOR_ID,
|
|
|
|
vendor_id);
|
|
|
|
ADD(alias, "mo", match_flags & IEEE1394_MATCH_MODEL_ID,
|
|
|
|
model_id);
|
|
|
|
ADD(alias, "sp", match_flags & IEEE1394_MATCH_SPECIFIER_ID,
|
|
|
|
specifier_id);
|
|
|
|
ADD(alias, "ver", match_flags & IEEE1394_MATCH_VERSION,
|
|
|
|
version);
|
2005-04-16 22:20:36 +00:00
|
|
|
|
2024-11-19 23:56:45 +00:00
|
|
|
module_alias_printf(mod, true, "ieee1394:%s", alias);
|
2005-04-16 22:20:36 +00:00
|
|
|
}
|
|
|
|
|
2021-08-26 10:39:09 +00:00
|
|
|
/* Looks like: pci:vNdNsvNsdNbcNscNiN or <prefix>_pci:vNdNsvNsdNbcNscNiN. */
|
2024-11-19 23:56:45 +00:00
|
|
|
static void do_pci_entry(struct module *mod, void *symval)
|
2005-04-16 22:20:36 +00:00
|
|
|
{
|
2024-11-19 23:56:45 +00:00
|
|
|
char alias[256];
|
2005-04-16 22:20:36 +00:00
|
|
|
/* Class field can be divided into these three. */
|
|
|
|
unsigned char baseclass, subclass, interface,
|
|
|
|
baseclass_mask, subclass_mask, interface_mask;
|
|
|
|
|
2013-01-20 16:58:47 +00:00
|
|
|
DEF_FIELD(symval, pci_device_id, vendor);
|
|
|
|
DEF_FIELD(symval, pci_device_id, device);
|
|
|
|
DEF_FIELD(symval, pci_device_id, subvendor);
|
|
|
|
DEF_FIELD(symval, pci_device_id, subdevice);
|
|
|
|
DEF_FIELD(symval, pci_device_id, class);
|
|
|
|
DEF_FIELD(symval, pci_device_id, class_mask);
|
2021-08-26 10:39:09 +00:00
|
|
|
DEF_FIELD(symval, pci_device_id, override_only);
|
|
|
|
|
|
|
|
switch (override_only) {
|
|
|
|
case 0:
|
|
|
|
strcpy(alias, "pci:");
|
|
|
|
break;
|
|
|
|
case PCI_ID_F_VFIO_DRIVER_OVERRIDE:
|
|
|
|
strcpy(alias, "vfio_pci:");
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
warn("Unknown PCI driver_override alias %08X\n",
|
|
|
|
override_only);
|
|
|
|
}
|
2005-04-16 22:20:36 +00:00
|
|
|
|
2013-01-20 16:58:47 +00:00
|
|
|
ADD(alias, "v", vendor != PCI_ANY_ID, vendor);
|
|
|
|
ADD(alias, "d", device != PCI_ANY_ID, device);
|
|
|
|
ADD(alias, "sv", subvendor != PCI_ANY_ID, subvendor);
|
|
|
|
ADD(alias, "sd", subdevice != PCI_ANY_ID, subdevice);
|
|
|
|
|
|
|
|
baseclass = (class) >> 16;
|
|
|
|
baseclass_mask = (class_mask) >> 16;
|
|
|
|
subclass = (class) >> 8;
|
|
|
|
subclass_mask = (class_mask) >> 8;
|
|
|
|
interface = class;
|
|
|
|
interface_mask = class_mask;
|
2005-04-16 22:20:36 +00:00
|
|
|
|
|
|
|
if ((baseclass_mask != 0 && baseclass_mask != 0xFF)
|
|
|
|
|| (subclass_mask != 0 && subclass_mask != 0xFF)
|
|
|
|
|| (interface_mask != 0 && interface_mask != 0xFF)) {
|
2006-01-28 15:57:26 +00:00
|
|
|
warn("Can't handle masks in %s:%04X\n",
|
2024-11-19 23:56:44 +00:00
|
|
|
mod->name, class_mask);
|
2024-11-19 23:56:45 +00:00
|
|
|
return;
|
2005-04-16 22:20:36 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
ADD(alias, "bc", baseclass_mask == 0xFF, baseclass);
|
|
|
|
ADD(alias, "sc", subclass_mask == 0xFF, subclass);
|
|
|
|
ADD(alias, "i", interface_mask == 0xFF, interface);
|
2024-11-19 23:56:45 +00:00
|
|
|
|
|
|
|
module_alias_printf(mod, true, "%s", alias);
|
2005-04-16 22:20:36 +00:00
|
|
|
}
|
|
|
|
|
2006-03-03 15:46:04 +00:00
|
|
|
/* looks like: "ccw:tNmNdtNdmN" */
|
2024-11-19 23:56:45 +00:00
|
|
|
static void do_ccw_entry(struct module *mod, void *symval)
|
2005-04-16 22:20:36 +00:00
|
|
|
{
|
2024-11-19 23:56:45 +00:00
|
|
|
char alias[256] = {};
|
|
|
|
|
2013-01-20 16:58:47 +00:00
|
|
|
DEF_FIELD(symval, ccw_device_id, match_flags);
|
|
|
|
DEF_FIELD(symval, ccw_device_id, cu_type);
|
|
|
|
DEF_FIELD(symval, ccw_device_id, cu_model);
|
|
|
|
DEF_FIELD(symval, ccw_device_id, dev_type);
|
|
|
|
DEF_FIELD(symval, ccw_device_id, dev_model);
|
2005-04-16 22:20:36 +00:00
|
|
|
|
2013-01-20 16:58:47 +00:00
|
|
|
ADD(alias, "t", match_flags&CCW_DEVICE_ID_MATCH_CU_TYPE,
|
|
|
|
cu_type);
|
|
|
|
ADD(alias, "m", match_flags&CCW_DEVICE_ID_MATCH_CU_MODEL,
|
|
|
|
cu_model);
|
|
|
|
ADD(alias, "dt", match_flags&CCW_DEVICE_ID_MATCH_DEVICE_TYPE,
|
|
|
|
dev_type);
|
|
|
|
ADD(alias, "dm", match_flags&CCW_DEVICE_ID_MATCH_DEVICE_MODEL,
|
|
|
|
dev_model);
|
2024-11-19 23:56:45 +00:00
|
|
|
|
|
|
|
module_alias_printf(mod, true, "ccw:%s", alias);
|
2005-04-16 22:20:36 +00:00
|
|
|
}
|
|
|
|
|
2006-09-20 13:58:25 +00:00
|
|
|
/* looks like: "ap:tN" */
|
2024-11-19 23:56:45 +00:00
|
|
|
static void do_ap_entry(struct module *mod, void *symval)
|
2006-09-20 13:58:25 +00:00
|
|
|
{
|
2013-01-20 16:58:47 +00:00
|
|
|
DEF_FIELD(symval, ap_device_id, dev_type);
|
|
|
|
|
2024-11-19 23:56:45 +00:00
|
|
|
module_alias_printf(mod, false, "ap:t%02X*", dev_type);
|
2006-09-20 13:58:25 +00:00
|
|
|
}
|
|
|
|
|
2008-07-14 07:58:44 +00:00
|
|
|
/* looks like: "css:tN" */
|
2024-11-19 23:56:45 +00:00
|
|
|
static void do_css_entry(struct module *mod, void *symval)
|
2008-07-14 07:58:44 +00:00
|
|
|
{
|
2013-01-20 16:58:47 +00:00
|
|
|
DEF_FIELD(symval, css_device_id, type);
|
|
|
|
|
2024-11-19 23:56:45 +00:00
|
|
|
module_alias_printf(mod, false, "css:t%01X", type);
|
2008-07-14 07:58:44 +00:00
|
|
|
}
|
|
|
|
|
2005-04-16 22:20:36 +00:00
|
|
|
/* Looks like: "serio:tyNprNidNexN" */
|
2024-11-19 23:56:45 +00:00
|
|
|
static void do_serio_entry(struct module *mod, void *symval)
|
2005-04-16 22:20:36 +00:00
|
|
|
{
|
2024-11-19 23:56:45 +00:00
|
|
|
char alias[256] = {};
|
|
|
|
|
2013-01-20 16:58:47 +00:00
|
|
|
DEF_FIELD(symval, serio_device_id, type);
|
|
|
|
DEF_FIELD(symval, serio_device_id, proto);
|
|
|
|
DEF_FIELD(symval, serio_device_id, id);
|
|
|
|
DEF_FIELD(symval, serio_device_id, extra);
|
2005-04-16 22:20:36 +00:00
|
|
|
|
2013-01-20 16:58:47 +00:00
|
|
|
ADD(alias, "ty", type != SERIO_ANY, type);
|
|
|
|
ADD(alias, "pr", proto != SERIO_ANY, proto);
|
|
|
|
ADD(alias, "id", id != SERIO_ANY, id);
|
|
|
|
ADD(alias, "ex", extra != SERIO_ANY, extra);
|
2005-04-16 22:20:36 +00:00
|
|
|
|
2024-11-19 23:56:45 +00:00
|
|
|
module_alias_printf(mod, true, "serio:%s", alias);
|
2005-04-16 22:20:36 +00:00
|
|
|
}
|
|
|
|
|
ACPI / scan: Add support for ACPI _CLS device matching
Device drivers typically use ACPI _HIDs/_CIDs listed in struct device_driver
acpi_match_table to match devices. However, for generic drivers, we do not
want to list _HID for all supported devices. Also, certain classes of devices
do not have _CID (e.g. SATA, USB). Instead, we can leverage ACPI _CLS,
which specifies PCI-defined class code (i.e. base-class, subclass and
programming interface). This patch adds support for matching ACPI devices using
the _CLS method.
To support loadable module, current design uses _HID or _CID to match device's
modalias. With the new way of matching with _CLS this would requires modification
to the current ACPI modalias key to include _CLS. This patch appends PCI-defined
class-code to the existing ACPI modalias as following.
acpi:<HID>:<CID1>:<CID2>:..:<CIDn>:<bbsspp>:
E.g:
# cat /sys/devices/platform/AMDI0600:00/modalias
acpi:AMDI0600:010601:
where bb is th base-class code, ss is te sub-class code, and pp is the
programming interface code
Since there would not be _HID/_CID in the ACPI matching table of the driver,
this patch adds a field to acpi_device_id to specify the matching _CLS.
static const struct acpi_device_id ahci_acpi_match[] = {
{ ACPI_DEVICE_CLASS(PCI_CLASS_STORAGE_SATA_AHCI, 0xffffff) },
{},
};
In this case, the corresponded entry in modules.alias file would be:
alias acpi*:010601:* ahci_platform
Acked-by: Mika Westerberg <mika.westerberg@linux.intel.com>
Reviewed-by: Hanjun Guo <hanjun.guo@linaro.org>
Signed-off-by: Suravee Suthikulpanit <Suravee.Suthikulpanit@amd.com>
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
2015-07-06 23:55:20 +00:00
|
|
|
/* looks like: "acpi:ACPI0003" or "acpi:PNP0C0B" or "acpi:LNXVIDEO" or
|
|
|
|
* "acpi:bbsspp" (bb=base-class, ss=sub-class, pp=prog-if)
|
|
|
|
*
|
|
|
|
* NOTE: Each driver should use one of the following : _HID, _CIDs
|
|
|
|
* or _CLS. Also, bb, ss, and pp can be substituted with ??
|
|
|
|
* as don't care byte.
|
|
|
|
*/
|
2024-11-19 23:56:45 +00:00
|
|
|
static void do_acpi_entry(struct module *mod, void *symval)
|
2007-07-23 12:43:51 +00:00
|
|
|
{
|
2013-01-20 16:58:47 +00:00
|
|
|
DEF_FIELD_ADDR(symval, acpi_device_id, id);
|
2024-11-03 12:46:50 +00:00
|
|
|
DEF_FIELD(symval, acpi_device_id, cls);
|
|
|
|
DEF_FIELD(symval, acpi_device_id, cls_msk);
|
ACPI / scan: Add support for ACPI _CLS device matching
Device drivers typically use ACPI _HIDs/_CIDs listed in struct device_driver
acpi_match_table to match devices. However, for generic drivers, we do not
want to list _HID for all supported devices. Also, certain classes of devices
do not have _CID (e.g. SATA, USB). Instead, we can leverage ACPI _CLS,
which specifies PCI-defined class code (i.e. base-class, subclass and
programming interface). This patch adds support for matching ACPI devices using
the _CLS method.
To support loadable module, current design uses _HID or _CID to match device's
modalias. With the new way of matching with _CLS this would requires modification
to the current ACPI modalias key to include _CLS. This patch appends PCI-defined
class-code to the existing ACPI modalias as following.
acpi:<HID>:<CID1>:<CID2>:..:<CIDn>:<bbsspp>:
E.g:
# cat /sys/devices/platform/AMDI0600:00/modalias
acpi:AMDI0600:010601:
where bb is th base-class code, ss is te sub-class code, and pp is the
programming interface code
Since there would not be _HID/_CID in the ACPI matching table of the driver,
this patch adds a field to acpi_device_id to specify the matching _CLS.
static const struct acpi_device_id ahci_acpi_match[] = {
{ ACPI_DEVICE_CLASS(PCI_CLASS_STORAGE_SATA_AHCI, 0xffffff) },
{},
};
In this case, the corresponded entry in modules.alias file would be:
alias acpi*:010601:* ahci_platform
Acked-by: Mika Westerberg <mika.westerberg@linux.intel.com>
Reviewed-by: Hanjun Guo <hanjun.guo@linaro.org>
Signed-off-by: Suravee Suthikulpanit <Suravee.Suthikulpanit@amd.com>
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
2015-07-06 23:55:20 +00:00
|
|
|
|
2024-11-19 23:56:40 +00:00
|
|
|
if ((*id)[0])
|
2024-11-19 23:56:45 +00:00
|
|
|
module_alias_printf(mod, false, "acpi*:%s:*", *id);
|
2024-11-03 12:46:50 +00:00
|
|
|
else {
|
2024-11-19 23:56:45 +00:00
|
|
|
char alias[256];
|
ACPI / scan: Add support for ACPI _CLS device matching
Device drivers typically use ACPI _HIDs/_CIDs listed in struct device_driver
acpi_match_table to match devices. However, for generic drivers, we do not
want to list _HID for all supported devices. Also, certain classes of devices
do not have _CID (e.g. SATA, USB). Instead, we can leverage ACPI _CLS,
which specifies PCI-defined class code (i.e. base-class, subclass and
programming interface). This patch adds support for matching ACPI devices using
the _CLS method.
To support loadable module, current design uses _HID or _CID to match device's
modalias. With the new way of matching with _CLS this would requires modification
to the current ACPI modalias key to include _CLS. This patch appends PCI-defined
class-code to the existing ACPI modalias as following.
acpi:<HID>:<CID1>:<CID2>:..:<CIDn>:<bbsspp>:
E.g:
# cat /sys/devices/platform/AMDI0600:00/modalias
acpi:AMDI0600:010601:
where bb is th base-class code, ss is te sub-class code, and pp is the
programming interface code
Since there would not be _HID/_CID in the ACPI matching table of the driver,
this patch adds a field to acpi_device_id to specify the matching _CLS.
static const struct acpi_device_id ahci_acpi_match[] = {
{ ACPI_DEVICE_CLASS(PCI_CLASS_STORAGE_SATA_AHCI, 0xffffff) },
{},
};
In this case, the corresponded entry in modules.alias file would be:
alias acpi*:010601:* ahci_platform
Acked-by: Mika Westerberg <mika.westerberg@linux.intel.com>
Reviewed-by: Hanjun Guo <hanjun.guo@linaro.org>
Signed-off-by: Suravee Suthikulpanit <Suravee.Suthikulpanit@amd.com>
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
2015-07-06 23:55:20 +00:00
|
|
|
int i, byte_shift, cnt = 0;
|
|
|
|
unsigned int msk;
|
|
|
|
|
|
|
|
for (i = 1; i <= 3; i++) {
|
|
|
|
byte_shift = 8 * (3-i);
|
2024-11-03 12:46:50 +00:00
|
|
|
msk = (cls_msk >> byte_shift) & 0xFF;
|
ACPI / scan: Add support for ACPI _CLS device matching
Device drivers typically use ACPI _HIDs/_CIDs listed in struct device_driver
acpi_match_table to match devices. However, for generic drivers, we do not
want to list _HID for all supported devices. Also, certain classes of devices
do not have _CID (e.g. SATA, USB). Instead, we can leverage ACPI _CLS,
which specifies PCI-defined class code (i.e. base-class, subclass and
programming interface). This patch adds support for matching ACPI devices using
the _CLS method.
To support loadable module, current design uses _HID or _CID to match device's
modalias. With the new way of matching with _CLS this would requires modification
to the current ACPI modalias key to include _CLS. This patch appends PCI-defined
class-code to the existing ACPI modalias as following.
acpi:<HID>:<CID1>:<CID2>:..:<CIDn>:<bbsspp>:
E.g:
# cat /sys/devices/platform/AMDI0600:00/modalias
acpi:AMDI0600:010601:
where bb is th base-class code, ss is te sub-class code, and pp is the
programming interface code
Since there would not be _HID/_CID in the ACPI matching table of the driver,
this patch adds a field to acpi_device_id to specify the matching _CLS.
static const struct acpi_device_id ahci_acpi_match[] = {
{ ACPI_DEVICE_CLASS(PCI_CLASS_STORAGE_SATA_AHCI, 0xffffff) },
{},
};
In this case, the corresponded entry in modules.alias file would be:
alias acpi*:010601:* ahci_platform
Acked-by: Mika Westerberg <mika.westerberg@linux.intel.com>
Reviewed-by: Hanjun Guo <hanjun.guo@linaro.org>
Signed-off-by: Suravee Suthikulpanit <Suravee.Suthikulpanit@amd.com>
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
2015-07-06 23:55:20 +00:00
|
|
|
if (msk)
|
|
|
|
sprintf(&alias[cnt], "%02x",
|
2024-11-03 12:46:50 +00:00
|
|
|
(cls >> byte_shift) & 0xFF);
|
ACPI / scan: Add support for ACPI _CLS device matching
Device drivers typically use ACPI _HIDs/_CIDs listed in struct device_driver
acpi_match_table to match devices. However, for generic drivers, we do not
want to list _HID for all supported devices. Also, certain classes of devices
do not have _CID (e.g. SATA, USB). Instead, we can leverage ACPI _CLS,
which specifies PCI-defined class code (i.e. base-class, subclass and
programming interface). This patch adds support for matching ACPI devices using
the _CLS method.
To support loadable module, current design uses _HID or _CID to match device's
modalias. With the new way of matching with _CLS this would requires modification
to the current ACPI modalias key to include _CLS. This patch appends PCI-defined
class-code to the existing ACPI modalias as following.
acpi:<HID>:<CID1>:<CID2>:..:<CIDn>:<bbsspp>:
E.g:
# cat /sys/devices/platform/AMDI0600:00/modalias
acpi:AMDI0600:010601:
where bb is th base-class code, ss is te sub-class code, and pp is the
programming interface code
Since there would not be _HID/_CID in the ACPI matching table of the driver,
this patch adds a field to acpi_device_id to specify the matching _CLS.
static const struct acpi_device_id ahci_acpi_match[] = {
{ ACPI_DEVICE_CLASS(PCI_CLASS_STORAGE_SATA_AHCI, 0xffffff) },
{},
};
In this case, the corresponded entry in modules.alias file would be:
alias acpi*:010601:* ahci_platform
Acked-by: Mika Westerberg <mika.westerberg@linux.intel.com>
Reviewed-by: Hanjun Guo <hanjun.guo@linaro.org>
Signed-off-by: Suravee Suthikulpanit <Suravee.Suthikulpanit@amd.com>
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
2015-07-06 23:55:20 +00:00
|
|
|
else
|
|
|
|
sprintf(&alias[cnt], "??");
|
|
|
|
cnt += 2;
|
|
|
|
}
|
2024-11-19 23:56:45 +00:00
|
|
|
module_alias_printf(mod, false, "acpi*:%s:*", alias);
|
ACPI / scan: Add support for ACPI _CLS device matching
Device drivers typically use ACPI _HIDs/_CIDs listed in struct device_driver
acpi_match_table to match devices. However, for generic drivers, we do not
want to list _HID for all supported devices. Also, certain classes of devices
do not have _CID (e.g. SATA, USB). Instead, we can leverage ACPI _CLS,
which specifies PCI-defined class code (i.e. base-class, subclass and
programming interface). This patch adds support for matching ACPI devices using
the _CLS method.
To support loadable module, current design uses _HID or _CID to match device's
modalias. With the new way of matching with _CLS this would requires modification
to the current ACPI modalias key to include _CLS. This patch appends PCI-defined
class-code to the existing ACPI modalias as following.
acpi:<HID>:<CID1>:<CID2>:..:<CIDn>:<bbsspp>:
E.g:
# cat /sys/devices/platform/AMDI0600:00/modalias
acpi:AMDI0600:010601:
where bb is th base-class code, ss is te sub-class code, and pp is the
programming interface code
Since there would not be _HID/_CID in the ACPI matching table of the driver,
this patch adds a field to acpi_device_id to specify the matching _CLS.
static const struct acpi_device_id ahci_acpi_match[] = {
{ ACPI_DEVICE_CLASS(PCI_CLASS_STORAGE_SATA_AHCI, 0xffffff) },
{},
};
In this case, the corresponded entry in modules.alias file would be:
alias acpi*:010601:* ahci_platform
Acked-by: Mika Westerberg <mika.westerberg@linux.intel.com>
Reviewed-by: Hanjun Guo <hanjun.guo@linaro.org>
Signed-off-by: Suravee Suthikulpanit <Suravee.Suthikulpanit@amd.com>
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
2015-07-06 23:55:20 +00:00
|
|
|
}
|
2007-07-23 12:43:51 +00:00
|
|
|
}
|
|
|
|
|
2005-04-16 22:20:36 +00:00
|
|
|
/* looks like: "pnp:dD" */
|
2024-11-19 23:56:47 +00:00
|
|
|
static void do_pnp_device_entry(struct module *mod, void *symval)
|
2005-04-16 22:20:36 +00:00
|
|
|
{
|
2024-11-19 23:56:47 +00:00
|
|
|
DEF_FIELD_ADDR(symval, pnp_device_id, id);
|
|
|
|
char acpi_id[sizeof(*id)];
|
2009-01-08 02:06:42 +00:00
|
|
|
|
2024-11-19 23:56:47 +00:00
|
|
|
/* fix broken pnp bus lowercasing */
|
|
|
|
for (unsigned int i = 0; i < sizeof(acpi_id); i++)
|
|
|
|
acpi_id[i] = toupper((*id)[i]);
|
|
|
|
module_alias_printf(mod, false, "pnp:d%s*", *id);
|
|
|
|
module_alias_printf(mod, false, "acpi*:%s:*", acpi_id);
|
2005-04-16 22:20:36 +00:00
|
|
|
}
|
|
|
|
|
2008-02-20 23:35:54 +00:00
|
|
|
/* looks like: "pnp:dD" for every device of the card */
|
2024-11-19 23:56:46 +00:00
|
|
|
static void do_pnp_card_entry(struct module *mod, void *symval)
|
2005-04-16 22:20:36 +00:00
|
|
|
{
|
2024-11-19 23:56:46 +00:00
|
|
|
DEF_FIELD_ADDR(symval, pnp_card_device_id, devs);
|
2008-02-20 23:35:54 +00:00
|
|
|
|
2024-11-19 23:56:46 +00:00
|
|
|
for (unsigned int i = 0; i < PNP_MAX_DEVICES; i++) {
|
|
|
|
const char *id = (char *)(*devs)[i].id;
|
|
|
|
char acpi_id[PNP_ID_LEN];
|
2008-02-20 23:35:54 +00:00
|
|
|
|
2024-11-19 23:56:46 +00:00
|
|
|
if (!id[0])
|
|
|
|
break;
|
2008-02-20 23:35:54 +00:00
|
|
|
|
2024-11-19 23:56:46 +00:00
|
|
|
/* fix broken pnp bus lowercasing */
|
|
|
|
for (unsigned int j = 0; j < sizeof(acpi_id); j++)
|
|
|
|
acpi_id[j] = toupper(id[j]);
|
2009-01-08 02:06:42 +00:00
|
|
|
|
2024-11-19 23:56:46 +00:00
|
|
|
/* add an individual alias for every device entry */
|
|
|
|
module_alias_printf(mod, false, "pnp:d%s*", id);
|
|
|
|
module_alias_printf(mod, false, "acpi*:%s:*", acpi_id);
|
2005-04-16 22:20:36 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2005-06-27 23:28:12 +00:00
|
|
|
/* Looks like: pcmcia:mNcNfNfnNpfnNvaNvbNvcNvdN. */
|
2024-11-19 23:56:45 +00:00
|
|
|
static void do_pcmcia_entry(struct module *mod, void *symval)
|
2005-06-27 23:28:12 +00:00
|
|
|
{
|
2024-11-19 23:56:45 +00:00
|
|
|
char alias[256] = {};
|
2005-06-27 23:28:12 +00:00
|
|
|
unsigned int i;
|
2013-01-20 16:58:47 +00:00
|
|
|
DEF_FIELD(symval, pcmcia_device_id, match_flags);
|
|
|
|
DEF_FIELD(symval, pcmcia_device_id, manf_id);
|
|
|
|
DEF_FIELD(symval, pcmcia_device_id, card_id);
|
|
|
|
DEF_FIELD(symval, pcmcia_device_id, func_id);
|
|
|
|
DEF_FIELD(symval, pcmcia_device_id, function);
|
|
|
|
DEF_FIELD(symval, pcmcia_device_id, device_no);
|
|
|
|
DEF_FIELD_ADDR(symval, pcmcia_device_id, prod_id_hash);
|
2005-09-25 12:39:46 +00:00
|
|
|
|
2005-06-27 23:28:12 +00:00
|
|
|
for (i=0; i<4; i++) {
|
2013-01-20 16:58:47 +00:00
|
|
|
(*prod_id_hash)[i] = TO_NATIVE((*prod_id_hash)[i]);
|
|
|
|
}
|
|
|
|
|
|
|
|
ADD(alias, "m", match_flags & PCMCIA_DEV_ID_MATCH_MANF_ID,
|
|
|
|
manf_id);
|
|
|
|
ADD(alias, "c", match_flags & PCMCIA_DEV_ID_MATCH_CARD_ID,
|
|
|
|
card_id);
|
|
|
|
ADD(alias, "f", match_flags & PCMCIA_DEV_ID_MATCH_FUNC_ID,
|
|
|
|
func_id);
|
|
|
|
ADD(alias, "fn", match_flags & PCMCIA_DEV_ID_MATCH_FUNCTION,
|
|
|
|
function);
|
|
|
|
ADD(alias, "pfn", match_flags & PCMCIA_DEV_ID_MATCH_DEVICE_NO,
|
|
|
|
device_no);
|
|
|
|
ADD(alias, "pa", match_flags & PCMCIA_DEV_ID_MATCH_PROD_ID1, (*prod_id_hash)[0]);
|
|
|
|
ADD(alias, "pb", match_flags & PCMCIA_DEV_ID_MATCH_PROD_ID2, (*prod_id_hash)[1]);
|
|
|
|
ADD(alias, "pc", match_flags & PCMCIA_DEV_ID_MATCH_PROD_ID3, (*prod_id_hash)[2]);
|
|
|
|
ADD(alias, "pd", match_flags & PCMCIA_DEV_ID_MATCH_PROD_ID4, (*prod_id_hash)[3]);
|
2005-06-27 23:28:12 +00:00
|
|
|
|
2024-11-19 23:56:45 +00:00
|
|
|
module_alias_printf(mod, true, "pcmcia:%s", alias);
|
2005-06-27 23:28:12 +00:00
|
|
|
}
|
|
|
|
|
2024-11-19 23:56:45 +00:00
|
|
|
static void do_vio_entry(struct module *mod, void *symval)
|
2005-08-17 06:42:59 +00:00
|
|
|
{
|
2024-11-19 23:56:45 +00:00
|
|
|
char alias[256];
|
2005-08-17 06:42:59 +00:00
|
|
|
char *tmp;
|
2013-01-20 16:58:47 +00:00
|
|
|
DEF_FIELD_ADDR(symval, vio_device_id, type);
|
|
|
|
DEF_FIELD_ADDR(symval, vio_device_id, compat);
|
2005-08-17 06:42:59 +00:00
|
|
|
|
2013-01-20 16:58:47 +00:00
|
|
|
sprintf(alias, "vio:T%sS%s", (*type)[0] ? *type : "*",
|
|
|
|
(*compat)[0] ? *compat : "*");
|
2005-08-17 06:42:59 +00:00
|
|
|
|
|
|
|
/* Replace all whitespace with underscores */
|
|
|
|
for (tmp = alias; tmp && *tmp; tmp++)
|
|
|
|
if (isspace (*tmp))
|
|
|
|
*tmp = '_';
|
|
|
|
|
2024-11-19 23:56:45 +00:00
|
|
|
module_alias_printf(mod, true, "%s", alias);
|
2005-08-17 06:42:59 +00:00
|
|
|
}
|
|
|
|
|
2005-12-07 20:40:34 +00:00
|
|
|
static void do_input(char *alias,
|
|
|
|
kernel_ulong_t *arr, unsigned int min, unsigned int max)
|
|
|
|
{
|
|
|
|
unsigned int i;
|
2006-04-26 04:14:19 +00:00
|
|
|
|
2013-01-20 16:58:47 +00:00
|
|
|
for (i = min / BITS_PER_LONG; i < max / BITS_PER_LONG + 1; i++)
|
|
|
|
arr[i] = TO_NATIVE(arr[i]);
|
2006-04-26 04:14:19 +00:00
|
|
|
for (i = min; i < max; i++)
|
modpost: fix input MODULE_DEVICE_TABLE() built for 64-bit on 32-bit host
When building a 64-bit kernel on a 32-bit build host, incorrect
input MODULE_ALIAS() entries may be generated.
For example, when compiling a 64-bit kernel with CONFIG_INPUT_MOUSEDEV=m
on a 64-bit build machine, you will get the correct output:
$ grep MODULE_ALIAS drivers/input/mousedev.mod.c
MODULE_ALIAS("input:b*v*p*e*-e*1,*2,*k*110,*r*0,*1,*a*m*l*s*f*w*");
MODULE_ALIAS("input:b*v*p*e*-e*1,*2,*k*r*8,*a*m*l*s*f*w*");
MODULE_ALIAS("input:b*v*p*e*-e*1,*3,*k*14A,*r*a*0,*1,*m*l*s*f*w*");
MODULE_ALIAS("input:b*v*p*e*-e*1,*3,*k*145,*r*a*0,*1,*18,*1C,*m*l*s*f*w*");
MODULE_ALIAS("input:b*v*p*e*-e*1,*3,*k*110,*r*a*0,*1,*m*l*s*f*w*");
However, building the same kernel on a 32-bit machine results in
incorrect output:
$ grep MODULE_ALIAS drivers/input/mousedev.mod.c
MODULE_ALIAS("input:b*v*p*e*-e*1,*2,*k*110,*130,*r*0,*1,*a*m*l*s*f*w*");
MODULE_ALIAS("input:b*v*p*e*-e*1,*2,*k*r*8,*a*m*l*s*f*w*");
MODULE_ALIAS("input:b*v*p*e*-e*1,*3,*k*14A,*16A,*r*a*0,*1,*20,*21,*m*l*s*f*w*");
MODULE_ALIAS("input:b*v*p*e*-e*1,*3,*k*145,*165,*r*a*0,*1,*18,*1C,*20,*21,*38,*3C,*m*l*s*f*w*");
MODULE_ALIAS("input:b*v*p*e*-e*1,*3,*k*110,*130,*r*a*0,*1,*20,*21,*m*l*s*f*w*");
A similar issue occurs with CONFIG_INPUT_JOYDEV=m. On a 64-bit build
machine, the output is:
$ grep MODULE_ALIAS drivers/input/joydev.mod.c
MODULE_ALIAS("input:b*v*p*e*-e*3,*k*r*a*0,*m*l*s*f*w*");
MODULE_ALIAS("input:b*v*p*e*-e*3,*k*r*a*2,*m*l*s*f*w*");
MODULE_ALIAS("input:b*v*p*e*-e*3,*k*r*a*8,*m*l*s*f*w*");
MODULE_ALIAS("input:b*v*p*e*-e*3,*k*r*a*6,*m*l*s*f*w*");
MODULE_ALIAS("input:b*v*p*e*-e*1,*k*120,*r*a*m*l*s*f*w*");
MODULE_ALIAS("input:b*v*p*e*-e*1,*k*130,*r*a*m*l*s*f*w*");
MODULE_ALIAS("input:b*v*p*e*-e*1,*k*2C0,*r*a*m*l*s*f*w*");
However, on a 32-bit machine, the output is incorrect:
$ grep MODULE_ALIAS drivers/input/joydev.mod.c
MODULE_ALIAS("input:b*v*p*e*-e*3,*k*r*a*0,*20,*m*l*s*f*w*");
MODULE_ALIAS("input:b*v*p*e*-e*3,*k*r*a*2,*22,*m*l*s*f*w*");
MODULE_ALIAS("input:b*v*p*e*-e*3,*k*r*a*8,*28,*m*l*s*f*w*");
MODULE_ALIAS("input:b*v*p*e*-e*3,*k*r*a*6,*26,*m*l*s*f*w*");
MODULE_ALIAS("input:b*v*p*e*-e*1,*k*11F,*13F,*r*a*m*l*s*f*w*");
MODULE_ALIAS("input:b*v*p*e*-e*1,*k*11F,*13F,*r*a*m*l*s*f*w*");
MODULE_ALIAS("input:b*v*p*e*-e*1,*k*2C0,*2E0,*r*a*m*l*s*f*w*");
When building a 64-bit kernel, BITS_PER_LONG is defined as 64. However,
on a 32-bit build machine, the constant 1L is a signed 32-bit value.
Left-shifting it beyond 32 bits causes wraparound, and shifting by 31
or 63 bits makes it a negative value.
The fix in commit e0e92632715f ("[PATCH] PATCH: 1 line 2.6.18 bugfix:
modpost-64bit-fix.patch") is incorrect; it only addresses cases where
a 64-bit kernel is built on a 64-bit build machine, overlooking cases
on a 32-bit build machine.
Using 1ULL ensures a 64-bit width on both 32-bit and 64-bit machines,
avoiding the wraparound issue.
Fixes: e0e92632715f ("[PATCH] PATCH: 1 line 2.6.18 bugfix: modpost-64bit-fix.patch")
Signed-off-by: Masahiro Yamada <masahiroy@kernel.org>
2024-11-03 12:52:57 +00:00
|
|
|
if (arr[i / BITS_PER_LONG] & (1ULL << (i%BITS_PER_LONG)))
|
2006-04-26 04:14:19 +00:00
|
|
|
sprintf(alias + strlen(alias), "%X,*", i);
|
2005-12-07 20:40:34 +00:00
|
|
|
}
|
|
|
|
|
2017-10-22 18:42:29 +00:00
|
|
|
/* input:b0v0p0e0-eXkXrXaXmXlXsXfXwX where X is comma-separated %02X. */
|
2024-11-19 23:56:45 +00:00
|
|
|
static void do_input_entry(struct module *mod, void *symval)
|
2005-12-07 20:40:34 +00:00
|
|
|
{
|
2024-11-19 23:56:45 +00:00
|
|
|
char alias[256] = {};
|
|
|
|
|
2013-01-20 16:58:47 +00:00
|
|
|
DEF_FIELD(symval, input_device_id, flags);
|
|
|
|
DEF_FIELD(symval, input_device_id, bustype);
|
|
|
|
DEF_FIELD(symval, input_device_id, vendor);
|
|
|
|
DEF_FIELD(symval, input_device_id, product);
|
|
|
|
DEF_FIELD(symval, input_device_id, version);
|
|
|
|
DEF_FIELD_ADDR(symval, input_device_id, evbit);
|
|
|
|
DEF_FIELD_ADDR(symval, input_device_id, keybit);
|
|
|
|
DEF_FIELD_ADDR(symval, input_device_id, relbit);
|
|
|
|
DEF_FIELD_ADDR(symval, input_device_id, absbit);
|
|
|
|
DEF_FIELD_ADDR(symval, input_device_id, mscbit);
|
|
|
|
DEF_FIELD_ADDR(symval, input_device_id, ledbit);
|
|
|
|
DEF_FIELD_ADDR(symval, input_device_id, sndbit);
|
|
|
|
DEF_FIELD_ADDR(symval, input_device_id, ffbit);
|
|
|
|
DEF_FIELD_ADDR(symval, input_device_id, swbit);
|
|
|
|
|
|
|
|
ADD(alias, "b", flags & INPUT_DEVICE_ID_MATCH_BUS, bustype);
|
|
|
|
ADD(alias, "v", flags & INPUT_DEVICE_ID_MATCH_VENDOR, vendor);
|
|
|
|
ADD(alias, "p", flags & INPUT_DEVICE_ID_MATCH_PRODUCT, product);
|
|
|
|
ADD(alias, "e", flags & INPUT_DEVICE_ID_MATCH_VERSION, version);
|
2005-12-07 20:40:34 +00:00
|
|
|
|
|
|
|
sprintf(alias + strlen(alias), "-e*");
|
2013-01-20 16:58:47 +00:00
|
|
|
if (flags & INPUT_DEVICE_ID_MATCH_EVBIT)
|
|
|
|
do_input(alias, *evbit, 0, INPUT_DEVICE_ID_EV_MAX);
|
2005-12-07 20:40:34 +00:00
|
|
|
sprintf(alias + strlen(alias), "k*");
|
2013-01-20 16:58:47 +00:00
|
|
|
if (flags & INPUT_DEVICE_ID_MATCH_KEYBIT)
|
|
|
|
do_input(alias, *keybit,
|
2007-03-09 18:59:06 +00:00
|
|
|
INPUT_DEVICE_ID_KEY_MIN_INTERESTING,
|
|
|
|
INPUT_DEVICE_ID_KEY_MAX);
|
2005-12-07 20:40:34 +00:00
|
|
|
sprintf(alias + strlen(alias), "r*");
|
2013-01-20 16:58:47 +00:00
|
|
|
if (flags & INPUT_DEVICE_ID_MATCH_RELBIT)
|
|
|
|
do_input(alias, *relbit, 0, INPUT_DEVICE_ID_REL_MAX);
|
2005-12-07 20:40:34 +00:00
|
|
|
sprintf(alias + strlen(alias), "a*");
|
2013-01-20 16:58:47 +00:00
|
|
|
if (flags & INPUT_DEVICE_ID_MATCH_ABSBIT)
|
|
|
|
do_input(alias, *absbit, 0, INPUT_DEVICE_ID_ABS_MAX);
|
2005-12-07 20:40:34 +00:00
|
|
|
sprintf(alias + strlen(alias), "m*");
|
2013-01-20 16:58:47 +00:00
|
|
|
if (flags & INPUT_DEVICE_ID_MATCH_MSCIT)
|
|
|
|
do_input(alias, *mscbit, 0, INPUT_DEVICE_ID_MSC_MAX);
|
2005-12-07 20:40:34 +00:00
|
|
|
sprintf(alias + strlen(alias), "l*");
|
2013-01-20 16:58:47 +00:00
|
|
|
if (flags & INPUT_DEVICE_ID_MATCH_LEDBIT)
|
|
|
|
do_input(alias, *ledbit, 0, INPUT_DEVICE_ID_LED_MAX);
|
2005-12-07 20:40:34 +00:00
|
|
|
sprintf(alias + strlen(alias), "s*");
|
2013-01-20 16:58:47 +00:00
|
|
|
if (flags & INPUT_DEVICE_ID_MATCH_SNDBIT)
|
|
|
|
do_input(alias, *sndbit, 0, INPUT_DEVICE_ID_SND_MAX);
|
2005-12-07 20:40:34 +00:00
|
|
|
sprintf(alias + strlen(alias), "f*");
|
2013-01-20 16:58:47 +00:00
|
|
|
if (flags & INPUT_DEVICE_ID_MATCH_FFBIT)
|
|
|
|
do_input(alias, *ffbit, 0, INPUT_DEVICE_ID_FF_MAX);
|
2005-12-07 20:40:34 +00:00
|
|
|
sprintf(alias + strlen(alias), "w*");
|
2013-01-20 16:58:47 +00:00
|
|
|
if (flags & INPUT_DEVICE_ID_MATCH_SWBIT)
|
|
|
|
do_input(alias, *swbit, 0, INPUT_DEVICE_ID_SW_MAX);
|
2024-11-19 23:56:45 +00:00
|
|
|
|
|
|
|
module_alias_printf(mod, false, "input:%s", alias);
|
2005-12-07 20:40:34 +00:00
|
|
|
}
|
|
|
|
|
2024-11-19 23:56:45 +00:00
|
|
|
static void do_eisa_entry(struct module *mod, void *symval)
|
2006-09-27 08:50:56 +00:00
|
|
|
{
|
2013-01-20 16:58:47 +00:00
|
|
|
DEF_FIELD_ADDR(symval, eisa_device_id, sig);
|
2024-11-19 23:56:45 +00:00
|
|
|
module_alias_printf(mod, false, EISA_DEVICE_MODALIAS_FMT "*", *sig);
|
2006-09-27 08:50:56 +00:00
|
|
|
}
|
|
|
|
|
2007-01-13 19:58:21 +00:00
|
|
|
/* Looks like: parisc:tNhvNrevNsvN */
|
2024-11-19 23:56:45 +00:00
|
|
|
static void do_parisc_entry(struct module *mod, void *symval)
|
2007-01-13 19:58:21 +00:00
|
|
|
{
|
2024-11-19 23:56:45 +00:00
|
|
|
char alias[256] = {};
|
|
|
|
|
2013-01-20 16:58:47 +00:00
|
|
|
DEF_FIELD(symval, parisc_device_id, hw_type);
|
|
|
|
DEF_FIELD(symval, parisc_device_id, hversion);
|
|
|
|
DEF_FIELD(symval, parisc_device_id, hversion_rev);
|
|
|
|
DEF_FIELD(symval, parisc_device_id, sversion);
|
2007-01-13 19:58:21 +00:00
|
|
|
|
2013-01-20 16:58:47 +00:00
|
|
|
ADD(alias, "t", hw_type != PA_HWTYPE_ANY_ID, hw_type);
|
|
|
|
ADD(alias, "hv", hversion != PA_HVERSION_ANY_ID, hversion);
|
|
|
|
ADD(alias, "rev", hversion_rev != PA_HVERSION_REV_ANY_ID, hversion_rev);
|
|
|
|
ADD(alias, "sv", sversion != PA_SVERSION_ANY_ID, sversion);
|
2007-01-13 19:58:21 +00:00
|
|
|
|
2024-11-19 23:56:45 +00:00
|
|
|
module_alias_printf(mod, true, "parisc:%s", alias);
|
2007-01-13 19:58:21 +00:00
|
|
|
}
|
|
|
|
|
2007-06-17 09:34:23 +00:00
|
|
|
/* Looks like: sdio:cNvNdN. */
|
2024-11-19 23:56:45 +00:00
|
|
|
static void do_sdio_entry(struct module *mod, void *symval)
|
2007-06-17 09:34:23 +00:00
|
|
|
{
|
2024-11-19 23:56:45 +00:00
|
|
|
char alias[256] = {};
|
|
|
|
|
2013-01-20 16:58:47 +00:00
|
|
|
DEF_FIELD(symval, sdio_device_id, class);
|
|
|
|
DEF_FIELD(symval, sdio_device_id, vendor);
|
|
|
|
DEF_FIELD(symval, sdio_device_id, device);
|
2007-06-17 09:34:23 +00:00
|
|
|
|
2013-01-20 16:58:47 +00:00
|
|
|
ADD(alias, "c", class != (__u8)SDIO_ANY_ID, class);
|
|
|
|
ADD(alias, "v", vendor != (__u16)SDIO_ANY_ID, vendor);
|
|
|
|
ADD(alias, "d", device != (__u16)SDIO_ANY_ID, device);
|
2024-11-19 23:56:45 +00:00
|
|
|
|
|
|
|
module_alias_printf(mod, true, "sdio:%s", alias);
|
2007-10-12 02:40:14 +00:00
|
|
|
}
|
|
|
|
|
2007-09-18 19:12:50 +00:00
|
|
|
/* Looks like: ssb:vNidNrevN. */
|
2024-11-19 23:56:45 +00:00
|
|
|
static void do_ssb_entry(struct module *mod, void *symval)
|
2007-09-18 19:12:50 +00:00
|
|
|
{
|
2024-11-19 23:56:45 +00:00
|
|
|
char alias[256] = {};
|
|
|
|
|
2013-01-20 16:58:47 +00:00
|
|
|
DEF_FIELD(symval, ssb_device_id, vendor);
|
|
|
|
DEF_FIELD(symval, ssb_device_id, coreid);
|
|
|
|
DEF_FIELD(symval, ssb_device_id, revision);
|
2007-06-17 09:34:23 +00:00
|
|
|
|
2013-01-20 16:58:47 +00:00
|
|
|
ADD(alias, "v", vendor != SSB_ANY_VENDOR, vendor);
|
|
|
|
ADD(alias, "id", coreid != SSB_ANY_ID, coreid);
|
|
|
|
ADD(alias, "rev", revision != SSB_ANY_REV, revision);
|
2024-11-19 23:56:45 +00:00
|
|
|
|
|
|
|
module_alias_printf(mod, true, "ssb:%s", alias);
|
2007-06-17 09:34:23 +00:00
|
|
|
}
|
|
|
|
|
2011-05-09 16:56:46 +00:00
|
|
|
/* Looks like: bcma:mNidNrevNclN. */
|
2024-11-19 23:56:45 +00:00
|
|
|
static void do_bcma_entry(struct module *mod, void *symval)
|
2011-05-09 16:56:46 +00:00
|
|
|
{
|
2024-11-19 23:56:45 +00:00
|
|
|
char alias[256] = {};
|
|
|
|
|
2013-01-20 16:58:47 +00:00
|
|
|
DEF_FIELD(symval, bcma_device_id, manuf);
|
|
|
|
DEF_FIELD(symval, bcma_device_id, id);
|
|
|
|
DEF_FIELD(symval, bcma_device_id, rev);
|
|
|
|
DEF_FIELD(symval, bcma_device_id, class);
|
2011-05-09 16:56:46 +00:00
|
|
|
|
2013-01-20 16:58:47 +00:00
|
|
|
ADD(alias, "m", manuf != BCMA_ANY_MANUF, manuf);
|
|
|
|
ADD(alias, "id", id != BCMA_ANY_ID, id);
|
|
|
|
ADD(alias, "rev", rev != BCMA_ANY_REV, rev);
|
|
|
|
ADD(alias, "cl", class != BCMA_ANY_CLASS, class);
|
2024-11-19 23:56:45 +00:00
|
|
|
|
|
|
|
module_alias_printf(mod, true, "bcma:%s", alias);
|
2011-05-09 16:56:46 +00:00
|
|
|
}
|
|
|
|
|
2007-10-22 01:03:39 +00:00
|
|
|
/* Looks like: virtio:dNvN */
|
2024-11-19 23:56:45 +00:00
|
|
|
static void do_virtio_entry(struct module *mod, void *symval)
|
2007-10-22 01:03:39 +00:00
|
|
|
{
|
2024-11-19 23:56:45 +00:00
|
|
|
char alias[256] = {};
|
|
|
|
|
2013-01-20 16:58:47 +00:00
|
|
|
DEF_FIELD(symval, virtio_device_id, device);
|
|
|
|
DEF_FIELD(symval, virtio_device_id, vendor);
|
2007-10-22 01:03:39 +00:00
|
|
|
|
2013-01-20 16:58:47 +00:00
|
|
|
ADD(alias, "d", device != VIRTIO_DEV_ANY_ID, device);
|
|
|
|
ADD(alias, "v", vendor != VIRTIO_DEV_ANY_ID, vendor);
|
2007-10-22 01:03:39 +00:00
|
|
|
|
2024-11-19 23:56:45 +00:00
|
|
|
module_alias_printf(mod, true, "virtio:%s", alias);
|
2007-10-22 01:03:39 +00:00
|
|
|
}
|
|
|
|
|
2011-08-25 16:48:30 +00:00
|
|
|
/*
|
|
|
|
* Looks like: vmbus:guid
|
|
|
|
* Each byte of the guid will be represented by two hex characters
|
|
|
|
* in the name.
|
|
|
|
*/
|
|
|
|
|
2024-11-19 23:56:45 +00:00
|
|
|
static void do_vmbus_entry(struct module *mod, void *symval)
|
2011-08-25 16:48:30 +00:00
|
|
|
{
|
|
|
|
int i;
|
2013-01-20 16:58:47 +00:00
|
|
|
DEF_FIELD_ADDR(symval, hv_vmbus_device_id, guid);
|
|
|
|
char guid_name[(sizeof(*guid) + 1) * 2];
|
2011-08-25 16:48:30 +00:00
|
|
|
|
2013-01-20 16:58:47 +00:00
|
|
|
for (i = 0; i < (sizeof(*guid) * 2); i += 2)
|
2015-12-15 00:01:43 +00:00
|
|
|
sprintf(&guid_name[i], "%02x", TO_NATIVE((guid->b)[i/2]));
|
2011-08-25 16:48:30 +00:00
|
|
|
|
2024-11-19 23:56:45 +00:00
|
|
|
module_alias_printf(mod, false, "vmbus:%s", guid_name);
|
2011-08-25 16:48:30 +00:00
|
|
|
}
|
|
|
|
|
2018-04-21 23:55:29 +00:00
|
|
|
/* Looks like: rpmsg:S */
|
2024-11-19 23:56:45 +00:00
|
|
|
static void do_rpmsg_entry(struct module *mod, void *symval)
|
2018-04-21 23:55:29 +00:00
|
|
|
{
|
|
|
|
DEF_FIELD_ADDR(symval, rpmsg_device_id, name);
|
|
|
|
|
2024-11-19 23:56:45 +00:00
|
|
|
module_alias_printf(mod, false, RPMSG_DEVICE_MODALIAS_FMT, *name);
|
2018-04-21 23:55:29 +00:00
|
|
|
}
|
|
|
|
|
2008-04-29 21:11:39 +00:00
|
|
|
/* Looks like: i2c:S */
|
2024-11-19 23:56:45 +00:00
|
|
|
static void do_i2c_entry(struct module *mod, void *symval)
|
2008-04-29 21:11:39 +00:00
|
|
|
{
|
2013-01-20 16:58:47 +00:00
|
|
|
DEF_FIELD_ADDR(symval, i2c_device_id, name);
|
2008-04-29 21:11:39 +00:00
|
|
|
|
2024-11-19 23:56:45 +00:00
|
|
|
module_alias_printf(mod, false, I2C_MODULE_PREFIX "%s", *name);
|
2008-04-29 21:11:39 +00:00
|
|
|
}
|
|
|
|
|
2024-11-19 23:56:45 +00:00
|
|
|
static void do_i3c_entry(struct module *mod, void *symval)
|
2020-02-27 11:31:08 +00:00
|
|
|
{
|
2024-11-19 23:56:45 +00:00
|
|
|
char alias[256] = {};
|
|
|
|
|
2020-02-27 11:31:08 +00:00
|
|
|
DEF_FIELD(symval, i3c_device_id, match_flags);
|
|
|
|
DEF_FIELD(symval, i3c_device_id, dcr);
|
|
|
|
DEF_FIELD(symval, i3c_device_id, manuf_id);
|
|
|
|
DEF_FIELD(symval, i3c_device_id, part_id);
|
|
|
|
DEF_FIELD(symval, i3c_device_id, extra_info);
|
|
|
|
|
|
|
|
ADD(alias, "dcr", match_flags & I3C_MATCH_DCR, dcr);
|
|
|
|
ADD(alias, "manuf", match_flags & I3C_MATCH_MANUF, manuf_id);
|
|
|
|
ADD(alias, "part", match_flags & I3C_MATCH_PART, part_id);
|
|
|
|
ADD(alias, "ext", match_flags & I3C_MATCH_EXTRA_INFO, extra_info);
|
|
|
|
|
2024-11-19 23:56:45 +00:00
|
|
|
module_alias_printf(mod, false, "i3c:%s", alias);
|
2020-02-27 11:31:08 +00:00
|
|
|
}
|
|
|
|
|
2024-11-19 23:56:45 +00:00
|
|
|
static void do_slim_entry(struct module *mod, void *symval)
|
2024-09-02 14:10:04 +00:00
|
|
|
{
|
|
|
|
DEF_FIELD(symval, slim_device_id, manf_id);
|
|
|
|
DEF_FIELD(symval, slim_device_id, prod_code);
|
|
|
|
|
2024-11-19 23:56:45 +00:00
|
|
|
module_alias_printf(mod, false, "slim:%x:%x:*", manf_id, prod_code);
|
2024-09-02 14:10:04 +00:00
|
|
|
}
|
|
|
|
|
2009-09-22 23:46:08 +00:00
|
|
|
/* Looks like: spi:S */
|
2024-11-19 23:56:45 +00:00
|
|
|
static void do_spi_entry(struct module *mod, void *symval)
|
2009-09-22 23:46:04 +00:00
|
|
|
{
|
2013-01-20 16:58:47 +00:00
|
|
|
DEF_FIELD_ADDR(symval, spi_device_id, name);
|
2009-09-22 23:46:04 +00:00
|
|
|
|
2024-11-19 23:56:45 +00:00
|
|
|
module_alias_printf(mod, false, SPI_MODULE_PREFIX "%s", *name);
|
2009-09-22 23:46:04 +00:00
|
|
|
}
|
|
|
|
|
2008-09-16 23:23:28 +00:00
|
|
|
static const struct dmifield {
|
|
|
|
const char *prefix;
|
|
|
|
int field;
|
|
|
|
} dmi_fields[] = {
|
|
|
|
{ "bvn", DMI_BIOS_VENDOR },
|
|
|
|
{ "bvr", DMI_BIOS_VERSION },
|
|
|
|
{ "bd", DMI_BIOS_DATE },
|
2020-06-06 09:35:50 +00:00
|
|
|
{ "br", DMI_BIOS_RELEASE },
|
|
|
|
{ "efr", DMI_EC_FIRMWARE_RELEASE },
|
2008-09-16 23:23:28 +00:00
|
|
|
{ "svn", DMI_SYS_VENDOR },
|
|
|
|
{ "pn", DMI_PRODUCT_NAME },
|
|
|
|
{ "pvr", DMI_PRODUCT_VERSION },
|
|
|
|
{ "rvn", DMI_BOARD_VENDOR },
|
|
|
|
{ "rn", DMI_BOARD_NAME },
|
|
|
|
{ "rvr", DMI_BOARD_VERSION },
|
|
|
|
{ "cvn", DMI_CHASSIS_VENDOR },
|
|
|
|
{ "ct", DMI_CHASSIS_TYPE },
|
|
|
|
{ "cvr", DMI_CHASSIS_VERSION },
|
|
|
|
{ NULL, DMI_NONE }
|
|
|
|
};
|
|
|
|
|
|
|
|
static void dmi_ascii_filter(char *d, const char *s)
|
|
|
|
{
|
|
|
|
/* Filter out characters we don't want to see in the modalias string */
|
|
|
|
for (; *s; s++)
|
|
|
|
if (*s > ' ' && *s < 127 && *s != ':')
|
|
|
|
*(d++) = *s;
|
|
|
|
|
|
|
|
*d = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2024-11-19 23:56:45 +00:00
|
|
|
static void do_dmi_entry(struct module *mod, void *symval)
|
2008-09-16 23:23:28 +00:00
|
|
|
{
|
2024-11-19 23:56:45 +00:00
|
|
|
char alias[256] = {};
|
2008-09-16 23:23:28 +00:00
|
|
|
int i, j;
|
2013-01-20 16:58:47 +00:00
|
|
|
DEF_FIELD_ADDR(symval, dmi_system_id, matches);
|
2008-09-16 23:23:28 +00:00
|
|
|
|
|
|
|
for (i = 0; i < ARRAY_SIZE(dmi_fields); i++) {
|
|
|
|
for (j = 0; j < 4; j++) {
|
2013-01-20 16:58:47 +00:00
|
|
|
if ((*matches)[j].slot &&
|
|
|
|
(*matches)[j].slot == dmi_fields[i].field) {
|
2008-09-16 23:23:28 +00:00
|
|
|
sprintf(alias + strlen(alias), ":%s*",
|
|
|
|
dmi_fields[i].prefix);
|
|
|
|
dmi_ascii_filter(alias + strlen(alias),
|
2013-01-20 16:58:47 +00:00
|
|
|
(*matches)[j].substr);
|
2008-09-16 23:23:28 +00:00
|
|
|
strcat(alias, "*");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-11-19 23:56:45 +00:00
|
|
|
module_alias_printf(mod, false, "dmi*%s:", alias);
|
2008-09-16 23:23:28 +00:00
|
|
|
}
|
2009-02-04 03:52:40 +00:00
|
|
|
|
2024-11-19 23:56:45 +00:00
|
|
|
static void do_platform_entry(struct module *mod, void *symval)
|
2009-02-04 03:52:40 +00:00
|
|
|
{
|
2013-01-20 16:58:47 +00:00
|
|
|
DEF_FIELD_ADDR(symval, platform_device_id, name);
|
2024-11-19 23:56:45 +00:00
|
|
|
|
|
|
|
module_alias_printf(mod, false, PLATFORM_MODULE_PREFIX "%s", *name);
|
2009-02-04 03:52:40 +00:00
|
|
|
}
|
|
|
|
|
2024-11-19 23:56:45 +00:00
|
|
|
static void do_mdio_entry(struct module *mod, void *symval)
|
2010-04-02 01:05:27 +00:00
|
|
|
{
|
2024-11-19 23:56:45 +00:00
|
|
|
char id[33];
|
2010-04-02 01:05:27 +00:00
|
|
|
int i;
|
2013-01-20 16:58:47 +00:00
|
|
|
DEF_FIELD(symval, mdio_device_id, phy_id);
|
|
|
|
DEF_FIELD(symval, mdio_device_id, phy_id_mask);
|
2010-04-02 01:05:27 +00:00
|
|
|
|
|
|
|
for (i = 0; i < 32; i++) {
|
2013-01-20 16:58:47 +00:00
|
|
|
if (!((phy_id_mask >> (31-i)) & 1))
|
2024-11-19 23:56:45 +00:00
|
|
|
id[i] = '?';
|
2013-01-20 16:58:47 +00:00
|
|
|
else if ((phy_id >> (31-i)) & 1)
|
2024-11-19 23:56:45 +00:00
|
|
|
id[i] = '1';
|
2010-04-02 01:05:27 +00:00
|
|
|
else
|
2024-11-19 23:56:45 +00:00
|
|
|
id[i] = '0';
|
2010-04-02 01:05:27 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Terminate the string */
|
2024-11-19 23:56:45 +00:00
|
|
|
id[32] = '\0';
|
2010-04-02 01:05:27 +00:00
|
|
|
|
2024-11-19 23:56:45 +00:00
|
|
|
module_alias_printf(mod, false, MDIO_MODULE_PREFIX "%s", id);
|
2010-04-02 01:05:27 +00:00
|
|
|
}
|
|
|
|
|
2008-11-18 20:13:53 +00:00
|
|
|
/* Looks like: zorro:iN. */
|
2024-11-19 23:56:45 +00:00
|
|
|
static void do_zorro_entry(struct module *mod, void *symval)
|
2008-11-18 20:13:53 +00:00
|
|
|
{
|
2024-11-19 23:56:45 +00:00
|
|
|
char alias[256] = {};
|
2013-01-20 16:58:47 +00:00
|
|
|
DEF_FIELD(symval, zorro_device_id, id);
|
2024-11-19 23:56:45 +00:00
|
|
|
|
2013-01-20 16:58:47 +00:00
|
|
|
ADD(alias, "i", id != ZORRO_WILDCARD, id);
|
2024-11-19 23:56:45 +00:00
|
|
|
|
|
|
|
module_alias_printf(mod, false, "zorro:%s", alias);
|
2008-11-18 20:13:53 +00:00
|
|
|
}
|
|
|
|
|
2009-12-18 19:52:39 +00:00
|
|
|
/* looks like: "pnp:dD" */
|
2024-11-19 23:56:45 +00:00
|
|
|
static void do_isapnp_entry(struct module *mod, void *symval)
|
2009-12-18 19:52:39 +00:00
|
|
|
{
|
2013-01-20 16:58:47 +00:00
|
|
|
DEF_FIELD(symval, isapnp_device_id, vendor);
|
|
|
|
DEF_FIELD(symval, isapnp_device_id, function);
|
2024-11-19 23:56:45 +00:00
|
|
|
module_alias_printf(mod, false, "pnp:d%c%c%c%x%x%x%x*",
|
2013-01-20 16:58:47 +00:00
|
|
|
'A' + ((vendor >> 2) & 0x3f) - 1,
|
|
|
|
'A' + (((vendor & 3) << 3) | ((vendor >> 13) & 7)) - 1,
|
|
|
|
'A' + ((vendor >> 8) & 0x1f) - 1,
|
|
|
|
(function >> 4) & 0x0f, function & 0x0f,
|
|
|
|
(function >> 12) & 0x0f, (function >> 8) & 0x0f);
|
2009-12-18 19:52:39 +00:00
|
|
|
}
|
|
|
|
|
2012-09-04 15:01:13 +00:00
|
|
|
/* Looks like: "ipack:fNvNdN". */
|
2024-11-19 23:56:45 +00:00
|
|
|
static void do_ipack_entry(struct module *mod, void *symval)
|
2012-09-04 15:01:13 +00:00
|
|
|
{
|
2024-11-19 23:56:45 +00:00
|
|
|
char alias[256] = {};
|
2013-01-20 16:58:47 +00:00
|
|
|
DEF_FIELD(symval, ipack_device_id, format);
|
|
|
|
DEF_FIELD(symval, ipack_device_id, vendor);
|
|
|
|
DEF_FIELD(symval, ipack_device_id, device);
|
2024-11-19 23:56:45 +00:00
|
|
|
|
2013-01-20 16:58:47 +00:00
|
|
|
ADD(alias, "f", format != IPACK_ANY_FORMAT, format);
|
|
|
|
ADD(alias, "v", vendor != IPACK_ANY_ID, vendor);
|
|
|
|
ADD(alias, "d", device != IPACK_ANY_ID, device);
|
2024-11-19 23:56:45 +00:00
|
|
|
|
|
|
|
module_alias_printf(mod, true, "ipack:%s", alias);
|
2012-09-04 15:01:13 +00:00
|
|
|
}
|
|
|
|
|
2011-10-05 13:44:57 +00:00
|
|
|
/*
|
|
|
|
* Append a match expression for a single masked hex digit.
|
|
|
|
* outp points to a pointer to the character at which to append.
|
|
|
|
* *outp is updated on return to point just after the appended text,
|
|
|
|
* to facilitate further appending.
|
|
|
|
*/
|
|
|
|
static void append_nibble_mask(char **outp,
|
|
|
|
unsigned int nibble, unsigned int mask)
|
|
|
|
{
|
|
|
|
char *p = *outp;
|
|
|
|
unsigned int i;
|
|
|
|
|
|
|
|
switch (mask) {
|
|
|
|
case 0:
|
|
|
|
*p++ = '?';
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 0xf:
|
|
|
|
p += sprintf(p, "%X", nibble);
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
/*
|
|
|
|
* Dumbly emit a match pattern for all possible matching
|
|
|
|
* digits. This could be improved in some cases using ranges,
|
|
|
|
* but it has the advantage of being trivially correct, and is
|
|
|
|
* often optimal.
|
|
|
|
*/
|
|
|
|
*p++ = '[';
|
|
|
|
for (i = 0; i < 0x10; i++)
|
|
|
|
if ((i & mask) == nibble)
|
|
|
|
p += sprintf(p, "%X", i);
|
|
|
|
*p++ = ']';
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Ensure that the string remains NUL-terminated: */
|
|
|
|
*p = '\0';
|
|
|
|
|
|
|
|
/* Advance the caller's end-of-string pointer: */
|
|
|
|
*outp = p;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* looks like: "amba:dN"
|
|
|
|
*
|
|
|
|
* N is exactly 8 digits, where each is an upper-case hex digit, or
|
|
|
|
* a ? or [] pattern matching exactly one digit.
|
|
|
|
*/
|
2024-11-19 23:56:45 +00:00
|
|
|
static void do_amba_entry(struct module *mod, void *symval)
|
2011-10-05 13:44:57 +00:00
|
|
|
{
|
2024-11-19 23:56:45 +00:00
|
|
|
char alias[256];
|
2011-10-05 13:44:57 +00:00
|
|
|
unsigned int digit;
|
|
|
|
char *p = alias;
|
2013-01-20 16:58:47 +00:00
|
|
|
DEF_FIELD(symval, amba_id, id);
|
|
|
|
DEF_FIELD(symval, amba_id, mask);
|
2011-10-05 13:44:57 +00:00
|
|
|
|
2013-01-20 16:58:47 +00:00
|
|
|
if ((id & mask) != id)
|
2022-11-09 13:30:55 +00:00
|
|
|
fatal("%s: Masked-off bit(s) of AMBA device ID are non-zero: id=0x%08X, mask=0x%08X. Please fix this driver.\n",
|
2024-11-19 23:56:44 +00:00
|
|
|
mod->name, id, mask);
|
2011-10-05 13:44:57 +00:00
|
|
|
|
|
|
|
for (digit = 0; digit < 8; digit++)
|
|
|
|
append_nibble_mask(&p,
|
2013-01-20 16:58:47 +00:00
|
|
|
(id >> (4 * (7 - digit))) & 0xf,
|
|
|
|
(mask >> (4 * (7 - digit))) & 0xf);
|
2011-10-05 13:44:57 +00:00
|
|
|
|
2024-11-19 23:56:45 +00:00
|
|
|
module_alias_printf(mod, false, "amba:d%s", alias);
|
2011-10-05 13:44:57 +00:00
|
|
|
}
|
|
|
|
|
2015-03-25 15:39:50 +00:00
|
|
|
/*
|
|
|
|
* looks like: "mipscdmm:tN"
|
|
|
|
*
|
|
|
|
* N is exactly 2 digits, where each is an upper-case hex digit, or
|
|
|
|
* a ? or [] pattern matching exactly one digit.
|
|
|
|
*/
|
2024-11-19 23:56:45 +00:00
|
|
|
static void do_mips_cdmm_entry(struct module *mod, void *symval)
|
2015-03-25 15:39:50 +00:00
|
|
|
{
|
|
|
|
DEF_FIELD(symval, mips_cdmm_device_id, type);
|
|
|
|
|
2024-11-19 23:56:45 +00:00
|
|
|
module_alias_printf(mod, false, "mipscdmm:t%02X*", type);
|
2015-03-25 15:39:50 +00:00
|
|
|
}
|
|
|
|
|
2014-02-08 12:34:10 +00:00
|
|
|
/* LOOKS like cpu:type:x86,venVVVVfamFFFFmodMMMM:feature:*,FEAT,*
|
2012-01-25 23:09:05 +00:00
|
|
|
* All fields are numbers. It would be nicer to use strings for vendor
|
|
|
|
* and feature, but getting those out of the build system here is too
|
|
|
|
* complicated.
|
|
|
|
*/
|
|
|
|
|
2024-11-19 23:56:45 +00:00
|
|
|
static void do_x86cpu_entry(struct module *mod, void *symval)
|
2012-01-25 23:09:05 +00:00
|
|
|
{
|
2024-11-19 23:56:45 +00:00
|
|
|
char alias[256] = {};
|
|
|
|
|
2013-01-20 16:58:47 +00:00
|
|
|
DEF_FIELD(symval, x86_cpu_id, feature);
|
|
|
|
DEF_FIELD(symval, x86_cpu_id, family);
|
|
|
|
DEF_FIELD(symval, x86_cpu_id, model);
|
|
|
|
DEF_FIELD(symval, x86_cpu_id, vendor);
|
2012-01-25 23:09:05 +00:00
|
|
|
|
2014-02-08 12:34:10 +00:00
|
|
|
ADD(alias, "ven", vendor != X86_VENDOR_ANY, vendor);
|
|
|
|
ADD(alias, "fam", family != X86_FAMILY_ANY, family);
|
|
|
|
ADD(alias, "mod", model != X86_MODEL_ANY, model);
|
2012-02-11 22:57:19 +00:00
|
|
|
strcat(alias, ":feature:*");
|
2013-01-20 16:58:47 +00:00
|
|
|
if (feature != X86_FEATURE_ANY)
|
|
|
|
sprintf(alias + strlen(alias), "%04X*", feature);
|
2024-11-19 23:56:45 +00:00
|
|
|
|
|
|
|
module_alias_printf(mod, false, "cpu:type:x86,%s", alias);
|
2012-01-25 23:09:05 +00:00
|
|
|
}
|
|
|
|
|
2014-02-08 12:34:09 +00:00
|
|
|
/* LOOKS like cpu:type:*:feature:*FEAT* */
|
2024-11-19 23:56:45 +00:00
|
|
|
static void do_cpu_entry(struct module *mod, void *symval)
|
2014-02-08 12:34:09 +00:00
|
|
|
{
|
|
|
|
DEF_FIELD(symval, cpu_feature, feature);
|
|
|
|
|
2024-11-19 23:56:45 +00:00
|
|
|
module_alias_printf(mod, false, "cpu:type:*:feature:*%04X*", feature);
|
2014-02-08 12:34:09 +00:00
|
|
|
}
|
|
|
|
|
2015-09-10 07:18:01 +00:00
|
|
|
/* Looks like: mei:S:uuid:N:* */
|
2024-11-19 23:56:45 +00:00
|
|
|
static void do_mei_entry(struct module *mod, void *symval)
|
2013-03-27 15:29:53 +00:00
|
|
|
{
|
2024-11-19 23:56:45 +00:00
|
|
|
char alias[256] = {};
|
|
|
|
|
2013-03-27 15:29:53 +00:00
|
|
|
DEF_FIELD_ADDR(symval, mei_cl_device_id, name);
|
2015-05-07 12:54:02 +00:00
|
|
|
DEF_FIELD_ADDR(symval, mei_cl_device_id, uuid);
|
2015-09-10 07:18:01 +00:00
|
|
|
DEF_FIELD(symval, mei_cl_device_id, version);
|
2015-05-07 12:54:02 +00:00
|
|
|
|
|
|
|
add_uuid(alias, *uuid);
|
2015-09-10 07:18:01 +00:00
|
|
|
ADD(alias, ":", version != MEI_CL_VERSION_ANY, version);
|
2013-03-27 15:29:53 +00:00
|
|
|
|
2024-11-19 23:56:45 +00:00
|
|
|
module_alias_printf(mod, false, MEI_CL_MODULE_PREFIX "%s:%s:*",
|
|
|
|
(*name)[0] ? *name : "*", alias);
|
2013-03-27 15:29:53 +00:00
|
|
|
}
|
|
|
|
|
2013-07-03 22:08:58 +00:00
|
|
|
/* Looks like: rapidio:vNdNavNadN */
|
2024-11-19 23:56:45 +00:00
|
|
|
static void do_rio_entry(struct module *mod, void *symval)
|
2013-07-03 22:08:58 +00:00
|
|
|
{
|
2024-11-19 23:56:45 +00:00
|
|
|
char alias[256] = {};
|
|
|
|
|
2013-07-03 22:08:58 +00:00
|
|
|
DEF_FIELD(symval, rio_device_id, did);
|
|
|
|
DEF_FIELD(symval, rio_device_id, vid);
|
|
|
|
DEF_FIELD(symval, rio_device_id, asm_did);
|
|
|
|
DEF_FIELD(symval, rio_device_id, asm_vid);
|
|
|
|
|
|
|
|
ADD(alias, "v", vid != RIO_ANY_ID, vid);
|
|
|
|
ADD(alias, "d", did != RIO_ANY_ID, did);
|
|
|
|
ADD(alias, "av", asm_vid != RIO_ANY_ID, asm_vid);
|
|
|
|
ADD(alias, "ad", asm_did != RIO_ANY_ID, asm_did);
|
|
|
|
|
2024-11-19 23:56:45 +00:00
|
|
|
module_alias_printf(mod, true, "rapidio:%s", alias);
|
2013-07-03 22:08:58 +00:00
|
|
|
}
|
|
|
|
|
2015-05-13 12:26:42 +00:00
|
|
|
/* Looks like: ulpi:vNpN */
|
2024-11-19 23:56:45 +00:00
|
|
|
static void do_ulpi_entry(struct module *mod, void *symval)
|
2015-05-13 12:26:42 +00:00
|
|
|
{
|
|
|
|
DEF_FIELD(symval, ulpi_device_id, vendor);
|
|
|
|
DEF_FIELD(symval, ulpi_device_id, product);
|
|
|
|
|
2024-11-19 23:56:45 +00:00
|
|
|
module_alias_printf(mod, false, "ulpi:v%04xp%04x", vendor, product);
|
2015-05-13 12:26:42 +00:00
|
|
|
}
|
|
|
|
|
2015-09-29 08:26:10 +00:00
|
|
|
/* Looks like: hdaudio:vNrNaN */
|
2024-11-19 23:56:45 +00:00
|
|
|
static void do_hda_entry(struct module *mod, void *symval)
|
2015-09-29 08:26:10 +00:00
|
|
|
{
|
2024-11-19 23:56:45 +00:00
|
|
|
char alias[256] = {};
|
|
|
|
|
2015-09-29 08:26:10 +00:00
|
|
|
DEF_FIELD(symval, hda_device_id, vendor_id);
|
|
|
|
DEF_FIELD(symval, hda_device_id, rev_id);
|
|
|
|
DEF_FIELD(symval, hda_device_id, api_version);
|
|
|
|
|
|
|
|
ADD(alias, "v", vendor_id != 0, vendor_id);
|
|
|
|
ADD(alias, "r", rev_id != 0, rev_id);
|
|
|
|
ADD(alias, "a", api_version != 0, api_version);
|
|
|
|
|
2024-11-19 23:56:45 +00:00
|
|
|
module_alias_printf(mod, true, "hdaudio:%s", alias);
|
2015-09-29 08:26:10 +00:00
|
|
|
}
|
|
|
|
|
2020-06-08 20:54:35 +00:00
|
|
|
/* Looks like: sdw:mNpNvNcN */
|
2024-11-19 23:56:45 +00:00
|
|
|
static void do_sdw_entry(struct module *mod, void *symval)
|
2017-12-14 05:49:33 +00:00
|
|
|
{
|
2024-11-19 23:56:45 +00:00
|
|
|
char alias[256] = {};
|
|
|
|
|
2017-12-14 05:49:33 +00:00
|
|
|
DEF_FIELD(symval, sdw_device_id, mfg_id);
|
|
|
|
DEF_FIELD(symval, sdw_device_id, part_id);
|
2020-06-08 20:54:35 +00:00
|
|
|
DEF_FIELD(symval, sdw_device_id, sdw_version);
|
|
|
|
DEF_FIELD(symval, sdw_device_id, class_id);
|
2017-12-14 05:49:33 +00:00
|
|
|
|
|
|
|
ADD(alias, "m", mfg_id != 0, mfg_id);
|
|
|
|
ADD(alias, "p", part_id != 0, part_id);
|
2020-06-08 20:54:35 +00:00
|
|
|
ADD(alias, "v", sdw_version != 0, sdw_version);
|
|
|
|
ADD(alias, "c", class_id != 0, class_id);
|
2017-12-14 05:49:33 +00:00
|
|
|
|
2024-11-19 23:56:45 +00:00
|
|
|
module_alias_printf(mod, true, "sdw:%s", alias);
|
2017-12-14 05:49:33 +00:00
|
|
|
}
|
|
|
|
|
2016-06-22 21:40:45 +00:00
|
|
|
/* Looks like: fsl-mc:vNdN */
|
2024-11-19 23:56:45 +00:00
|
|
|
static void do_fsl_mc_entry(struct module *mod, void *symval)
|
2016-06-22 21:40:45 +00:00
|
|
|
{
|
|
|
|
DEF_FIELD(symval, fsl_mc_device_id, vendor);
|
|
|
|
DEF_FIELD_ADDR(symval, fsl_mc_device_id, obj_type);
|
|
|
|
|
2024-11-19 23:56:45 +00:00
|
|
|
module_alias_printf(mod, false, "fsl-mc:v%08Xd%s", vendor, *obj_type);
|
2016-06-22 21:40:45 +00:00
|
|
|
}
|
|
|
|
|
2017-10-02 10:38:34 +00:00
|
|
|
/* Looks like: tbsvc:kSpNvNrN */
|
2024-11-19 23:56:45 +00:00
|
|
|
static void do_tbsvc_entry(struct module *mod, void *symval)
|
2017-10-02 10:38:34 +00:00
|
|
|
{
|
2024-11-19 23:56:45 +00:00
|
|
|
char alias[256] = {};
|
|
|
|
|
2017-10-02 10:38:34 +00:00
|
|
|
DEF_FIELD(symval, tb_service_id, match_flags);
|
|
|
|
DEF_FIELD_ADDR(symval, tb_service_id, protocol_key);
|
|
|
|
DEF_FIELD(symval, tb_service_id, protocol_id);
|
|
|
|
DEF_FIELD(symval, tb_service_id, protocol_version);
|
|
|
|
DEF_FIELD(symval, tb_service_id, protocol_revision);
|
|
|
|
|
|
|
|
if (match_flags & TBSVC_MATCH_PROTOCOL_KEY)
|
|
|
|
sprintf(alias + strlen(alias), "k%s", *protocol_key);
|
|
|
|
else
|
|
|
|
strcat(alias + strlen(alias), "k*");
|
|
|
|
ADD(alias, "p", match_flags & TBSVC_MATCH_PROTOCOL_ID, protocol_id);
|
|
|
|
ADD(alias, "v", match_flags & TBSVC_MATCH_PROTOCOL_VERSION,
|
|
|
|
protocol_version);
|
|
|
|
ADD(alias, "r", match_flags & TBSVC_MATCH_PROTOCOL_REVISION,
|
|
|
|
protocol_revision);
|
|
|
|
|
2024-11-19 23:56:45 +00:00
|
|
|
module_alias_printf(mod, true, "tbsvc:%s", alias);
|
2017-10-02 10:38:34 +00:00
|
|
|
}
|
|
|
|
|
2018-06-27 15:19:50 +00:00
|
|
|
/* Looks like: typec:idNmN */
|
2024-11-19 23:56:45 +00:00
|
|
|
static void do_typec_entry(struct module *mod, void *symval)
|
2018-06-27 15:19:50 +00:00
|
|
|
{
|
2024-11-19 23:56:45 +00:00
|
|
|
char alias[256] = {};
|
|
|
|
|
2018-06-27 15:19:50 +00:00
|
|
|
DEF_FIELD(symval, typec_device_id, svid);
|
|
|
|
DEF_FIELD(symval, typec_device_id, mode);
|
|
|
|
|
|
|
|
ADD(alias, "m", mode != TYPEC_ANY_MODE, mode);
|
|
|
|
|
2024-11-19 23:56:45 +00:00
|
|
|
module_alias_printf(mod, false, "typec:id%04X%s", svid, alias);
|
2018-06-27 15:19:50 +00:00
|
|
|
}
|
|
|
|
|
2019-01-29 05:49:35 +00:00
|
|
|
/* Looks like: tee:uuid */
|
2024-11-19 23:56:45 +00:00
|
|
|
static void do_tee_entry(struct module *mod, void *symval)
|
2019-01-29 05:49:35 +00:00
|
|
|
{
|
2023-10-07 17:04:44 +00:00
|
|
|
DEF_FIELD_ADDR(symval, tee_client_device_id, uuid);
|
2019-01-29 05:49:35 +00:00
|
|
|
|
2024-11-19 23:56:45 +00:00
|
|
|
module_alias_printf(mod, true,
|
|
|
|
"tee:%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x",
|
2023-10-07 17:04:44 +00:00
|
|
|
uuid->b[0], uuid->b[1], uuid->b[2], uuid->b[3], uuid->b[4],
|
|
|
|
uuid->b[5], uuid->b[6], uuid->b[7], uuid->b[8], uuid->b[9],
|
|
|
|
uuid->b[10], uuid->b[11], uuid->b[12], uuid->b[13], uuid->b[14],
|
|
|
|
uuid->b[15]);
|
2019-01-29 05:49:35 +00:00
|
|
|
}
|
|
|
|
|
2019-02-19 19:59:50 +00:00
|
|
|
/* Looks like: wmi:guid */
|
2024-11-19 23:56:45 +00:00
|
|
|
static void do_wmi_entry(struct module *mod, void *symval)
|
2019-02-19 19:59:50 +00:00
|
|
|
{
|
|
|
|
DEF_FIELD_ADDR(symval, wmi_device_id, guid_string);
|
|
|
|
|
|
|
|
if (strlen(*guid_string) != UUID_STRING_LEN) {
|
|
|
|
warn("Invalid WMI device id 'wmi:%s' in '%s'\n",
|
2024-11-19 23:56:44 +00:00
|
|
|
*guid_string, mod->name);
|
2024-11-19 23:56:45 +00:00
|
|
|
return;
|
2019-02-19 19:59:50 +00:00
|
|
|
}
|
|
|
|
|
2024-11-19 23:56:45 +00:00
|
|
|
module_alias_printf(mod, false, WMI_MODULE_PREFIX "%s", *guid_string);
|
2019-02-19 19:59:50 +00:00
|
|
|
}
|
|
|
|
|
2020-02-20 09:58:50 +00:00
|
|
|
/* Looks like: mhi:S */
|
2024-11-19 23:56:45 +00:00
|
|
|
static void do_mhi_entry(struct module *mod, void *symval)
|
2020-02-20 09:58:50 +00:00
|
|
|
{
|
|
|
|
DEF_FIELD_ADDR(symval, mhi_device_id, chan);
|
2024-11-19 23:56:45 +00:00
|
|
|
module_alias_printf(mod, false, MHI_DEVICE_MODALIAS_FMT, *chan);
|
2020-12-03 00:54:24 +00:00
|
|
|
}
|
|
|
|
|
2022-04-05 13:57:54 +00:00
|
|
|
/* Looks like: mhi_ep:S */
|
2024-11-19 23:56:45 +00:00
|
|
|
static void do_mhi_ep_entry(struct module *mod, void *symval)
|
2022-04-05 13:57:54 +00:00
|
|
|
{
|
|
|
|
DEF_FIELD_ADDR(symval, mhi_device_id, chan);
|
|
|
|
|
2024-11-19 23:56:45 +00:00
|
|
|
module_alias_printf(mod, false, MHI_EP_DEVICE_MODALIAS_FMT, *chan);
|
2022-04-05 13:57:54 +00:00
|
|
|
}
|
|
|
|
|
2021-10-29 15:28:56 +00:00
|
|
|
/* Looks like: ishtp:{guid} */
|
2024-11-19 23:56:45 +00:00
|
|
|
static void do_ishtp_entry(struct module *mod, void *symval)
|
2021-10-29 15:28:56 +00:00
|
|
|
{
|
2024-11-19 23:56:45 +00:00
|
|
|
char alias[256] = {};
|
2023-10-07 17:04:45 +00:00
|
|
|
DEF_FIELD_ADDR(symval, ishtp_device_id, guid);
|
2021-10-29 15:28:56 +00:00
|
|
|
|
2023-10-07 17:04:45 +00:00
|
|
|
add_guid(alias, *guid);
|
2021-10-29 15:28:56 +00:00
|
|
|
|
2024-11-19 23:56:45 +00:00
|
|
|
module_alias_printf(mod, false, ISHTP_MODULE_PREFIX "{%s}", alias);
|
2021-10-29 15:28:56 +00:00
|
|
|
}
|
|
|
|
|
2024-11-19 23:56:45 +00:00
|
|
|
static void do_auxiliary_entry(struct module *mod, void *symval)
|
2020-12-03 00:54:24 +00:00
|
|
|
{
|
|
|
|
DEF_FIELD_ADDR(symval, auxiliary_device_id, name);
|
2020-02-20 09:58:50 +00:00
|
|
|
|
2024-11-19 23:56:45 +00:00
|
|
|
module_alias_printf(mod, false, AUXILIARY_MODULE_PREFIX "%s", *name);
|
2020-02-20 09:58:50 +00:00
|
|
|
}
|
|
|
|
|
2020-12-21 18:39:56 +00:00
|
|
|
/*
|
|
|
|
* Looks like: ssam:dNcNtNiNfN
|
|
|
|
*
|
|
|
|
* N is exactly 2 digits, where each is an upper-case hex digit.
|
|
|
|
*/
|
2024-11-19 23:56:45 +00:00
|
|
|
static void do_ssam_entry(struct module *mod, void *symval)
|
2020-12-21 18:39:56 +00:00
|
|
|
{
|
2024-11-19 23:56:45 +00:00
|
|
|
char alias[256] = {};
|
|
|
|
|
2020-12-21 18:39:56 +00:00
|
|
|
DEF_FIELD(symval, ssam_device_id, match_flags);
|
|
|
|
DEF_FIELD(symval, ssam_device_id, domain);
|
|
|
|
DEF_FIELD(symval, ssam_device_id, category);
|
|
|
|
DEF_FIELD(symval, ssam_device_id, target);
|
|
|
|
DEF_FIELD(symval, ssam_device_id, instance);
|
|
|
|
DEF_FIELD(symval, ssam_device_id, function);
|
|
|
|
|
|
|
|
ADD(alias, "t", match_flags & SSAM_MATCH_TARGET, target);
|
|
|
|
ADD(alias, "i", match_flags & SSAM_MATCH_INSTANCE, instance);
|
|
|
|
ADD(alias, "f", match_flags & SSAM_MATCH_FUNCTION, function);
|
|
|
|
|
2024-11-19 23:56:45 +00:00
|
|
|
module_alias_printf(mod, false, "ssam:d%02Xc%02X%s",
|
|
|
|
domain, category, alias);
|
2020-12-21 18:39:56 +00:00
|
|
|
}
|
|
|
|
|
2021-01-07 04:37:11 +00:00
|
|
|
/* Looks like: dfl:tNfN */
|
2024-11-19 23:56:45 +00:00
|
|
|
static void do_dfl_entry(struct module *mod, void *symval)
|
2021-01-07 04:37:11 +00:00
|
|
|
{
|
|
|
|
DEF_FIELD(symval, dfl_device_id, type);
|
|
|
|
DEF_FIELD(symval, dfl_device_id, feature_id);
|
|
|
|
|
2024-11-19 23:56:45 +00:00
|
|
|
module_alias_printf(mod, true, "dfl:t%04Xf%04X", type, feature_id);
|
2021-01-07 04:37:11 +00:00
|
|
|
}
|
|
|
|
|
2023-03-13 13:26:30 +00:00
|
|
|
/* Looks like: cdx:vNdN */
|
2024-11-19 23:56:45 +00:00
|
|
|
static void do_cdx_entry(struct module *mod, void *symval)
|
2023-03-13 13:26:30 +00:00
|
|
|
{
|
2024-11-19 23:56:45 +00:00
|
|
|
char alias[256];
|
|
|
|
|
2023-03-13 13:26:30 +00:00
|
|
|
DEF_FIELD(symval, cdx_device_id, vendor);
|
|
|
|
DEF_FIELD(symval, cdx_device_id, device);
|
2023-10-17 16:05:05 +00:00
|
|
|
DEF_FIELD(symval, cdx_device_id, subvendor);
|
|
|
|
DEF_FIELD(symval, cdx_device_id, subdevice);
|
|
|
|
DEF_FIELD(symval, cdx_device_id, class);
|
|
|
|
DEF_FIELD(symval, cdx_device_id, class_mask);
|
2023-05-31 12:45:57 +00:00
|
|
|
DEF_FIELD(symval, cdx_device_id, override_only);
|
2023-03-13 13:26:30 +00:00
|
|
|
|
2023-05-31 12:45:57 +00:00
|
|
|
switch (override_only) {
|
|
|
|
case 0:
|
|
|
|
strcpy(alias, "cdx:");
|
|
|
|
break;
|
|
|
|
case CDX_ID_F_VFIO_DRIVER_OVERRIDE:
|
|
|
|
strcpy(alias, "vfio_cdx:");
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
warn("Unknown CDX driver_override alias %08X\n",
|
|
|
|
override_only);
|
2024-11-19 23:56:45 +00:00
|
|
|
return;
|
2023-05-31 12:45:57 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
ADD(alias, "v", vendor != CDX_ANY_ID, vendor);
|
|
|
|
ADD(alias, "d", device != CDX_ANY_ID, device);
|
2023-10-17 16:05:05 +00:00
|
|
|
ADD(alias, "sv", subvendor != CDX_ANY_ID, subvendor);
|
|
|
|
ADD(alias, "sd", subdevice != CDX_ANY_ID, subdevice);
|
|
|
|
ADD(alias, "c", class_mask == 0xFFFFFF, class);
|
|
|
|
|
2024-11-19 23:56:45 +00:00
|
|
|
module_alias_printf(mod, false, "%s", alias);
|
2023-03-13 13:26:30 +00:00
|
|
|
}
|
|
|
|
|
2024-11-19 23:56:45 +00:00
|
|
|
static void do_vchiq_entry(struct module *mod, void *symval)
|
2023-10-19 09:01:26 +00:00
|
|
|
{
|
|
|
|
DEF_FIELD_ADDR(symval, vchiq_device_id, name);
|
|
|
|
|
2024-11-19 23:56:45 +00:00
|
|
|
module_alias_printf(mod, false, "vchiq:%s", *name);
|
2023-10-19 09:01:26 +00:00
|
|
|
}
|
|
|
|
|
2024-02-12 14:50:06 +00:00
|
|
|
/* Looks like: coreboot:tN */
|
2024-11-19 23:56:45 +00:00
|
|
|
static void do_coreboot_entry(struct module *mod, void *symval)
|
2024-02-12 14:50:06 +00:00
|
|
|
{
|
|
|
|
DEF_FIELD(symval, coreboot_device_id, tag);
|
|
|
|
|
2024-11-19 23:56:45 +00:00
|
|
|
module_alias_printf(mod, false, "coreboot:t%08X", tag);
|
2024-02-12 14:50:06 +00:00
|
|
|
}
|
|
|
|
|
2012-01-12 23:02:15 +00:00
|
|
|
/* Does namelen bytes of name exactly match the symbol? */
|
|
|
|
static bool sym_is(const char *name, unsigned namelen, const char *symbol)
|
2005-04-16 22:20:36 +00:00
|
|
|
{
|
2012-01-12 23:02:15 +00:00
|
|
|
if (namelen != strlen(symbol))
|
|
|
|
return false;
|
2005-04-16 22:20:36 +00:00
|
|
|
|
2012-01-12 23:02:15 +00:00
|
|
|
return memcmp(name, symbol, namelen) == 0;
|
2005-04-16 22:20:36 +00:00
|
|
|
}
|
|
|
|
|
modpost: improve error messages in device_id_check()
The first error message in device_id_check() is obscure and can be
misleading because the cause of the error is unlikely to be found in
the struct definition in mod_devicetable.h.
This type of error occurs when an array is passed to an incorrect type
of MODULE_DEVICE_TABLE().
[Example 1]
static const struct acpi_device_id foo_ids[] = {
{ "FOO" },
{ /* sentinel */ },
};
MODULE_DEVICE_TABLE(of, foo_ids);
Currently, modpost outputs a meaningless suggestion:
ERROR: modpost: ...: sizeof(struct of_device_id)=200 is not a modulo of the size of section __mod_device_table__of__<identifier>=64.
Fix definition of struct of_device_id in mod_devicetable.h
The root cause here is that MODULE_DEVICE_TABLE(of, ...) is used instead
of the correct MODULE_DEVICE_TABLE(acpi, ...).
This commit provides a more intuitive error message:
ERROR: modpost: ...: type mismatch between foo_ids[] and MODULE_DEVICE_TABLE(of, ...)
The second error message, related to a missing terminator, is too
verbose.
[Example 2]
static const struct acpi_device_id foo_ids[] = {
{ "FOO" },
};
MODULE_DEVICE_TABLE(acpi, foo_ids);
The current error message is overly long, and does not pinpoint the
incorrect array:
...: struct acpi_device_id is 32 bytes. The last of 1 is:
0x46 0x4f 0x4f 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
ERROR: modpost: ...: struct acpi_device_id is not terminated with a NULL entry!
This commit changes it to a more concise error message, sufficient to
identify the incorrect array:
ERROR: modpost: ...: foo_ids[] is not terminated with a NULL entry
Lastly, this commit squashes device_id_check() into do_table() and
changes fatal() into error(), allowing modpost to continue processing
other modules.
Signed-off-by: Masahiro Yamada <masahiroy@kernel.org>
2024-11-19 23:56:53 +00:00
|
|
|
static void do_table(const char *name, void *symval, unsigned long size,
|
2005-04-16 22:20:36 +00:00
|
|
|
unsigned long id_size,
|
2006-07-09 14:26:07 +00:00
|
|
|
const char *device_id,
|
2024-11-19 23:56:45 +00:00
|
|
|
void (*do_entry)(struct module *mod, void *symval),
|
2005-04-16 22:20:36 +00:00
|
|
|
struct module *mod)
|
|
|
|
{
|
|
|
|
unsigned int i;
|
|
|
|
|
modpost: improve error messages in device_id_check()
The first error message in device_id_check() is obscure and can be
misleading because the cause of the error is unlikely to be found in
the struct definition in mod_devicetable.h.
This type of error occurs when an array is passed to an incorrect type
of MODULE_DEVICE_TABLE().
[Example 1]
static const struct acpi_device_id foo_ids[] = {
{ "FOO" },
{ /* sentinel */ },
};
MODULE_DEVICE_TABLE(of, foo_ids);
Currently, modpost outputs a meaningless suggestion:
ERROR: modpost: ...: sizeof(struct of_device_id)=200 is not a modulo of the size of section __mod_device_table__of__<identifier>=64.
Fix definition of struct of_device_id in mod_devicetable.h
The root cause here is that MODULE_DEVICE_TABLE(of, ...) is used instead
of the correct MODULE_DEVICE_TABLE(acpi, ...).
This commit provides a more intuitive error message:
ERROR: modpost: ...: type mismatch between foo_ids[] and MODULE_DEVICE_TABLE(of, ...)
The second error message, related to a missing terminator, is too
verbose.
[Example 2]
static const struct acpi_device_id foo_ids[] = {
{ "FOO" },
};
MODULE_DEVICE_TABLE(acpi, foo_ids);
The current error message is overly long, and does not pinpoint the
incorrect array:
...: struct acpi_device_id is 32 bytes. The last of 1 is:
0x46 0x4f 0x4f 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
ERROR: modpost: ...: struct acpi_device_id is not terminated with a NULL entry!
This commit changes it to a more concise error message, sufficient to
identify the incorrect array:
ERROR: modpost: ...: foo_ids[] is not terminated with a NULL entry
Lastly, this commit squashes device_id_check() into do_table() and
changes fatal() into error(), allowing modpost to continue processing
other modules.
Signed-off-by: Masahiro Yamada <masahiroy@kernel.org>
2024-11-19 23:56:53 +00:00
|
|
|
if (size % id_size || size < id_size) {
|
|
|
|
error("%s: type mismatch between %s[] and MODULE_DEVICE_TABLE(%s, ...)\n",
|
|
|
|
mod->name, name, device_id);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Verify the last entry is a terminator */
|
|
|
|
for (i = size - id_size; i < size; i++) {
|
|
|
|
if (*(uint8_t *)(symval + i)) {
|
|
|
|
error("%s: %s[] is not terminated with a NULL entry\n",
|
|
|
|
mod->name, name);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2005-04-16 22:20:36 +00:00
|
|
|
/* Leave last one: it's the terminator. */
|
|
|
|
size -= id_size;
|
|
|
|
|
2024-11-19 23:56:45 +00:00
|
|
|
for (i = 0; i < size; i += id_size)
|
|
|
|
do_entry(mod, symval + i);
|
2005-04-16 22:20:36 +00:00
|
|
|
}
|
|
|
|
|
2018-11-22 04:28:41 +00:00
|
|
|
static const struct devtable devtable[] = {
|
|
|
|
{"hid", SIZE_hid_device_id, do_hid_entry},
|
|
|
|
{"ieee1394", SIZE_ieee1394_device_id, do_ieee1394_entry},
|
|
|
|
{"pci", SIZE_pci_device_id, do_pci_entry},
|
|
|
|
{"ccw", SIZE_ccw_device_id, do_ccw_entry},
|
|
|
|
{"ap", SIZE_ap_device_id, do_ap_entry},
|
|
|
|
{"css", SIZE_css_device_id, do_css_entry},
|
|
|
|
{"serio", SIZE_serio_device_id, do_serio_entry},
|
|
|
|
{"acpi", SIZE_acpi_device_id, do_acpi_entry},
|
|
|
|
{"pcmcia", SIZE_pcmcia_device_id, do_pcmcia_entry},
|
|
|
|
{"vio", SIZE_vio_device_id, do_vio_entry},
|
|
|
|
{"input", SIZE_input_device_id, do_input_entry},
|
|
|
|
{"eisa", SIZE_eisa_device_id, do_eisa_entry},
|
|
|
|
{"parisc", SIZE_parisc_device_id, do_parisc_entry},
|
|
|
|
{"sdio", SIZE_sdio_device_id, do_sdio_entry},
|
|
|
|
{"ssb", SIZE_ssb_device_id, do_ssb_entry},
|
|
|
|
{"bcma", SIZE_bcma_device_id, do_bcma_entry},
|
|
|
|
{"virtio", SIZE_virtio_device_id, do_virtio_entry},
|
|
|
|
{"vmbus", SIZE_hv_vmbus_device_id, do_vmbus_entry},
|
|
|
|
{"rpmsg", SIZE_rpmsg_device_id, do_rpmsg_entry},
|
|
|
|
{"i2c", SIZE_i2c_device_id, do_i2c_entry},
|
2020-02-27 11:31:08 +00:00
|
|
|
{"i3c", SIZE_i3c_device_id, do_i3c_entry},
|
2024-09-02 14:10:04 +00:00
|
|
|
{"slim", SIZE_slim_device_id, do_slim_entry},
|
2018-11-22 04:28:41 +00:00
|
|
|
{"spi", SIZE_spi_device_id, do_spi_entry},
|
|
|
|
{"dmi", SIZE_dmi_system_id, do_dmi_entry},
|
|
|
|
{"platform", SIZE_platform_device_id, do_platform_entry},
|
|
|
|
{"mdio", SIZE_mdio_device_id, do_mdio_entry},
|
|
|
|
{"zorro", SIZE_zorro_device_id, do_zorro_entry},
|
|
|
|
{"isapnp", SIZE_isapnp_device_id, do_isapnp_entry},
|
|
|
|
{"ipack", SIZE_ipack_device_id, do_ipack_entry},
|
|
|
|
{"amba", SIZE_amba_id, do_amba_entry},
|
|
|
|
{"mipscdmm", SIZE_mips_cdmm_device_id, do_mips_cdmm_entry},
|
|
|
|
{"x86cpu", SIZE_x86_cpu_id, do_x86cpu_entry},
|
|
|
|
{"cpu", SIZE_cpu_feature, do_cpu_entry},
|
|
|
|
{"mei", SIZE_mei_cl_device_id, do_mei_entry},
|
|
|
|
{"rapidio", SIZE_rio_device_id, do_rio_entry},
|
|
|
|
{"ulpi", SIZE_ulpi_device_id, do_ulpi_entry},
|
|
|
|
{"hdaudio", SIZE_hda_device_id, do_hda_entry},
|
|
|
|
{"sdw", SIZE_sdw_device_id, do_sdw_entry},
|
|
|
|
{"fslmc", SIZE_fsl_mc_device_id, do_fsl_mc_entry},
|
|
|
|
{"tbsvc", SIZE_tb_service_id, do_tbsvc_entry},
|
|
|
|
{"typec", SIZE_typec_device_id, do_typec_entry},
|
2019-01-29 05:49:35 +00:00
|
|
|
{"tee", SIZE_tee_client_device_id, do_tee_entry},
|
2019-02-19 19:59:50 +00:00
|
|
|
{"wmi", SIZE_wmi_device_id, do_wmi_entry},
|
2020-02-20 09:58:50 +00:00
|
|
|
{"mhi", SIZE_mhi_device_id, do_mhi_entry},
|
2022-04-05 13:57:54 +00:00
|
|
|
{"mhi_ep", SIZE_mhi_device_id, do_mhi_ep_entry},
|
2020-12-03 00:54:24 +00:00
|
|
|
{"auxiliary", SIZE_auxiliary_device_id, do_auxiliary_entry},
|
2020-12-21 18:39:56 +00:00
|
|
|
{"ssam", SIZE_ssam_device_id, do_ssam_entry},
|
2021-01-07 04:37:11 +00:00
|
|
|
{"dfl", SIZE_dfl_device_id, do_dfl_entry},
|
2021-10-29 15:28:56 +00:00
|
|
|
{"ishtp", SIZE_ishtp_device_id, do_ishtp_entry},
|
2023-03-13 13:26:30 +00:00
|
|
|
{"cdx", SIZE_cdx_device_id, do_cdx_entry},
|
2023-10-19 09:01:26 +00:00
|
|
|
{"vchiq", SIZE_vchiq_device_id, do_vchiq_entry},
|
2024-02-12 14:50:06 +00:00
|
|
|
{"coreboot", SIZE_coreboot_device_id, do_coreboot_entry},
|
2024-11-19 23:56:48 +00:00
|
|
|
{"of", SIZE_of_device_id, do_of_entry},
|
2024-11-19 23:56:49 +00:00
|
|
|
{"usb", SIZE_usb_device_id, do_usb_entry_multi},
|
2024-11-19 23:56:47 +00:00
|
|
|
{"pnp", SIZE_pnp_device_id, do_pnp_device_entry},
|
2024-11-19 23:56:46 +00:00
|
|
|
{"pnp_card", SIZE_pnp_card_device_id, do_pnp_card_entry},
|
2018-11-22 04:28:41 +00:00
|
|
|
};
|
|
|
|
|
2005-04-16 22:20:36 +00:00
|
|
|
/* Create MODULE_ALIAS() statements.
|
|
|
|
* At this time, we cannot write the actual output C source yet,
|
|
|
|
* so we write into the mod->dev_table_buf buffer. */
|
|
|
|
void handle_moddevtable(struct module *mod, struct elf_info *info,
|
|
|
|
Elf_Sym *sym, const char *symname)
|
|
|
|
{
|
|
|
|
void *symval;
|
2007-09-16 09:15:46 +00:00
|
|
|
char *zeros = NULL;
|
2024-11-19 23:56:51 +00:00
|
|
|
const char *type, *name;
|
|
|
|
size_t typelen;
|
2024-11-19 23:56:52 +00:00
|
|
|
static const char *prefix = "__mod_device_table__";
|
2005-04-16 22:20:36 +00:00
|
|
|
|
|
|
|
/* We're looking for a section relative symbol */
|
2010-07-28 23:47:53 +00:00
|
|
|
if (!sym->st_shndx || get_secindex(info, sym) >= info->num_sections)
|
2005-04-16 22:20:36 +00:00
|
|
|
return;
|
|
|
|
|
2012-04-12 18:37:30 +00:00
|
|
|
/* We're looking for an object */
|
|
|
|
if (ELF_ST_TYPE(sym->st_info) != STT_OBJECT)
|
|
|
|
return;
|
|
|
|
|
2024-11-19 23:56:52 +00:00
|
|
|
/* All our symbols are of form __mod_device_table__<type>__<name>. */
|
|
|
|
if (!strstarts(symname, prefix))
|
2012-01-12 23:02:15 +00:00
|
|
|
return;
|
2024-11-19 23:56:52 +00:00
|
|
|
type = symname + strlen(prefix);
|
|
|
|
|
2024-11-19 23:56:51 +00:00
|
|
|
name = strstr(type, "__");
|
|
|
|
if (!name)
|
2014-02-03 00:44:13 +00:00
|
|
|
return;
|
2024-11-19 23:56:51 +00:00
|
|
|
typelen = name - type;
|
modpost: improve error messages in device_id_check()
The first error message in device_id_check() is obscure and can be
misleading because the cause of the error is unlikely to be found in
the struct definition in mod_devicetable.h.
This type of error occurs when an array is passed to an incorrect type
of MODULE_DEVICE_TABLE().
[Example 1]
static const struct acpi_device_id foo_ids[] = {
{ "FOO" },
{ /* sentinel */ },
};
MODULE_DEVICE_TABLE(of, foo_ids);
Currently, modpost outputs a meaningless suggestion:
ERROR: modpost: ...: sizeof(struct of_device_id)=200 is not a modulo of the size of section __mod_device_table__of__<identifier>=64.
Fix definition of struct of_device_id in mod_devicetable.h
The root cause here is that MODULE_DEVICE_TABLE(of, ...) is used instead
of the correct MODULE_DEVICE_TABLE(acpi, ...).
This commit provides a more intuitive error message:
ERROR: modpost: ...: type mismatch between foo_ids[] and MODULE_DEVICE_TABLE(of, ...)
The second error message, related to a missing terminator, is too
verbose.
[Example 2]
static const struct acpi_device_id foo_ids[] = {
{ "FOO" },
};
MODULE_DEVICE_TABLE(acpi, foo_ids);
The current error message is overly long, and does not pinpoint the
incorrect array:
...: struct acpi_device_id is 32 bytes. The last of 1 is:
0x46 0x4f 0x4f 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
ERROR: modpost: ...: struct acpi_device_id is not terminated with a NULL entry!
This commit changes it to a more concise error message, sufficient to
identify the incorrect array:
ERROR: modpost: ...: foo_ids[] is not terminated with a NULL entry
Lastly, this commit squashes device_id_check() into do_table() and
changes fatal() into error(), allowing modpost to continue processing
other modules.
Signed-off-by: Masahiro Yamada <masahiroy@kernel.org>
2024-11-19 23:56:53 +00:00
|
|
|
name += strlen("__");
|
2012-01-12 23:02:15 +00:00
|
|
|
|
2007-09-16 09:15:46 +00:00
|
|
|
/* Handle all-NULL symbols allocated into .bss */
|
2010-07-28 23:47:53 +00:00
|
|
|
if (info->sechdrs[get_secindex(info, sym)].sh_type & SHT_NOBITS) {
|
2007-09-16 09:15:46 +00:00
|
|
|
zeros = calloc(1, sym->st_size);
|
|
|
|
symval = zeros;
|
|
|
|
} else {
|
2022-07-19 16:53:00 +00:00
|
|
|
symval = sym_get_data(info, sym);
|
2007-09-16 09:15:46 +00:00
|
|
|
}
|
2005-04-16 22:20:36 +00:00
|
|
|
|
2024-11-19 23:56:49 +00:00
|
|
|
for (int i = 0; i < ARRAY_SIZE(devtable); i++) {
|
|
|
|
const struct devtable *p = &devtable[i];
|
2012-01-12 23:02:15 +00:00
|
|
|
|
2024-11-19 23:56:51 +00:00
|
|
|
if (sym_is(type, typelen, p->device_id)) {
|
modpost: improve error messages in device_id_check()
The first error message in device_id_check() is obscure and can be
misleading because the cause of the error is unlikely to be found in
the struct definition in mod_devicetable.h.
This type of error occurs when an array is passed to an incorrect type
of MODULE_DEVICE_TABLE().
[Example 1]
static const struct acpi_device_id foo_ids[] = {
{ "FOO" },
{ /* sentinel */ },
};
MODULE_DEVICE_TABLE(of, foo_ids);
Currently, modpost outputs a meaningless suggestion:
ERROR: modpost: ...: sizeof(struct of_device_id)=200 is not a modulo of the size of section __mod_device_table__of__<identifier>=64.
Fix definition of struct of_device_id in mod_devicetable.h
The root cause here is that MODULE_DEVICE_TABLE(of, ...) is used instead
of the correct MODULE_DEVICE_TABLE(acpi, ...).
This commit provides a more intuitive error message:
ERROR: modpost: ...: type mismatch between foo_ids[] and MODULE_DEVICE_TABLE(of, ...)
The second error message, related to a missing terminator, is too
verbose.
[Example 2]
static const struct acpi_device_id foo_ids[] = {
{ "FOO" },
};
MODULE_DEVICE_TABLE(acpi, foo_ids);
The current error message is overly long, and does not pinpoint the
incorrect array:
...: struct acpi_device_id is 32 bytes. The last of 1 is:
0x46 0x4f 0x4f 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
ERROR: modpost: ...: struct acpi_device_id is not terminated with a NULL entry!
This commit changes it to a more concise error message, sufficient to
identify the incorrect array:
ERROR: modpost: ...: foo_ids[] is not terminated with a NULL entry
Lastly, this commit squashes device_id_check() into do_table() and
changes fatal() into error(), allowing modpost to continue processing
other modules.
Signed-off-by: Masahiro Yamada <masahiroy@kernel.org>
2024-11-19 23:56:53 +00:00
|
|
|
do_table(name, symval, sym->st_size, p->id_size,
|
2024-11-19 23:56:49 +00:00
|
|
|
p->device_id, p->do_entry, mod);
|
|
|
|
break;
|
2012-01-12 23:02:15 +00:00
|
|
|
}
|
|
|
|
}
|
2024-11-19 23:56:49 +00:00
|
|
|
|
2007-09-16 09:15:46 +00:00
|
|
|
free(zeros);
|
2005-04-16 22:20:36 +00:00
|
|
|
}
|