diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2010-05-21 20:15:44 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2010-05-21 20:15:44 -0400 |
commit | a8251096b427283c47e7d8f9568be6b388dd68ec (patch) | |
tree | edc9747e30b4b4413aa99acfbd3104d81b1c303b | |
parent | 27a3353a4525afe984f3b793681869d636136b69 (diff) | |
parent | 480b02df3aa9f07d1c7df0cd8be7a5ca73893455 (diff) |
Merge branch 'modules' of git://git.kernel.org/pub/scm/linux/kernel/git/rusty/linux-2.6-for-linus
* 'modules' of git://git.kernel.org/pub/scm/linux/kernel/git/rusty/linux-2.6-for-linus:
module: drop the lock while waiting for module to complete initialization.
MODULE_DEVICE_TABLE(isapnp, ...) does nothing
hisax_fcpcipnp: fix broken isapnp device table.
isapnp: move definitions to mod_devicetable.h so file2alias can reach them.
-rw-r--r-- | drivers/isdn/hisax/hisax_fcpcipnp.c | 3 | ||||
-rw-r--r-- | include/linux/isapnp.h | 8 | ||||
-rw-r--r-- | include/linux/mod_devicetable.h | 7 | ||||
-rw-r--r-- | kernel/module.c | 59 | ||||
-rw-r--r-- | scripts/mod/file2alias.c | 17 |
5 files changed, 64 insertions, 30 deletions
diff --git a/drivers/isdn/hisax/hisax_fcpcipnp.c b/drivers/isdn/hisax/hisax_fcpcipnp.c index 1925118122f8..8b0a7d86b30f 100644 --- a/drivers/isdn/hisax/hisax_fcpcipnp.c +++ b/drivers/isdn/hisax/hisax_fcpcipnp.c | |||
@@ -74,9 +74,10 @@ static struct pnp_device_id fcpnp_ids[] __devinitdata = { | |||
74 | .id = "AVM0900", | 74 | .id = "AVM0900", |
75 | .driver_data = (unsigned long) "Fritz!Card PnP", | 75 | .driver_data = (unsigned long) "Fritz!Card PnP", |
76 | }, | 76 | }, |
77 | { .id = "" } | ||
77 | }; | 78 | }; |
78 | 79 | ||
79 | MODULE_DEVICE_TABLE(isapnp, fcpnp_ids); | 80 | MODULE_DEVICE_TABLE(pnp, fcpnp_ids); |
80 | #endif | 81 | #endif |
81 | 82 | ||
82 | static int protocol = 2; /* EURO-ISDN Default */ | 83 | static int protocol = 2; /* EURO-ISDN Default */ |
diff --git a/include/linux/isapnp.h b/include/linux/isapnp.h index cd5a269fdb5e..e2d28b026a8c 100644 --- a/include/linux/isapnp.h +++ b/include/linux/isapnp.h | |||
@@ -43,10 +43,10 @@ | |||
43 | */ | 43 | */ |
44 | 44 | ||
45 | #ifdef __KERNEL__ | 45 | #ifdef __KERNEL__ |
46 | #include <linux/mod_devicetable.h> | ||
46 | 47 | ||
47 | #define DEVICE_COUNT_COMPATIBLE 4 | 48 | #define DEVICE_COUNT_COMPATIBLE 4 |
48 | 49 | ||
49 | #define ISAPNP_ANY_ID 0xffff | ||
50 | #define ISAPNP_CARD_DEVS 8 | 50 | #define ISAPNP_CARD_DEVS 8 |
51 | 51 | ||
52 | #define ISAPNP_CARD_ID(_va, _vb, _vc, _device) \ | 52 | #define ISAPNP_CARD_ID(_va, _vb, _vc, _device) \ |
@@ -74,12 +74,6 @@ struct isapnp_card_id { | |||
74 | #define ISAPNP_DEVICE_SINGLE_END \ | 74 | #define ISAPNP_DEVICE_SINGLE_END \ |
75 | .card_vendor = 0, .card_device = 0 | 75 | .card_vendor = 0, .card_device = 0 |
76 | 76 | ||
77 | struct isapnp_device_id { | ||
78 | unsigned short card_vendor, card_device; | ||
79 | unsigned short vendor, function; | ||
80 | unsigned long driver_data; /* data private to the driver */ | ||
81 | }; | ||
82 | |||
83 | #if defined(CONFIG_ISAPNP) || (defined(CONFIG_ISAPNP_MODULE) && defined(MODULE)) | 77 | #if defined(CONFIG_ISAPNP) || (defined(CONFIG_ISAPNP_MODULE) && defined(MODULE)) |
84 | 78 | ||
85 | #define __ISAPNP__ | 79 | #define __ISAPNP__ |
diff --git a/include/linux/mod_devicetable.h b/include/linux/mod_devicetable.h index 007fbaafead0..48c007dae476 100644 --- a/include/linux/mod_devicetable.h +++ b/include/linux/mod_devicetable.h | |||
@@ -509,4 +509,11 @@ struct zorro_device_id { | |||
509 | 509 | ||
510 | #define ZORRO_DEVICE_MODALIAS_FMT "zorro:i%08X" | 510 | #define ZORRO_DEVICE_MODALIAS_FMT "zorro:i%08X" |
511 | 511 | ||
512 | #define ISAPNP_ANY_ID 0xffff | ||
513 | struct isapnp_device_id { | ||
514 | unsigned short card_vendor, card_device; | ||
515 | unsigned short vendor, function; | ||
516 | kernel_ulong_t driver_data; /* data private to the driver */ | ||
517 | }; | ||
518 | |||
512 | #endif /* LINUX_MOD_DEVICETABLE_H */ | 519 | #endif /* LINUX_MOD_DEVICETABLE_H */ |
diff --git a/kernel/module.c b/kernel/module.c index 3c4fc4bb4b82..a8014bfb5a4e 100644 --- a/kernel/module.c +++ b/kernel/module.c | |||
@@ -565,33 +565,26 @@ int use_module(struct module *a, struct module *b) | |||
565 | struct module_use *use; | 565 | struct module_use *use; |
566 | int no_warn, err; | 566 | int no_warn, err; |
567 | 567 | ||
568 | if (b == NULL || already_uses(a, b)) return 1; | 568 | if (b == NULL || already_uses(a, b)) |
569 | |||
570 | /* If we're interrupted or time out, we fail. */ | ||
571 | if (wait_event_interruptible_timeout( | ||
572 | module_wq, (err = strong_try_module_get(b)) != -EBUSY, | ||
573 | 30 * HZ) <= 0) { | ||
574 | printk("%s: gave up waiting for init of module %s.\n", | ||
575 | a->name, b->name); | ||
576 | return 0; | 569 | return 0; |
577 | } | ||
578 | 570 | ||
579 | /* If strong_try_module_get() returned a different error, we fail. */ | 571 | /* If we're interrupted or time out, we fail. */ |
572 | err = strong_try_module_get(b); | ||
580 | if (err) | 573 | if (err) |
581 | return 0; | 574 | return err; |
582 | 575 | ||
583 | DEBUGP("Allocating new usage for %s.\n", a->name); | 576 | DEBUGP("Allocating new usage for %s.\n", a->name); |
584 | use = kmalloc(sizeof(*use), GFP_ATOMIC); | 577 | use = kmalloc(sizeof(*use), GFP_ATOMIC); |
585 | if (!use) { | 578 | if (!use) { |
586 | printk("%s: out of memory loading\n", a->name); | 579 | printk("%s: out of memory loading\n", a->name); |
587 | module_put(b); | 580 | module_put(b); |
588 | return 0; | 581 | return -ENOMEM; |
589 | } | 582 | } |
590 | 583 | ||
591 | use->module_which_uses = a; | 584 | use->module_which_uses = a; |
592 | list_add(&use->list, &b->modules_which_use_me); | 585 | list_add(&use->list, &b->modules_which_use_me); |
593 | no_warn = sysfs_create_link(b->holders_dir, &a->mkobj.kobj, a->name); | 586 | no_warn = sysfs_create_link(b->holders_dir, &a->mkobj.kobj, a->name); |
594 | return 1; | 587 | return 0; |
595 | } | 588 | } |
596 | EXPORT_SYMBOL_GPL(use_module); | 589 | EXPORT_SYMBOL_GPL(use_module); |
597 | 590 | ||
@@ -884,7 +877,7 @@ static inline void module_unload_free(struct module *mod) | |||
884 | 877 | ||
885 | int use_module(struct module *a, struct module *b) | 878 | int use_module(struct module *a, struct module *b) |
886 | { | 879 | { |
887 | return strong_try_module_get(b) == 0; | 880 | return strong_try_module_get(b); |
888 | } | 881 | } |
889 | EXPORT_SYMBOL_GPL(use_module); | 882 | EXPORT_SYMBOL_GPL(use_module); |
890 | 883 | ||
@@ -1055,17 +1048,39 @@ static const struct kernel_symbol *resolve_symbol(Elf_Shdr *sechdrs, | |||
1055 | struct module *owner; | 1048 | struct module *owner; |
1056 | const struct kernel_symbol *sym; | 1049 | const struct kernel_symbol *sym; |
1057 | const unsigned long *crc; | 1050 | const unsigned long *crc; |
1051 | DEFINE_WAIT(wait); | ||
1052 | int err; | ||
1053 | long timeleft = 30 * HZ; | ||
1058 | 1054 | ||
1055 | again: | ||
1059 | sym = find_symbol(name, &owner, &crc, | 1056 | sym = find_symbol(name, &owner, &crc, |
1060 | !(mod->taints & (1 << TAINT_PROPRIETARY_MODULE)), true); | 1057 | !(mod->taints & (1 << TAINT_PROPRIETARY_MODULE)), true); |
1061 | /* use_module can fail due to OOM, | 1058 | if (!sym) |
1062 | or module initialization or unloading */ | 1059 | return NULL; |
1063 | if (sym) { | 1060 | |
1064 | if (!check_version(sechdrs, versindex, name, mod, crc, owner) | 1061 | if (!check_version(sechdrs, versindex, name, mod, crc, owner)) |
1065 | || !use_module(mod, owner)) | 1062 | return NULL; |
1066 | sym = NULL; | 1063 | |
1067 | } | 1064 | prepare_to_wait(&module_wq, &wait, TASK_INTERRUPTIBLE); |
1068 | return sym; | 1065 | err = use_module(mod, owner); |
1066 | if (likely(!err) || err != -EBUSY || signal_pending(current)) { | ||
1067 | finish_wait(&module_wq, &wait); | ||
1068 | return err ? NULL : sym; | ||
1069 | } | ||
1070 | |||
1071 | /* Module is still loading. Drop lock and wait. */ | ||
1072 | mutex_unlock(&module_mutex); | ||
1073 | timeleft = schedule_timeout(timeleft); | ||
1074 | mutex_lock(&module_mutex); | ||
1075 | finish_wait(&module_wq, &wait); | ||
1076 | |||
1077 | /* Module might be gone entirely, or replaced. Re-lookup. */ | ||
1078 | if (timeleft) | ||
1079 | goto again; | ||
1080 | |||
1081 | printk(KERN_WARNING "%s: gave up waiting for init of module %s.\n", | ||
1082 | mod->name, owner->name); | ||
1083 | return NULL; | ||
1069 | } | 1084 | } |
1070 | 1085 | ||
1071 | /* | 1086 | /* |
diff --git a/scripts/mod/file2alias.c b/scripts/mod/file2alias.c index 9cf2400580a7..5758aab0d8bb 100644 --- a/scripts/mod/file2alias.c +++ b/scripts/mod/file2alias.c | |||
@@ -828,6 +828,19 @@ static int do_zorro_entry(const char *filename, struct zorro_device_id *id, | |||
828 | return 1; | 828 | return 1; |
829 | } | 829 | } |
830 | 830 | ||
831 | /* looks like: "pnp:dD" */ | ||
832 | static int do_isapnp_entry(const char *filename, | ||
833 | struct isapnp_device_id *id, char *alias) | ||
834 | { | ||
835 | sprintf(alias, "pnp:d%c%c%c%x%x%x%x*", | ||
836 | 'A' + ((id->vendor >> 2) & 0x3f) - 1, | ||
837 | 'A' + (((id->vendor & 3) << 3) | ((id->vendor >> 13) & 7)) - 1, | ||
838 | 'A' + ((id->vendor >> 8) & 0x1f) - 1, | ||
839 | (id->function >> 4) & 0x0f, id->function & 0x0f, | ||
840 | (id->function >> 12) & 0x0f, (id->function >> 8) & 0x0f); | ||
841 | return 1; | ||
842 | } | ||
843 | |||
831 | /* Ignore any prefix, eg. some architectures prepend _ */ | 844 | /* Ignore any prefix, eg. some architectures prepend _ */ |
832 | static inline int sym_is(const char *symbol, const char *name) | 845 | static inline int sym_is(const char *symbol, const char *name) |
833 | { | 846 | { |
@@ -983,6 +996,10 @@ void handle_moddevtable(struct module *mod, struct elf_info *info, | |||
983 | do_table(symval, sym->st_size, | 996 | do_table(symval, sym->st_size, |
984 | sizeof(struct zorro_device_id), "zorro", | 997 | sizeof(struct zorro_device_id), "zorro", |
985 | do_zorro_entry, mod); | 998 | do_zorro_entry, mod); |
999 | else if (sym_is(symname, "__mod_isapnp_device_table")) | ||
1000 | do_table(symval, sym->st_size, | ||
1001 | sizeof(struct isapnp_device_id), "isa", | ||
1002 | do_isapnp_entry, mod); | ||
986 | free(zeros); | 1003 | free(zeros); |
987 | } | 1004 | } |
988 | 1005 | ||