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 | ||