From fb33d81613a4e3e27972a65b6e566de50a447d33 Mon Sep 17 00:00:00 2001 From: Sam Ravnborg Date: Sun, 9 Jul 2006 16:26:07 +0200 Subject: kbuild: improve error from file2alias The original errormessage was just plain unreadable. Sample error message after this update (not for real - I provoked it): FATAL: drivers/net/s2io: sizeof(struct pci_device_id)=33 is not a modulo of the size of section __mod_pci_device_table=160. Fix definition of struct pci_device_id in mod_devicetable.h Before a warning was generated - this is now a fatal error. Signed-off-by: Sam Ravnborg --- scripts/mod/file2alias.c | 62 +++++++++++++++++++++++++++++++++--------------- 1 file changed, 43 insertions(+), 19 deletions(-) (limited to 'scripts/mod/file2alias.c') diff --git a/scripts/mod/file2alias.c b/scripts/mod/file2alias.c index 37f67c23e11b..44312926b849 100644 --- a/scripts/mod/file2alias.c +++ b/scripts/mod/file2alias.c @@ -52,6 +52,23 @@ do { \ sprintf(str + strlen(str), "*"); \ } while(0) +/** + * Check that sizeof(device_id type) are consistent with size of section + * in .o file. If in-consistent then userspace and kernel does not agree + * on actual size which is a bug. + **/ +static void device_id_size_check(const char *modname, const char *device_id, + unsigned long size, unsigned long id_size) +{ + if (size % id_size || size < id_size) { + fatal("%s: sizeof(struct %s_device_id)=%lu is not a modulo " + "of the size of section __mod_%s_device_table=%lu.\n" + "Fix definition of struct %s_device_id " + "in mod_devicetable.h\n", + modname, device_id, id_size, device_id, size, device_id); + } +} + /* USB is special because the bcdDevice can be matched against a numeric range */ /* Looks like "usb:vNpNdNdcNdscNdpNicNiscNipN" */ static void do_usb_entry(struct usb_device_id *id, @@ -152,10 +169,8 @@ static void do_usb_table(void *symval, unsigned long size, unsigned int i; const unsigned long id_size = sizeof(struct usb_device_id); - if (size % id_size || size < id_size) { - warn("%s ids %lu bad size " - "(each on %lu)\n", mod->name, size, id_size); - } + device_id_size_check(mod->name, "usb", size, id_size); + /* Leave last one: it's the terminator. */ size -= id_size; @@ -434,6 +449,7 @@ static inline int sym_is(const char *symbol, const char *name) static void do_table(void *symval, unsigned long size, unsigned long id_size, + const char *device_id, void *function, struct module *mod) { @@ -441,10 +457,7 @@ static void do_table(void *symval, unsigned long size, char alias[500]; int (*do_entry)(const char *, void *entry, char *alias) = function; - if (size % id_size || size < id_size) { - warn("%s ids %lu bad size " - "(each on %lu)\n", mod->name, size, id_size); - } + device_id_size_check(mod->name, device_id, size, id_size); /* Leave last one: it's the terminator. */ size -= id_size; @@ -476,40 +489,51 @@ void handle_moddevtable(struct module *mod, struct elf_info *info, + sym->st_value; if (sym_is(symname, "__mod_pci_device_table")) - do_table(symval, sym->st_size, sizeof(struct pci_device_id), + do_table(symval, sym->st_size, + sizeof(struct pci_device_id), "pci", do_pci_entry, mod); else if (sym_is(symname, "__mod_usb_device_table")) /* special case to handle bcdDevice ranges */ do_usb_table(symval, sym->st_size, mod); else if (sym_is(symname, "__mod_ieee1394_device_table")) - do_table(symval, sym->st_size, sizeof(struct ieee1394_device_id), + do_table(symval, sym->st_size, + sizeof(struct ieee1394_device_id), "ieee1394", do_ieee1394_entry, mod); else if (sym_is(symname, "__mod_ccw_device_table")) - do_table(symval, sym->st_size, sizeof(struct ccw_device_id), + do_table(symval, sym->st_size, + sizeof(struct ccw_device_id), "ccw", do_ccw_entry, mod); else if (sym_is(symname, "__mod_serio_device_table")) - do_table(symval, sym->st_size, sizeof(struct serio_device_id), + do_table(symval, sym->st_size, + sizeof(struct serio_device_id), "serio", do_serio_entry, mod); else if (sym_is(symname, "__mod_pnp_device_table")) - do_table(symval, sym->st_size, sizeof(struct pnp_device_id), + do_table(symval, sym->st_size, + sizeof(struct pnp_device_id), "pnp", do_pnp_entry, mod); else if (sym_is(symname, "__mod_pnp_card_device_table")) - do_table(symval, sym->st_size, sizeof(struct pnp_card_device_id), + do_table(symval, sym->st_size, + sizeof(struct pnp_card_device_id), "pnp_card", do_pnp_card_entry, mod); else if (sym_is(symname, "__mod_pcmcia_device_table")) - do_table(symval, sym->st_size, sizeof(struct pcmcia_device_id), + do_table(symval, sym->st_size, + sizeof(struct pcmcia_device_id), "pcmcia", do_pcmcia_entry, mod); else if (sym_is(symname, "__mod_of_device_table")) - do_table(symval, sym->st_size, sizeof(struct of_device_id), + do_table(symval, sym->st_size, + sizeof(struct of_device_id), "of", do_of_entry, mod); else if (sym_is(symname, "__mod_vio_device_table")) - do_table(symval, sym->st_size, sizeof(struct vio_device_id), + do_table(symval, sym->st_size, + sizeof(struct vio_device_id), "vio", do_vio_entry, mod); else if (sym_is(symname, "__mod_i2c_device_table")) - do_table(symval, sym->st_size, sizeof(struct i2c_device_id), + do_table(symval, sym->st_size, + sizeof(struct i2c_device_id), "i2c", do_i2c_entry, mod); else if (sym_is(symname, "__mod_input_device_table")) - do_table(symval, sym->st_size, sizeof(struct input_device_id), + do_table(symval, sym->st_size, + sizeof(struct input_device_id), "input", do_input_entry, mod); } -- cgit v1.2.3 From e0e92632715f08dddeddb72b76e04c20126e1f67 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Tue, 15 Aug 2006 12:09:27 +0200 Subject: [PATCH] PATCH: 1 line 2.6.18 bugfix: modpost-64bit-fix.patch There is a small but annoying bug in scripts/mod/file2alias.c which causes it to generate invalid aliases for input devices on 64 bit archs. This causes joydev.ko to not be automaticly loaded when inserting a joystick, resulting in a non working joystick (for the average user). In scripts/mod/file2alias.c is the following code for generating the input aliases: static void do_input(char *alias, kernel_ulong_t *arr, unsigned int min, unsigned int max) { unsigned int i; for (i = min; i < max; i++) if (arr[i / BITS_PER_LONG] & (1 << (i%BITS_PER_LONG))) sprintf(alias + strlen(alias), "%X,*", i); } On 32 bits systems, this correctly generates "0,*" for the first alias, "8,*" for the second etc. However on 64 bits it generates: "0,*20,*" resp "8,*28,*" Notice how it adds 20 + first entry (hex) ! to the list of hex codes, which is 32 more then the first entry, thus is because the bit test above wraps at 32 bits instead of 64. scripts/mod/file2alias.c, line 379 reads: if (arr[i / BITS_PER_LONG] & (1 << (i%BITS_PER_LONG))) That should be: if (arr[i / BITS_PER_LONG] & (1L << (i%BITS_PER_LONG))) Notice the added 'L' after the 1, otherwise that is an 32 bit int instead of a 64 bit long, and when that int gets shifted >= 32 times, appearantly the number by which to shift is wrapped at 5 bits ( % 32) causing it to test a bit 32 bits too low. The patch below makes the nescesarry 1 char change :) Signed-off-by: Hans de Goede Acked-by: Rusty Russell Signed-off-by: Greg Kroah-Hartman --- scripts/mod/file2alias.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'scripts/mod/file2alias.c') diff --git a/scripts/mod/file2alias.c b/scripts/mod/file2alias.c index 44312926b849..e2de650d3dbf 100644 --- a/scripts/mod/file2alias.c +++ b/scripts/mod/file2alias.c @@ -391,7 +391,7 @@ static void do_input(char *alias, unsigned int i; for (i = min; i < max; i++) - if (arr[i / BITS_PER_LONG] & (1 << (i%BITS_PER_LONG))) + if (arr[i / BITS_PER_LONG] & (1L << (i%BITS_PER_LONG))) sprintf(alias + strlen(alias), "%X,*", i); } -- cgit v1.2.3