diff options
| author | Rusty Russell <rusty@rustcorp.com.au> | 2012-01-12 18:02:15 -0500 |
|---|---|---|
| committer | Rusty Russell <rusty@rustcorp.com.au> | 2012-01-12 18:02:15 -0500 |
| commit | 626596e295d477c0fefa08cd5daa7dd011b1bb2c (patch) | |
| tree | 92d3394766c12b54c9a4fe89fe8e3f6fde89ce5a /scripts/mod | |
| parent | cca3e707301862ca9b9327e6a732463982f8cd1b (diff) | |
modpost: use a table rather than a giant if/else statement.
We look for symbols of form __mod_<busname>_device_table, and for all
but three cases we use a standard interation function (do_table) to
walk over the contents and dump out the aliases.
Alessandro Rubini did this first, I just repainted the bikeshed a bit.
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
Cc: Alessandro Rubini <rubini@gnudd.com>
Diffstat (limited to 'scripts/mod')
| -rw-r--r-- | scripts/mod/file2alias.c | 192 |
1 files changed, 73 insertions, 119 deletions
diff --git a/scripts/mod/file2alias.c b/scripts/mod/file2alias.c index 363ab4666b17..395e7479bcf7 100644 --- a/scripts/mod/file2alias.c +++ b/scripts/mod/file2alias.c | |||
| @@ -28,6 +28,7 @@ typedef Elf64_Addr kernel_ulong_t; | |||
| 28 | #endif | 28 | #endif |
| 29 | 29 | ||
| 30 | #include <ctype.h> | 30 | #include <ctype.h> |
| 31 | #include <stdbool.h> | ||
| 31 | 32 | ||
| 32 | typedef uint32_t __u32; | 33 | typedef uint32_t __u32; |
| 33 | typedef uint16_t __u16; | 34 | typedef uint16_t __u16; |
| @@ -948,15 +949,13 @@ static int do_amba_entry(const char *filename, | |||
| 948 | return 1; | 949 | return 1; |
| 949 | } | 950 | } |
| 950 | 951 | ||
| 951 | /* Ignore any prefix, eg. some architectures prepend _ */ | 952 | /* Does namelen bytes of name exactly match the symbol? */ |
| 952 | static inline int sym_is(const char *symbol, const char *name) | 953 | static bool sym_is(const char *name, unsigned namelen, const char *symbol) |
| 953 | { | 954 | { |
| 954 | const char *match; | 955 | if (namelen != strlen(symbol)) |
| 956 | return false; | ||
| 955 | 957 | ||
| 956 | match = strstr(symbol, name); | 958 | return memcmp(name, symbol, namelen) == 0; |
| 957 | if (!match) | ||
| 958 | return 0; | ||
| 959 | return match[strlen(name)] == '\0'; | ||
| 960 | } | 959 | } |
| 961 | 960 | ||
| 962 | static void do_table(void *symval, unsigned long size, | 961 | static void do_table(void *symval, unsigned long size, |
| @@ -981,6 +980,43 @@ static void do_table(void *symval, unsigned long size, | |||
| 981 | } | 980 | } |
| 982 | } | 981 | } |
| 983 | 982 | ||
| 983 | /* This array collects all instances that use the generic do_table above */ | ||
| 984 | struct devtable_switch { | ||
| 985 | const char *device_id; /* name of table, __mod_<name>_device_table. */ | ||
| 986 | unsigned long id_size; | ||
| 987 | void *function; | ||
| 988 | }; | ||
| 989 | |||
| 990 | static const struct devtable_switch devtable_switch[] = { | ||
| 991 | { "acpi", sizeof(struct acpi_device_id), do_acpi_entry }, | ||
| 992 | { "amba", sizeof(struct amba_id), do_amba_entry }, | ||
| 993 | { "ap", sizeof(struct ap_device_id), do_ap_entry }, | ||
| 994 | { "bcma", sizeof(struct bcma_device_id), do_bcma_entry }, | ||
| 995 | { "ccw", sizeof(struct ccw_device_id), do_ccw_entry }, | ||
| 996 | { "css", sizeof(struct css_device_id), do_css_entry }, | ||
| 997 | { "dmi", sizeof(struct dmi_system_id), do_dmi_entry }, | ||
| 998 | { "eisa", sizeof(struct eisa_device_id), do_eisa_entry }, | ||
| 999 | { "hid", sizeof(struct hid_device_id), do_hid_entry }, | ||
| 1000 | { "i2c", sizeof(struct i2c_device_id), do_i2c_entry }, | ||
| 1001 | { "ieee1394", sizeof(struct ieee1394_device_id), do_ieee1394_entry }, | ||
| 1002 | { "input", sizeof(struct input_device_id), do_input_entry }, | ||
| 1003 | { "isa", sizeof(struct isapnp_device_id), do_isapnp_entry }, | ||
| 1004 | { "mdio", sizeof(struct mdio_device_id), do_mdio_entry }, | ||
| 1005 | { "of", sizeof(struct of_device_id), do_of_entry }, | ||
| 1006 | { "parisc", sizeof(struct parisc_device_id), do_parisc_entry }, | ||
| 1007 | { "pci", sizeof(struct pci_device_id), do_pci_entry }, | ||
| 1008 | { "pcmcia", sizeof(struct pcmcia_device_id), do_pcmcia_entry }, | ||
| 1009 | { "platform", sizeof(struct platform_device_id), do_platform_entry }, | ||
| 1010 | { "sdio", sizeof(struct sdio_device_id), do_sdio_entry }, | ||
| 1011 | { "serio", sizeof(struct serio_device_id), do_serio_entry }, | ||
| 1012 | { "spi", sizeof(struct spi_device_id), do_spi_entry }, | ||
| 1013 | { "ssb", sizeof(struct ssb_device_id), do_ssb_entry }, | ||
| 1014 | { "vio", sizeof(struct vio_device_id), do_vio_entry }, | ||
| 1015 | { "virtio", sizeof(struct virtio_device_id), do_virtio_entry }, | ||
| 1016 | { "vmbus", sizeof(struct hv_vmbus_device_id), do_vmbus_entry }, | ||
| 1017 | { "zorro", sizeof(struct zorro_device_id), do_zorro_entry }, | ||
| 1018 | }; | ||
| 1019 | |||
| 984 | /* Create MODULE_ALIAS() statements. | 1020 | /* Create MODULE_ALIAS() statements. |
| 985 | * At this time, we cannot write the actual output C source yet, | 1021 | * At this time, we cannot write the actual output C source yet, |
| 986 | * so we write into the mod->dev_table_buf buffer. */ | 1022 | * so we write into the mod->dev_table_buf buffer. */ |
| @@ -989,11 +1025,25 @@ void handle_moddevtable(struct module *mod, struct elf_info *info, | |||
| 989 | { | 1025 | { |
| 990 | void *symval; | 1026 | void *symval; |
| 991 | char *zeros = NULL; | 1027 | char *zeros = NULL; |
| 1028 | const char *name; | ||
| 1029 | unsigned int namelen; | ||
| 992 | 1030 | ||
| 993 | /* We're looking for a section relative symbol */ | 1031 | /* We're looking for a section relative symbol */ |
| 994 | if (!sym->st_shndx || get_secindex(info, sym) >= info->num_sections) | 1032 | if (!sym->st_shndx || get_secindex(info, sym) >= info->num_sections) |
| 995 | return; | 1033 | return; |
| 996 | 1034 | ||
| 1035 | /* All our symbols are of form <prefix>__mod_XXX_device_table. */ | ||
| 1036 | name = strstr(symname, "__mod_"); | ||
| 1037 | if (!name) | ||
| 1038 | return; | ||
| 1039 | name += strlen("__mod_"); | ||
| 1040 | namelen = strlen(name); | ||
| 1041 | if (namelen < strlen("_device_table")) | ||
| 1042 | return; | ||
| 1043 | if (strcmp(name + namelen - strlen("_device_table"), "_device_table")) | ||
| 1044 | return; | ||
| 1045 | namelen -= strlen("_device_table"); | ||
| 1046 | |||
| 997 | /* Handle all-NULL symbols allocated into .bss */ | 1047 | /* Handle all-NULL symbols allocated into .bss */ |
| 998 | if (info->sechdrs[get_secindex(info, sym)].sh_type & SHT_NOBITS) { | 1048 | if (info->sechdrs[get_secindex(info, sym)].sh_type & SHT_NOBITS) { |
| 999 | zeros = calloc(1, sym->st_size); | 1049 | zeros = calloc(1, sym->st_size); |
| @@ -1004,121 +1054,25 @@ void handle_moddevtable(struct module *mod, struct elf_info *info, | |||
| 1004 | + sym->st_value; | 1054 | + sym->st_value; |
| 1005 | } | 1055 | } |
| 1006 | 1056 | ||
| 1007 | if (sym_is(symname, "__mod_pci_device_table")) | 1057 | /* First handle the "special" cases */ |
| 1008 | do_table(symval, sym->st_size, | 1058 | if (sym_is(name, namelen, "usb")) |
| 1009 | sizeof(struct pci_device_id), "pci", | ||
| 1010 | do_pci_entry, mod); | ||
| 1011 | else if (sym_is(symname, "__mod_usb_device_table")) | ||
| 1012 | /* special case to handle bcdDevice ranges */ | ||
| 1013 | do_usb_table(symval, sym->st_size, mod); | 1059 | do_usb_table(symval, sym->st_size, mod); |
| 1014 | else if (sym_is(symname, "__mod_hid_device_table")) | 1060 | else if (sym_is(name, namelen, "pnp")) |
| 1015 | do_table(symval, sym->st_size, | ||
| 1016 | sizeof(struct hid_device_id), "hid", | ||
| 1017 | do_hid_entry, mod); | ||
| 1018 | else if (sym_is(symname, "__mod_ieee1394_device_table")) | ||
| 1019 | do_table(symval, sym->st_size, | ||
| 1020 | sizeof(struct ieee1394_device_id), "ieee1394", | ||
| 1021 | do_ieee1394_entry, mod); | ||
| 1022 | else if (sym_is(symname, "__mod_ccw_device_table")) | ||
| 1023 | do_table(symval, sym->st_size, | ||
| 1024 | sizeof(struct ccw_device_id), "ccw", | ||
| 1025 | do_ccw_entry, mod); | ||
| 1026 | else if (sym_is(symname, "__mod_ap_device_table")) | ||
| 1027 | do_table(symval, sym->st_size, | ||
| 1028 | sizeof(struct ap_device_id), "ap", | ||
| 1029 | do_ap_entry, mod); | ||
| 1030 | else if (sym_is(symname, "__mod_css_device_table")) | ||
| 1031 | do_table(symval, sym->st_size, | ||
| 1032 | sizeof(struct css_device_id), "css", | ||
| 1033 | do_css_entry, mod); | ||
| 1034 | else if (sym_is(symname, "__mod_serio_device_table")) | ||
| 1035 | do_table(symval, sym->st_size, | ||
| 1036 | sizeof(struct serio_device_id), "serio", | ||
| 1037 | do_serio_entry, mod); | ||
| 1038 | else if (sym_is(symname, "__mod_acpi_device_table")) | ||
| 1039 | do_table(symval, sym->st_size, | ||
| 1040 | sizeof(struct acpi_device_id), "acpi", | ||
| 1041 | do_acpi_entry, mod); | ||
| 1042 | else if (sym_is(symname, "__mod_pnp_device_table")) | ||
| 1043 | do_pnp_device_entry(symval, sym->st_size, mod); | 1061 | do_pnp_device_entry(symval, sym->st_size, mod); |
| 1044 | else if (sym_is(symname, "__mod_pnp_card_device_table")) | 1062 | else if (sym_is(name, namelen, "pnp_card")) |
| 1045 | do_pnp_card_entries(symval, sym->st_size, mod); | 1063 | do_pnp_card_entries(symval, sym->st_size, mod); |
| 1046 | else if (sym_is(symname, "__mod_pcmcia_device_table")) | 1064 | else { |
| 1047 | do_table(symval, sym->st_size, | 1065 | const struct devtable_switch *p = devtable_switch; |
| 1048 | sizeof(struct pcmcia_device_id), "pcmcia", | 1066 | unsigned int i; |
| 1049 | do_pcmcia_entry, mod); | 1067 | |
| 1050 | else if (sym_is(symname, "__mod_of_device_table")) | 1068 | for (i = 0; i < ARRAY_SIZE(devtable_switch); i++, p++) { |
| 1051 | do_table(symval, sym->st_size, | 1069 | if (sym_is(name, namelen, p->device_id)) { |
| 1052 | sizeof(struct of_device_id), "of", | 1070 | do_table(symval, sym->st_size, p->id_size, |
| 1053 | do_of_entry, mod); | 1071 | p->device_id, p->function, mod); |
| 1054 | else if (sym_is(symname, "__mod_vio_device_table")) | 1072 | break; |
| 1055 | do_table(symval, sym->st_size, | 1073 | } |
| 1056 | sizeof(struct vio_device_id), "vio", | 1074 | } |
| 1057 | do_vio_entry, mod); | 1075 | } |
| 1058 | else if (sym_is(symname, "__mod_input_device_table")) | ||
| 1059 | do_table(symval, sym->st_size, | ||
| 1060 | sizeof(struct input_device_id), "input", | ||
| 1061 | do_input_entry, mod); | ||
| 1062 | else if (sym_is(symname, "__mod_eisa_device_table")) | ||
| 1063 | do_table(symval, sym->st_size, | ||
| 1064 | sizeof(struct eisa_device_id), "eisa", | ||
| 1065 | do_eisa_entry, mod); | ||
| 1066 | else if (sym_is(symname, "__mod_parisc_device_table")) | ||
| 1067 | do_table(symval, sym->st_size, | ||
| 1068 | sizeof(struct parisc_device_id), "parisc", | ||
| 1069 | do_parisc_entry, mod); | ||
| 1070 | else if (sym_is(symname, "__mod_sdio_device_table")) | ||
| 1071 | do_table(symval, sym->st_size, | ||
| 1072 | sizeof(struct sdio_device_id), "sdio", | ||
| 1073 | do_sdio_entry, mod); | ||
| 1074 | else if (sym_is(symname, "__mod_ssb_device_table")) | ||
| 1075 | do_table(symval, sym->st_size, | ||
| 1076 | sizeof(struct ssb_device_id), "ssb", | ||
| 1077 | do_ssb_entry, mod); | ||
| 1078 | else if (sym_is(symname, "__mod_bcma_device_table")) | ||
| 1079 | do_table(symval, sym->st_size, | ||
| 1080 | sizeof(struct bcma_device_id), "bcma", | ||
| 1081 | do_bcma_entry, mod); | ||
| 1082 | else if (sym_is(symname, "__mod_virtio_device_table")) | ||
| 1083 | do_table(symval, sym->st_size, | ||
| 1084 | sizeof(struct virtio_device_id), "virtio", | ||
| 1085 | do_virtio_entry, mod); | ||
| 1086 | else if (sym_is(symname, "__mod_vmbus_device_table")) | ||
| 1087 | do_table(symval, sym->st_size, | ||
| 1088 | sizeof(struct hv_vmbus_device_id), "vmbus", | ||
| 1089 | do_vmbus_entry, mod); | ||
| 1090 | else if (sym_is(symname, "__mod_i2c_device_table")) | ||
| 1091 | do_table(symval, sym->st_size, | ||
| 1092 | sizeof(struct i2c_device_id), "i2c", | ||
| 1093 | do_i2c_entry, mod); | ||
| 1094 | else if (sym_is(symname, "__mod_spi_device_table")) | ||
| 1095 | do_table(symval, sym->st_size, | ||
| 1096 | sizeof(struct spi_device_id), "spi", | ||
| 1097 | do_spi_entry, mod); | ||
| 1098 | else if (sym_is(symname, "__mod_dmi_device_table")) | ||
| 1099 | do_table(symval, sym->st_size, | ||
| 1100 | sizeof(struct dmi_system_id), "dmi", | ||
| 1101 | do_dmi_entry, mod); | ||
| 1102 | else if (sym_is(symname, "__mod_platform_device_table")) | ||
| 1103 | do_table(symval, sym->st_size, | ||
| 1104 | sizeof(struct platform_device_id), "platform", | ||
| 1105 | do_platform_entry, mod); | ||
| 1106 | else if (sym_is(symname, "__mod_mdio_device_table")) | ||
| 1107 | do_table(symval, sym->st_size, | ||
| 1108 | sizeof(struct mdio_device_id), "mdio", | ||
| 1109 | do_mdio_entry, mod); | ||
| 1110 | else if (sym_is(symname, "__mod_zorro_device_table")) | ||
| 1111 | do_table(symval, sym->st_size, | ||
| 1112 | sizeof(struct zorro_device_id), "zorro", | ||
| 1113 | do_zorro_entry, mod); | ||
| 1114 | else if (sym_is(symname, "__mod_isapnp_device_table")) | ||
| 1115 | do_table(symval, sym->st_size, | ||
| 1116 | sizeof(struct isapnp_device_id), "isa", | ||
| 1117 | do_isapnp_entry, mod); | ||
| 1118 | else if (sym_is(symname, "__mod_amba_device_table")) | ||
| 1119 | do_table(symval, sym->st_size, | ||
| 1120 | sizeof(struct amba_id), "amba", | ||
| 1121 | do_amba_entry, mod); | ||
| 1122 | free(zeros); | 1076 | free(zeros); |
| 1123 | } | 1077 | } |
| 1124 | 1078 | ||
