Commit acbef7b7 authored by Philipp Zabel's avatar Philipp Zabel Committed by Linus Torvalds

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 2f632369
("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: 2f632369 ("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.deSigned-off-by: default avatarPhilipp 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: default avatarAndrew Morton <akpm@linux-foundation.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
parent 8148a73c
...@@ -371,6 +371,49 @@ static void do_usb_table(void *symval, unsigned long size, ...@@ -371,6 +371,49 @@ static void do_usb_table(void *symval, unsigned long size,
do_usb_entry_multi(symval + i, mod); do_usb_entry_multi(symval + i, mod);
} }
static void do_of_entry_multi(void *symval, struct module *mod)
{
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 : "*");
if (compatible[0])
sprintf(&alias[len], "%sC%s", (*type)[0] ? "*" : "",
*compatible);
/* Replace all whitespace with underscores */
for (tmp = alias; tmp && *tmp; tmp++)
if (isspace(*tmp))
*tmp = '_';
buf_printf(&mod->dev_table_buf, "MODULE_ALIAS(\"%s\");\n", alias);
strcat(alias, "C");
add_wildcard(alias);
buf_printf(&mod->dev_table_buf, "MODULE_ALIAS(\"%s\");\n", alias);
}
static void do_of_table(void *symval, unsigned long size,
struct module *mod)
{
unsigned int i;
const unsigned long id_size = SIZE_of_device_id;
device_id_check(mod->name, "of", size, id_size, symval);
/* Leave last one: it's the terminator. */
size -= id_size;
for (i = 0; i < size; i += id_size)
do_of_entry_multi(symval + i, mod);
}
/* Looks like: hid:bNvNpN */ /* Looks like: hid:bNvNpN */
static int do_hid_entry(const char *filename, static int do_hid_entry(const char *filename,
void *symval, char *alias) void *symval, char *alias)
...@@ -684,30 +727,6 @@ static int do_pcmcia_entry(const char *filename, ...@@ -684,30 +727,6 @@ static int do_pcmcia_entry(const char *filename,
} }
ADD_TO_DEVTABLE("pcmcia", pcmcia_device_id, do_pcmcia_entry); ADD_TO_DEVTABLE("pcmcia", pcmcia_device_id, do_pcmcia_entry);
static int do_of_entry (const char *filename, void *symval, char *alias)
{
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 : "*");
if (compatible[0])
sprintf(&alias[len], "%sC%s", (*type)[0] ? "*" : "",
*compatible);
/* Replace all whitespace with underscores */
for (tmp = alias; tmp && *tmp; tmp++)
if (isspace (*tmp))
*tmp = '_';
return 1;
}
ADD_TO_DEVTABLE("of", of_device_id, do_of_entry);
static int do_vio_entry(const char *filename, void *symval, static int do_vio_entry(const char *filename, void *symval,
char *alias) char *alias)
{ {
...@@ -1348,6 +1367,8 @@ void handle_moddevtable(struct module *mod, struct elf_info *info, ...@@ -1348,6 +1367,8 @@ void handle_moddevtable(struct module *mod, struct elf_info *info,
/* First handle the "special" cases */ /* First handle the "special" cases */
if (sym_is(name, namelen, "usb")) if (sym_is(name, namelen, "usb"))
do_usb_table(symval, sym->st_size, mod); do_usb_table(symval, sym->st_size, mod);
if (sym_is(name, namelen, "of"))
do_of_table(symval, sym->st_size, mod);
else if (sym_is(name, namelen, "pnp")) else if (sym_is(name, namelen, "pnp"))
do_pnp_device_entry(symval, sym->st_size, mod); do_pnp_device_entry(symval, sym->st_size, mod);
else if (sym_is(name, namelen, "pnp_card")) else if (sym_is(name, namelen, "pnp_card"))
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment