diff options
Diffstat (limited to 'drivers/base')
-rw-r--r-- | drivers/base/base.h | 2 | ||||
-rw-r--r-- | drivers/base/core.c | 6 | ||||
-rw-r--r-- | drivers/base/dd.c | 1 | ||||
-rw-r--r-- | drivers/base/iommu.c | 2 | ||||
-rw-r--r-- | drivers/base/platform.c | 255 |
5 files changed, 248 insertions, 18 deletions
diff --git a/drivers/base/base.h b/drivers/base/base.h index ddc97496db4a..b528145a078f 100644 --- a/drivers/base/base.h +++ b/drivers/base/base.h | |||
@@ -115,7 +115,7 @@ extern int driver_probe_device(struct device_driver *drv, struct device *dev); | |||
115 | static inline int driver_match_device(struct device_driver *drv, | 115 | static inline int driver_match_device(struct device_driver *drv, |
116 | struct device *dev) | 116 | struct device *dev) |
117 | { | 117 | { |
118 | return drv->bus->match && drv->bus->match(dev, drv); | 118 | return drv->bus->match ? drv->bus->match(dev, drv) : 1; |
119 | } | 119 | } |
120 | 120 | ||
121 | extern void sysdev_shutdown(void); | 121 | extern void sysdev_shutdown(void); |
diff --git a/drivers/base/core.c b/drivers/base/core.c index e73c92d13a23..4aa527b8a913 100644 --- a/drivers/base/core.c +++ b/drivers/base/core.c | |||
@@ -891,7 +891,8 @@ int device_add(struct device *dev) | |||
891 | set_dev_node(dev, dev_to_node(parent)); | 891 | set_dev_node(dev, dev_to_node(parent)); |
892 | 892 | ||
893 | /* first, register with generic layer. */ | 893 | /* first, register with generic layer. */ |
894 | error = kobject_add(&dev->kobj, dev->kobj.parent, "%s", dev_name(dev)); | 894 | /* we require the name to be set before, and pass NULL */ |
895 | error = kobject_add(&dev->kobj, dev->kobj.parent, NULL); | ||
895 | if (error) | 896 | if (error) |
896 | goto Error; | 897 | goto Error; |
897 | 898 | ||
@@ -1142,6 +1143,9 @@ int device_for_each_child(struct device *parent, void *data, | |||
1142 | struct device *child; | 1143 | struct device *child; |
1143 | int error = 0; | 1144 | int error = 0; |
1144 | 1145 | ||
1146 | if (!parent->p) | ||
1147 | return 0; | ||
1148 | |||
1145 | klist_iter_init(&parent->p->klist_children, &i); | 1149 | klist_iter_init(&parent->p->klist_children, &i); |
1146 | while ((child = next_device(&i)) && !error) | 1150 | while ((child = next_device(&i)) && !error) |
1147 | error = fn(child, data); | 1151 | error = fn(child, data); |
diff --git a/drivers/base/dd.c b/drivers/base/dd.c index f17c3266a0e0..742cbe6b042b 100644 --- a/drivers/base/dd.c +++ b/drivers/base/dd.c | |||
@@ -179,6 +179,7 @@ void wait_for_device_probe(void) | |||
179 | wait_event(probe_waitqueue, atomic_read(&probe_count) == 0); | 179 | wait_event(probe_waitqueue, atomic_read(&probe_count) == 0); |
180 | async_synchronize_full(); | 180 | async_synchronize_full(); |
181 | } | 181 | } |
182 | EXPORT_SYMBOL_GPL(wait_for_device_probe); | ||
182 | 183 | ||
183 | /** | 184 | /** |
184 | * driver_probe_device - attempt to bind device & driver together | 185 | * driver_probe_device - attempt to bind device & driver together |
diff --git a/drivers/base/iommu.c b/drivers/base/iommu.c index 9f0e672f4be8..8ad4ffea6920 100644 --- a/drivers/base/iommu.c +++ b/drivers/base/iommu.c | |||
@@ -18,6 +18,8 @@ | |||
18 | 18 | ||
19 | #include <linux/bug.h> | 19 | #include <linux/bug.h> |
20 | #include <linux/types.h> | 20 | #include <linux/types.h> |
21 | #include <linux/module.h> | ||
22 | #include <linux/slab.h> | ||
21 | #include <linux/errno.h> | 23 | #include <linux/errno.h> |
22 | #include <linux/iommu.h> | 24 | #include <linux/iommu.h> |
23 | 25 | ||
diff --git a/drivers/base/platform.c b/drivers/base/platform.c index d2198f64ad4e..8b4708e06244 100644 --- a/drivers/base/platform.c +++ b/drivers/base/platform.c | |||
@@ -217,7 +217,6 @@ int platform_device_add_data(struct platform_device *pdev, const void *data, | |||
217 | if (d) { | 217 | if (d) { |
218 | memcpy(d, data, size); | 218 | memcpy(d, data, size); |
219 | pdev->dev.platform_data = d; | 219 | pdev->dev.platform_data = d; |
220 | pdev->platform_data = d; | ||
221 | } | 220 | } |
222 | return d ? 0 : -ENOMEM; | 221 | return d ? 0 : -ENOMEM; |
223 | } | 222 | } |
@@ -247,21 +246,6 @@ int platform_device_add(struct platform_device *pdev) | |||
247 | else | 246 | else |
248 | dev_set_name(&pdev->dev, pdev->name); | 247 | dev_set_name(&pdev->dev, pdev->name); |
249 | 248 | ||
250 | /* We will remove platform_data field from struct device | ||
251 | * if all platform devices pass its platform specific data | ||
252 | * from platform_device. The conversion is going to be a | ||
253 | * long time, so we allow the two cases coexist to make | ||
254 | * this kind of fix more easily*/ | ||
255 | if (pdev->platform_data && pdev->dev.platform_data) { | ||
256 | printk(KERN_ERR | ||
257 | "%s: use which platform_data?\n", | ||
258 | dev_name(&pdev->dev)); | ||
259 | } else if (pdev->platform_data) { | ||
260 | pdev->dev.platform_data = pdev->platform_data; | ||
261 | } else if (pdev->dev.platform_data) { | ||
262 | pdev->platform_data = pdev->dev.platform_data; | ||
263 | } | ||
264 | |||
265 | for (i = 0; i < pdev->num_resources; i++) { | 249 | for (i = 0; i < pdev->num_resources; i++) { |
266 | struct resource *p, *r = &pdev->resource[i]; | 250 | struct resource *p, *r = &pdev->resource[i]; |
267 | 251 | ||
@@ -990,6 +974,8 @@ int __init platform_bus_init(void) | |||
990 | { | 974 | { |
991 | int error; | 975 | int error; |
992 | 976 | ||
977 | early_platform_cleanup(); | ||
978 | |||
993 | error = device_register(&platform_bus); | 979 | error = device_register(&platform_bus); |
994 | if (error) | 980 | if (error) |
995 | return error; | 981 | return error; |
@@ -1020,3 +1006,240 @@ u64 dma_get_required_mask(struct device *dev) | |||
1020 | } | 1006 | } |
1021 | EXPORT_SYMBOL_GPL(dma_get_required_mask); | 1007 | EXPORT_SYMBOL_GPL(dma_get_required_mask); |
1022 | #endif | 1008 | #endif |
1009 | |||
1010 | static __initdata LIST_HEAD(early_platform_driver_list); | ||
1011 | static __initdata LIST_HEAD(early_platform_device_list); | ||
1012 | |||
1013 | /** | ||
1014 | * early_platform_driver_register | ||
1015 | * @epdrv: early_platform driver structure | ||
1016 | * @buf: string passed from early_param() | ||
1017 | */ | ||
1018 | int __init early_platform_driver_register(struct early_platform_driver *epdrv, | ||
1019 | char *buf) | ||
1020 | { | ||
1021 | unsigned long index; | ||
1022 | int n; | ||
1023 | |||
1024 | /* Simply add the driver to the end of the global list. | ||
1025 | * Drivers will by default be put on the list in compiled-in order. | ||
1026 | */ | ||
1027 | if (!epdrv->list.next) { | ||
1028 | INIT_LIST_HEAD(&epdrv->list); | ||
1029 | list_add_tail(&epdrv->list, &early_platform_driver_list); | ||
1030 | } | ||
1031 | |||
1032 | /* If the user has specified device then make sure the driver | ||
1033 | * gets prioritized. The driver of the last device specified on | ||
1034 | * command line will be put first on the list. | ||
1035 | */ | ||
1036 | n = strlen(epdrv->pdrv->driver.name); | ||
1037 | if (buf && !strncmp(buf, epdrv->pdrv->driver.name, n)) { | ||
1038 | list_move(&epdrv->list, &early_platform_driver_list); | ||
1039 | |||
1040 | if (!strcmp(buf, epdrv->pdrv->driver.name)) | ||
1041 | epdrv->requested_id = -1; | ||
1042 | else if (buf[n] == '.' && strict_strtoul(&buf[n + 1], 10, | ||
1043 | &index) == 0) | ||
1044 | epdrv->requested_id = index; | ||
1045 | else | ||
1046 | epdrv->requested_id = EARLY_PLATFORM_ID_ERROR; | ||
1047 | } | ||
1048 | |||
1049 | return 0; | ||
1050 | } | ||
1051 | |||
1052 | /** | ||
1053 | * early_platform_add_devices - add a numbers of early platform devices | ||
1054 | * @devs: array of early platform devices to add | ||
1055 | * @num: number of early platform devices in array | ||
1056 | */ | ||
1057 | void __init early_platform_add_devices(struct platform_device **devs, int num) | ||
1058 | { | ||
1059 | struct device *dev; | ||
1060 | int i; | ||
1061 | |||
1062 | /* simply add the devices to list */ | ||
1063 | for (i = 0; i < num; i++) { | ||
1064 | dev = &devs[i]->dev; | ||
1065 | |||
1066 | if (!dev->devres_head.next) { | ||
1067 | INIT_LIST_HEAD(&dev->devres_head); | ||
1068 | list_add_tail(&dev->devres_head, | ||
1069 | &early_platform_device_list); | ||
1070 | } | ||
1071 | } | ||
1072 | } | ||
1073 | |||
1074 | /** | ||
1075 | * early_platform_driver_register_all | ||
1076 | * @class_str: string to identify early platform driver class | ||
1077 | */ | ||
1078 | void __init early_platform_driver_register_all(char *class_str) | ||
1079 | { | ||
1080 | /* The "class_str" parameter may or may not be present on the kernel | ||
1081 | * command line. If it is present then there may be more than one | ||
1082 | * matching parameter. | ||
1083 | * | ||
1084 | * Since we register our early platform drivers using early_param() | ||
1085 | * we need to make sure that they also get registered in the case | ||
1086 | * when the parameter is missing from the kernel command line. | ||
1087 | * | ||
1088 | * We use parse_early_options() to make sure the early_param() gets | ||
1089 | * called at least once. The early_param() may be called more than | ||
1090 | * once since the name of the preferred device may be specified on | ||
1091 | * the kernel command line. early_platform_driver_register() handles | ||
1092 | * this case for us. | ||
1093 | */ | ||
1094 | parse_early_options(class_str); | ||
1095 | } | ||
1096 | |||
1097 | /** | ||
1098 | * early_platform_match | ||
1099 | * @epdrv: early platform driver structure | ||
1100 | * @id: id to match against | ||
1101 | */ | ||
1102 | static __init struct platform_device * | ||
1103 | early_platform_match(struct early_platform_driver *epdrv, int id) | ||
1104 | { | ||
1105 | struct platform_device *pd; | ||
1106 | |||
1107 | list_for_each_entry(pd, &early_platform_device_list, dev.devres_head) | ||
1108 | if (platform_match(&pd->dev, &epdrv->pdrv->driver)) | ||
1109 | if (pd->id == id) | ||
1110 | return pd; | ||
1111 | |||
1112 | return NULL; | ||
1113 | } | ||
1114 | |||
1115 | /** | ||
1116 | * early_platform_left | ||
1117 | * @epdrv: early platform driver structure | ||
1118 | * @id: return true if id or above exists | ||
1119 | */ | ||
1120 | static __init int early_platform_left(struct early_platform_driver *epdrv, | ||
1121 | int id) | ||
1122 | { | ||
1123 | struct platform_device *pd; | ||
1124 | |||
1125 | list_for_each_entry(pd, &early_platform_device_list, dev.devres_head) | ||
1126 | if (platform_match(&pd->dev, &epdrv->pdrv->driver)) | ||
1127 | if (pd->id >= id) | ||
1128 | return 1; | ||
1129 | |||
1130 | return 0; | ||
1131 | } | ||
1132 | |||
1133 | /** | ||
1134 | * early_platform_driver_probe_id | ||
1135 | * @class_str: string to identify early platform driver class | ||
1136 | * @id: id to match against | ||
1137 | * @nr_probe: number of platform devices to successfully probe before exiting | ||
1138 | */ | ||
1139 | static int __init early_platform_driver_probe_id(char *class_str, | ||
1140 | int id, | ||
1141 | int nr_probe) | ||
1142 | { | ||
1143 | struct early_platform_driver *epdrv; | ||
1144 | struct platform_device *match; | ||
1145 | int match_id; | ||
1146 | int n = 0; | ||
1147 | int left = 0; | ||
1148 | |||
1149 | list_for_each_entry(epdrv, &early_platform_driver_list, list) { | ||
1150 | /* only use drivers matching our class_str */ | ||
1151 | if (strcmp(class_str, epdrv->class_str)) | ||
1152 | continue; | ||
1153 | |||
1154 | if (id == -2) { | ||
1155 | match_id = epdrv->requested_id; | ||
1156 | left = 1; | ||
1157 | |||
1158 | } else { | ||
1159 | match_id = id; | ||
1160 | left += early_platform_left(epdrv, id); | ||
1161 | |||
1162 | /* skip requested id */ | ||
1163 | switch (epdrv->requested_id) { | ||
1164 | case EARLY_PLATFORM_ID_ERROR: | ||
1165 | case EARLY_PLATFORM_ID_UNSET: | ||
1166 | break; | ||
1167 | default: | ||
1168 | if (epdrv->requested_id == id) | ||
1169 | match_id = EARLY_PLATFORM_ID_UNSET; | ||
1170 | } | ||
1171 | } | ||
1172 | |||
1173 | switch (match_id) { | ||
1174 | case EARLY_PLATFORM_ID_ERROR: | ||
1175 | pr_warning("%s: unable to parse %s parameter\n", | ||
1176 | class_str, epdrv->pdrv->driver.name); | ||
1177 | /* fall-through */ | ||
1178 | case EARLY_PLATFORM_ID_UNSET: | ||
1179 | match = NULL; | ||
1180 | break; | ||
1181 | default: | ||
1182 | match = early_platform_match(epdrv, match_id); | ||
1183 | } | ||
1184 | |||
1185 | if (match) { | ||
1186 | if (epdrv->pdrv->probe(match)) | ||
1187 | pr_warning("%s: unable to probe %s early.\n", | ||
1188 | class_str, match->name); | ||
1189 | else | ||
1190 | n++; | ||
1191 | } | ||
1192 | |||
1193 | if (n >= nr_probe) | ||
1194 | break; | ||
1195 | } | ||
1196 | |||
1197 | if (left) | ||
1198 | return n; | ||
1199 | else | ||
1200 | return -ENODEV; | ||
1201 | } | ||
1202 | |||
1203 | /** | ||
1204 | * early_platform_driver_probe | ||
1205 | * @class_str: string to identify early platform driver class | ||
1206 | * @nr_probe: number of platform devices to successfully probe before exiting | ||
1207 | * @user_only: only probe user specified early platform devices | ||
1208 | */ | ||
1209 | int __init early_platform_driver_probe(char *class_str, | ||
1210 | int nr_probe, | ||
1211 | int user_only) | ||
1212 | { | ||
1213 | int k, n, i; | ||
1214 | |||
1215 | n = 0; | ||
1216 | for (i = -2; n < nr_probe; i++) { | ||
1217 | k = early_platform_driver_probe_id(class_str, i, nr_probe - n); | ||
1218 | |||
1219 | if (k < 0) | ||
1220 | break; | ||
1221 | |||
1222 | n += k; | ||
1223 | |||
1224 | if (user_only) | ||
1225 | break; | ||
1226 | } | ||
1227 | |||
1228 | return n; | ||
1229 | } | ||
1230 | |||
1231 | /** | ||
1232 | * early_platform_cleanup - clean up early platform code | ||
1233 | */ | ||
1234 | void __init early_platform_cleanup(void) | ||
1235 | { | ||
1236 | struct platform_device *pd, *pd2; | ||
1237 | |||
1238 | /* clean up the devres list used to chain devices */ | ||
1239 | list_for_each_entry_safe(pd, pd2, &early_platform_device_list, | ||
1240 | dev.devres_head) { | ||
1241 | list_del(&pd->dev.devres_head); | ||
1242 | memset(&pd->dev.devres_head, 0, sizeof(pd->dev.devres_head)); | ||
1243 | } | ||
1244 | } | ||
1245 | |||