diff options
| -rw-r--r-- | Documentation/driver-model/platform.txt | 59 | ||||
| -rw-r--r-- | drivers/base/base.h | 2 | ||||
| -rw-r--r-- | drivers/base/core.c | 3 | ||||
| -rw-r--r-- | drivers/base/platform.c | 239 | ||||
| -rw-r--r-- | drivers/uio/uio_cif.c | 1 | ||||
| -rw-r--r-- | fs/proc/base.c | 4 | ||||
| -rw-r--r-- | fs/sysfs/file.c | 16 | ||||
| -rw-r--r-- | include/linux/dynamic_debug.h | 2 | ||||
| -rw-r--r-- | include/linux/init.h | 1 | ||||
| -rw-r--r-- | include/linux/kernel.h | 9 | ||||
| -rw-r--r-- | include/linux/platform_device.h | 42 | ||||
| -rw-r--r-- | init/main.c | 7 | ||||
| -rw-r--r-- | lib/kobject_uevent.c | 2 |
13 files changed, 378 insertions, 9 deletions
diff --git a/Documentation/driver-model/platform.txt b/Documentation/driver-model/platform.txt index 83009fdcbbc..2e2c2ea90ce 100644 --- a/Documentation/driver-model/platform.txt +++ b/Documentation/driver-model/platform.txt | |||
| @@ -169,3 +169,62 @@ three different ways to find such a match: | |||
| 169 | be probed later if another device registers. (Which is OK, since | 169 | be probed later if another device registers. (Which is OK, since |
| 170 | this interface is only for use with non-hotpluggable devices.) | 170 | this interface is only for use with non-hotpluggable devices.) |
| 171 | 171 | ||
| 172 | |||
| 173 | Early Platform Devices and Drivers | ||
| 174 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||
| 175 | The early platform interfaces provide platform data to platform device | ||
| 176 | drivers early on during the system boot. The code is built on top of the | ||
| 177 | early_param() command line parsing and can be executed very early on. | ||
| 178 | |||
| 179 | Example: "earlyprintk" class early serial console in 6 steps | ||
| 180 | |||
| 181 | 1. Registering early platform device data | ||
| 182 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||
| 183 | The architecture code registers platform device data using the function | ||
| 184 | early_platform_add_devices(). In the case of early serial console this | ||
| 185 | should be hardware configuration for the serial port. Devices registered | ||
| 186 | at this point will later on be matched against early platform drivers. | ||
| 187 | |||
| 188 | 2. Parsing kernel command line | ||
| 189 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||
| 190 | The architecture code calls parse_early_param() to parse the kernel | ||
| 191 | command line. This will execute all matching early_param() callbacks. | ||
| 192 | User specified early platform devices will be registered at this point. | ||
| 193 | For the early serial console case the user can specify port on the | ||
| 194 | kernel command line as "earlyprintk=serial.0" where "earlyprintk" is | ||
| 195 | the class string, "serial" is the name of the platfrom driver and | ||
| 196 | 0 is the platform device id. If the id is -1 then the dot and the | ||
| 197 | id can be omitted. | ||
| 198 | |||
| 199 | 3. Installing early platform drivers belonging to a certain class | ||
| 200 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||
| 201 | The architecture code may optionally force registration of all early | ||
| 202 | platform drivers belonging to a certain class using the function | ||
| 203 | early_platform_driver_register_all(). User specified devices from | ||
| 204 | step 2 have priority over these. This step is omitted by the serial | ||
| 205 | driver example since the early serial driver code should be disabled | ||
| 206 | unless the user has specified port on the kernel command line. | ||
| 207 | |||
| 208 | 4. Early platform driver registration | ||
| 209 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||
| 210 | Compiled-in platform drivers making use of early_platform_init() are | ||
| 211 | automatically registered during step 2 or 3. The serial driver example | ||
| 212 | should use early_platform_init("earlyprintk", &platform_driver). | ||
| 213 | |||
| 214 | 5. Probing of early platform drivers belonging to a certain class | ||
| 215 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||
| 216 | The architecture code calls early_platform_driver_probe() to match | ||
| 217 | registered early platform devices associated with a certain class with | ||
| 218 | registered early platform drivers. Matched devices will get probed(). | ||
| 219 | This step can be executed at any point during the early boot. As soon | ||
| 220 | as possible may be good for the serial port case. | ||
| 221 | |||
| 222 | 6. Inside the early platform driver probe() | ||
| 223 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||
| 224 | The driver code needs to take special care during early boot, especially | ||
| 225 | when it comes to memory allocation and interrupt registration. The code | ||
| 226 | in the probe() function can use is_early_platform_device() to check if | ||
| 227 | it is called at early platform device or at the regular platform device | ||
| 228 | time. The early serial driver performs register_console() at this point. | ||
| 229 | |||
| 230 | For further information, see <linux/platform_device.h>. | ||
diff --git a/drivers/base/base.h b/drivers/base/base.h index ddc97496db4..b528145a078 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 e73c92d13a2..d230ff4b3ee 100644 --- a/drivers/base/core.c +++ b/drivers/base/core.c | |||
| @@ -1142,6 +1142,9 @@ int device_for_each_child(struct device *parent, void *data, | |||
| 1142 | struct device *child; | 1142 | struct device *child; |
| 1143 | int error = 0; | 1143 | int error = 0; |
| 1144 | 1144 | ||
| 1145 | if (!parent->p) | ||
| 1146 | return 0; | ||
| 1147 | |||
| 1145 | klist_iter_init(&parent->p->klist_children, &i); | 1148 | klist_iter_init(&parent->p->klist_children, &i); |
| 1146 | while ((child = next_device(&i)) && !error) | 1149 | while ((child = next_device(&i)) && !error) |
| 1147 | error = fn(child, data); | 1150 | error = fn(child, data); |
diff --git a/drivers/base/platform.c b/drivers/base/platform.c index d2198f64ad4..b5b6c973a2e 100644 --- a/drivers/base/platform.c +++ b/drivers/base/platform.c | |||
| @@ -990,6 +990,8 @@ int __init platform_bus_init(void) | |||
| 990 | { | 990 | { |
| 991 | int error; | 991 | int error; |
| 992 | 992 | ||
| 993 | early_platform_cleanup(); | ||
| 994 | |||
| 993 | error = device_register(&platform_bus); | 995 | error = device_register(&platform_bus); |
| 994 | if (error) | 996 | if (error) |
| 995 | return error; | 997 | return error; |
| @@ -1020,3 +1022,240 @@ u64 dma_get_required_mask(struct device *dev) | |||
| 1020 | } | 1022 | } |
| 1021 | EXPORT_SYMBOL_GPL(dma_get_required_mask); | 1023 | EXPORT_SYMBOL_GPL(dma_get_required_mask); |
| 1022 | #endif | 1024 | #endif |
| 1025 | |||
| 1026 | static __initdata LIST_HEAD(early_platform_driver_list); | ||
| 1027 | static __initdata LIST_HEAD(early_platform_device_list); | ||
| 1028 | |||
| 1029 | /** | ||
| 1030 | * early_platform_driver_register | ||
| 1031 | * @edrv: early_platform driver structure | ||
| 1032 | * @buf: string passed from early_param() | ||
| 1033 | */ | ||
| 1034 | int __init early_platform_driver_register(struct early_platform_driver *epdrv, | ||
| 1035 | char *buf) | ||
| 1036 | { | ||
| 1037 | unsigned long index; | ||
| 1038 | int n; | ||
| 1039 | |||
| 1040 | /* Simply add the driver to the end of the global list. | ||
| 1041 | * Drivers will by default be put on the list in compiled-in order. | ||
| 1042 | */ | ||
| 1043 | if (!epdrv->list.next) { | ||
| 1044 | INIT_LIST_HEAD(&epdrv->list); | ||
| 1045 | list_add_tail(&epdrv->list, &early_platform_driver_list); | ||
| 1046 | } | ||
| 1047 | |||
| 1048 | /* If the user has specified device then make sure the driver | ||
| 1049 | * gets prioritized. The driver of the last device specified on | ||
| 1050 | * command line will be put first on the list. | ||
| 1051 | */ | ||
| 1052 | n = strlen(epdrv->pdrv->driver.name); | ||
| 1053 | if (buf && !strncmp(buf, epdrv->pdrv->driver.name, n)) { | ||
| 1054 | list_move(&epdrv->list, &early_platform_driver_list); | ||
| 1055 | |||
| 1056 | if (!strcmp(buf, epdrv->pdrv->driver.name)) | ||
| 1057 | epdrv->requested_id = -1; | ||
| 1058 | else if (buf[n] == '.' && strict_strtoul(&buf[n + 1], 10, | ||
| 1059 | &index) == 0) | ||
| 1060 | epdrv->requested_id = index; | ||
| 1061 | else | ||
| 1062 | epdrv->requested_id = EARLY_PLATFORM_ID_ERROR; | ||
| 1063 | } | ||
| 1064 | |||
| 1065 | return 0; | ||
| 1066 | } | ||
| 1067 | |||
| 1068 | /** | ||
| 1069 | * early_platform_add_devices - add a numbers of early platform devices | ||
| 1070 | * @devs: array of early platform devices to add | ||
| 1071 | * @num: number of early platform devices in array | ||
| 1072 | */ | ||
| 1073 | void __init early_platform_add_devices(struct platform_device **devs, int num) | ||
| 1074 | { | ||
| 1075 | struct device *dev; | ||
| 1076 | int i; | ||
| 1077 | |||
| 1078 | /* simply add the devices to list */ | ||
| 1079 | for (i = 0; i < num; i++) { | ||
| 1080 | dev = &devs[i]->dev; | ||
| 1081 | |||
| 1082 | if (!dev->devres_head.next) { | ||
| 1083 | INIT_LIST_HEAD(&dev->devres_head); | ||
| 1084 | list_add_tail(&dev->devres_head, | ||
| 1085 | &early_platform_device_list); | ||
| 1086 | } | ||
| 1087 | } | ||
| 1088 | } | ||
| 1089 | |||
| 1090 | /** | ||
| 1091 | * early_platform_driver_register_all | ||
| 1092 | * @class_str: string to identify early platform driver class | ||
| 1093 | */ | ||
| 1094 | void __init early_platform_driver_register_all(char *class_str) | ||
| 1095 | { | ||
| 1096 | /* The "class_str" parameter may or may not be present on the kernel | ||
| 1097 | * command line. If it is present then there may be more than one | ||
| 1098 | * matching parameter. | ||
| 1099 | * | ||
| 1100 | * Since we register our early platform drivers using early_param() | ||
| 1101 | * we need to make sure that they also get registered in the case | ||
| 1102 | * when the parameter is missing from the kernel command line. | ||
| 1103 | * | ||
| 1104 | * We use parse_early_options() to make sure the early_param() gets | ||
| 1105 | * called at least once. The early_param() may be called more than | ||
| 1106 | * once since the name of the preferred device may be specified on | ||
| 1107 | * the kernel command line. early_platform_driver_register() handles | ||
| 1108 | * this case for us. | ||
| 1109 | */ | ||
| 1110 | parse_early_options(class_str); | ||
| 1111 | } | ||
| 1112 | |||
| 1113 | /** | ||
| 1114 | * early_platform_match | ||
| 1115 | * @edrv: early platform driver structure | ||
| 1116 | * @id: id to match against | ||
| 1117 | */ | ||
| 1118 | static __init struct platform_device * | ||
| 1119 | early_platform_match(struct early_platform_driver *epdrv, int id) | ||
| 1120 | { | ||
| 1121 | struct platform_device *pd; | ||
| 1122 | |||
| 1123 | list_for_each_entry(pd, &early_platform_device_list, dev.devres_head) | ||
| 1124 | if (platform_match(&pd->dev, &epdrv->pdrv->driver)) | ||
| 1125 | if (pd->id == id) | ||
| 1126 | return pd; | ||
| 1127 | |||
| 1128 | return NULL; | ||
| 1129 | } | ||
| 1130 | |||
| 1131 | /** | ||
| 1132 | * early_platform_left | ||
| 1133 | * @edrv: early platform driver structure | ||
| 1134 | * @id: return true if id or above exists | ||
| 1135 | */ | ||
| 1136 | static __init int early_platform_left(struct early_platform_driver *epdrv, | ||
| 1137 | int id) | ||
| 1138 | { | ||
| 1139 | struct platform_device *pd; | ||
| 1140 | |||
| 1141 | list_for_each_entry(pd, &early_platform_device_list, dev.devres_head) | ||
| 1142 | if (platform_match(&pd->dev, &epdrv->pdrv->driver)) | ||
| 1143 | if (pd->id >= id) | ||
| 1144 | return 1; | ||
| 1145 | |||
| 1146 | return 0; | ||
| 1147 | } | ||
| 1148 | |||
| 1149 | /** | ||
| 1150 | * early_platform_driver_probe_id | ||
| 1151 | * @class_str: string to identify early platform driver class | ||
| 1152 | * @id: id to match against | ||
| 1153 | * @nr_probe: number of platform devices to successfully probe before exiting | ||
| 1154 | */ | ||
| 1155 | static int __init early_platform_driver_probe_id(char *class_str, | ||
| 1156 | int id, | ||
| 1157 | int nr_probe) | ||
| 1158 | { | ||
| 1159 | struct early_platform_driver *epdrv; | ||
| 1160 | struct platform_device *match; | ||
| 1161 | int match_id; | ||
| 1162 | int n = 0; | ||
| 1163 | int left = 0; | ||
| 1164 | |||
| 1165 | list_for_each_entry(epdrv, &early_platform_driver_list, list) { | ||
| 1166 | /* only use drivers matching our class_str */ | ||
| 1167 | if (strcmp(class_str, epdrv->class_str)) | ||
| 1168 | continue; | ||
| 1169 | |||
| 1170 | if (id == -2) { | ||
| 1171 | match_id = epdrv->requested_id; | ||
| 1172 | left = 1; | ||
| 1173 | |||
| 1174 | } else { | ||
| 1175 | match_id = id; | ||
| 1176 | left += early_platform_left(epdrv, id); | ||
| 1177 | |||
| 1178 | /* skip requested id */ | ||
| 1179 | switch (epdrv->requested_id) { | ||
| 1180 | case EARLY_PLATFORM_ID_ERROR: | ||
| 1181 | case EARLY_PLATFORM_ID_UNSET: | ||
| 1182 | break; | ||
| 1183 | default: | ||
| 1184 | if (epdrv->requested_id == id) | ||
| 1185 | match_id = EARLY_PLATFORM_ID_UNSET; | ||
| 1186 | } | ||
| 1187 | } | ||
| 1188 | |||
| 1189 | switch (match_id) { | ||
| 1190 | case EARLY_PLATFORM_ID_ERROR: | ||
| 1191 | pr_warning("%s: unable to parse %s parameter\n", | ||
| 1192 | class_str, epdrv->pdrv->driver.name); | ||
| 1193 | /* fall-through */ | ||
| 1194 | case EARLY_PLATFORM_ID_UNSET: | ||
| 1195 | match = NULL; | ||
| 1196 | break; | ||
| 1197 | default: | ||
| 1198 | match = early_platform_match(epdrv, match_id); | ||
| 1199 | } | ||
| 1200 | |||
| 1201 | if (match) { | ||
| 1202 | if (epdrv->pdrv->probe(match)) | ||
| 1203 | pr_warning("%s: unable to probe %s early.\n", | ||
| 1204 | class_str, match->name); | ||
| 1205 | else | ||
| 1206 | n++; | ||
| 1207 | } | ||
| 1208 | |||
| 1209 | if (n >= nr_probe) | ||
| 1210 | break; | ||
| 1211 | } | ||
| 1212 | |||
| 1213 | if (left) | ||
| 1214 | return n; | ||
| 1215 | else | ||
| 1216 | return -ENODEV; | ||
| 1217 | } | ||
| 1218 | |||
| 1219 | /** | ||
| 1220 | * early_platform_driver_probe | ||
| 1221 | * @class_str: string to identify early platform driver class | ||
| 1222 | * @nr_probe: number of platform devices to successfully probe before exiting | ||
| 1223 | * @user_only: only probe user specified early platform devices | ||
| 1224 | */ | ||
| 1225 | int __init early_platform_driver_probe(char *class_str, | ||
| 1226 | int nr_probe, | ||
| 1227 | int user_only) | ||
| 1228 | { | ||
| 1229 | int k, n, i; | ||
| 1230 | |||
| 1231 | n = 0; | ||
| 1232 | for (i = -2; n < nr_probe; i++) { | ||
| 1233 | k = early_platform_driver_probe_id(class_str, i, nr_probe - n); | ||
| 1234 | |||
| 1235 | if (k < 0) | ||
| 1236 | break; | ||
| 1237 | |||
| 1238 | n += k; | ||
| 1239 | |||
| 1240 | if (user_only) | ||
| 1241 | break; | ||
| 1242 | } | ||
| 1243 | |||
| 1244 | return n; | ||
| 1245 | } | ||
| 1246 | |||
| 1247 | /** | ||
| 1248 | * early_platform_cleanup - clean up early platform code | ||
| 1249 | */ | ||
| 1250 | void __init early_platform_cleanup(void) | ||
| 1251 | { | ||
| 1252 | struct platform_device *pd, *pd2; | ||
| 1253 | |||
| 1254 | /* clean up the devres list used to chain devices */ | ||
| 1255 | list_for_each_entry_safe(pd, pd2, &early_platform_device_list, | ||
| 1256 | dev.devres_head) { | ||
| 1257 | list_del(&pd->dev.devres_head); | ||
| 1258 | memset(&pd->dev.devres_head, 0, sizeof(pd->dev.devres_head)); | ||
| 1259 | } | ||
| 1260 | } | ||
| 1261 | |||
diff --git a/drivers/uio/uio_cif.c b/drivers/uio/uio_cif.c index c60b8fcf0e3..28034c81291 100644 --- a/drivers/uio/uio_cif.c +++ b/drivers/uio/uio_cif.c | |||
| @@ -147,5 +147,6 @@ static void __exit hilscher_exit_module(void) | |||
| 147 | module_init(hilscher_init_module); | 147 | module_init(hilscher_init_module); |
| 148 | module_exit(hilscher_exit_module); | 148 | module_exit(hilscher_exit_module); |
| 149 | 149 | ||
| 150 | MODULE_DEVICE_TABLE(pci, hilscher_pci_ids); | ||
| 150 | MODULE_LICENSE("GPL v2"); | 151 | MODULE_LICENSE("GPL v2"); |
| 151 | MODULE_AUTHOR("Hans J. Koch, Benedikt Spranger"); | 152 | MODULE_AUTHOR("Hans J. Koch, Benedikt Spranger"); |
diff --git a/fs/proc/base.c b/fs/proc/base.c index f71559784bf..aa763ab0077 100644 --- a/fs/proc/base.c +++ b/fs/proc/base.c | |||
| @@ -648,14 +648,14 @@ static unsigned mounts_poll(struct file *file, poll_table *wait) | |||
| 648 | { | 648 | { |
| 649 | struct proc_mounts *p = file->private_data; | 649 | struct proc_mounts *p = file->private_data; |
| 650 | struct mnt_namespace *ns = p->ns; | 650 | struct mnt_namespace *ns = p->ns; |
| 651 | unsigned res = 0; | 651 | unsigned res = POLLIN | POLLRDNORM; |
| 652 | 652 | ||
| 653 | poll_wait(file, &ns->poll, wait); | 653 | poll_wait(file, &ns->poll, wait); |
| 654 | 654 | ||
| 655 | spin_lock(&vfsmount_lock); | 655 | spin_lock(&vfsmount_lock); |
| 656 | if (p->event != ns->event) { | 656 | if (p->event != ns->event) { |
| 657 | p->event = ns->event; | 657 | p->event = ns->event; |
| 658 | res = POLLERR; | 658 | res |= POLLERR | POLLPRI; |
| 659 | } | 659 | } |
| 660 | spin_unlock(&vfsmount_lock); | 660 | spin_unlock(&vfsmount_lock); |
| 661 | 661 | ||
diff --git a/fs/sysfs/file.c b/fs/sysfs/file.c index 289c43a4726..b1606e07b7a 100644 --- a/fs/sysfs/file.c +++ b/fs/sysfs/file.c | |||
| @@ -446,11 +446,11 @@ static unsigned int sysfs_poll(struct file *filp, poll_table *wait) | |||
| 446 | if (buffer->event != atomic_read(&od->event)) | 446 | if (buffer->event != atomic_read(&od->event)) |
| 447 | goto trigger; | 447 | goto trigger; |
| 448 | 448 | ||
| 449 | return 0; | 449 | return DEFAULT_POLLMASK; |
| 450 | 450 | ||
| 451 | trigger: | 451 | trigger: |
| 452 | buffer->needs_read_fill = 1; | 452 | buffer->needs_read_fill = 1; |
| 453 | return POLLERR|POLLPRI; | 453 | return DEFAULT_POLLMASK|POLLERR|POLLPRI; |
| 454 | } | 454 | } |
| 455 | 455 | ||
| 456 | void sysfs_notify_dirent(struct sysfs_dirent *sd) | 456 | void sysfs_notify_dirent(struct sysfs_dirent *sd) |
| @@ -667,6 +667,7 @@ struct sysfs_schedule_callback_struct { | |||
| 667 | struct work_struct work; | 667 | struct work_struct work; |
| 668 | }; | 668 | }; |
| 669 | 669 | ||
| 670 | static struct workqueue_struct *sysfs_workqueue; | ||
| 670 | static DEFINE_MUTEX(sysfs_workq_mutex); | 671 | static DEFINE_MUTEX(sysfs_workq_mutex); |
| 671 | static LIST_HEAD(sysfs_workq); | 672 | static LIST_HEAD(sysfs_workq); |
| 672 | static void sysfs_schedule_callback_work(struct work_struct *work) | 673 | static void sysfs_schedule_callback_work(struct work_struct *work) |
| @@ -715,11 +716,20 @@ int sysfs_schedule_callback(struct kobject *kobj, void (*func)(void *), | |||
| 715 | mutex_lock(&sysfs_workq_mutex); | 716 | mutex_lock(&sysfs_workq_mutex); |
| 716 | list_for_each_entry_safe(ss, tmp, &sysfs_workq, workq_list) | 717 | list_for_each_entry_safe(ss, tmp, &sysfs_workq, workq_list) |
| 717 | if (ss->kobj == kobj) { | 718 | if (ss->kobj == kobj) { |
| 719 | module_put(owner); | ||
| 718 | mutex_unlock(&sysfs_workq_mutex); | 720 | mutex_unlock(&sysfs_workq_mutex); |
| 719 | return -EAGAIN; | 721 | return -EAGAIN; |
| 720 | } | 722 | } |
| 721 | mutex_unlock(&sysfs_workq_mutex); | 723 | mutex_unlock(&sysfs_workq_mutex); |
| 722 | 724 | ||
| 725 | if (sysfs_workqueue == NULL) { | ||
| 726 | sysfs_workqueue = create_workqueue("sysfsd"); | ||
| 727 | if (sysfs_workqueue == NULL) { | ||
| 728 | module_put(owner); | ||
| 729 | return -ENOMEM; | ||
| 730 | } | ||
| 731 | } | ||
| 732 | |||
| 723 | ss = kmalloc(sizeof(*ss), GFP_KERNEL); | 733 | ss = kmalloc(sizeof(*ss), GFP_KERNEL); |
| 724 | if (!ss) { | 734 | if (!ss) { |
| 725 | module_put(owner); | 735 | module_put(owner); |
| @@ -735,7 +745,7 @@ int sysfs_schedule_callback(struct kobject *kobj, void (*func)(void *), | |||
| 735 | mutex_lock(&sysfs_workq_mutex); | 745 | mutex_lock(&sysfs_workq_mutex); |
| 736 | list_add_tail(&ss->workq_list, &sysfs_workq); | 746 | list_add_tail(&ss->workq_list, &sysfs_workq); |
| 737 | mutex_unlock(&sysfs_workq_mutex); | 747 | mutex_unlock(&sysfs_workq_mutex); |
| 738 | schedule_work(&ss->work); | 748 | queue_work(sysfs_workqueue, &ss->work); |
| 739 | return 0; | 749 | return 0; |
| 740 | } | 750 | } |
| 741 | EXPORT_SYMBOL_GPL(sysfs_schedule_callback); | 751 | EXPORT_SYMBOL_GPL(sysfs_schedule_callback); |
diff --git a/include/linux/dynamic_debug.h b/include/linux/dynamic_debug.h index baabf33be24..a0d9422a156 100644 --- a/include/linux/dynamic_debug.h +++ b/include/linux/dynamic_debug.h | |||
| @@ -70,7 +70,7 @@ extern int ddebug_remove_module(char *mod_name); | |||
| 70 | DEBUG_HASH2, __LINE__, _DPRINTK_FLAGS_DEFAULT }; \ | 70 | DEBUG_HASH2, __LINE__, _DPRINTK_FLAGS_DEFAULT }; \ |
| 71 | if (__dynamic_dbg_enabled(descriptor)) \ | 71 | if (__dynamic_dbg_enabled(descriptor)) \ |
| 72 | dev_printk(KERN_DEBUG, dev, \ | 72 | dev_printk(KERN_DEBUG, dev, \ |
| 73 | KBUILD_MODNAME ": " pr_fmt(fmt),\ | 73 | KBUILD_MODNAME ": " fmt, \ |
| 74 | ##__VA_ARGS__); \ | 74 | ##__VA_ARGS__); \ |
| 75 | } while (0) | 75 | } while (0) |
| 76 | 76 | ||
diff --git a/include/linux/init.h b/include/linux/init.h index 68cb0265d00..f121a7a10c3 100644 --- a/include/linux/init.h +++ b/include/linux/init.h | |||
| @@ -247,6 +247,7 @@ struct obs_kernel_param { | |||
| 247 | 247 | ||
| 248 | /* Relies on boot_command_line being set */ | 248 | /* Relies on boot_command_line being set */ |
| 249 | void __init parse_early_param(void); | 249 | void __init parse_early_param(void); |
| 250 | void __init parse_early_options(char *cmdline); | ||
| 250 | #endif /* __ASSEMBLY__ */ | 251 | #endif /* __ASSEMBLY__ */ |
| 251 | 252 | ||
| 252 | /** | 253 | /** |
diff --git a/include/linux/kernel.h b/include/linux/kernel.h index d9e75ec7def..883cd44ff76 100644 --- a/include/linux/kernel.h +++ b/include/linux/kernel.h | |||
| @@ -377,6 +377,15 @@ static inline char *pack_hex_byte(char *buf, u8 byte) | |||
| 377 | #define pr_cont(fmt, ...) \ | 377 | #define pr_cont(fmt, ...) \ |
| 378 | printk(KERN_CONT fmt, ##__VA_ARGS__) | 378 | printk(KERN_CONT fmt, ##__VA_ARGS__) |
| 379 | 379 | ||
| 380 | /* pr_devel() should produce zero code unless DEBUG is defined */ | ||
| 381 | #ifdef DEBUG | ||
| 382 | #define pr_devel(fmt, ...) \ | ||
| 383 | printk(KERN_DEBUG pr_fmt(fmt), ##__VA_ARGS__) | ||
| 384 | #else | ||
| 385 | #define pr_devel(fmt, ...) \ | ||
| 386 | ({ if (0) printk(KERN_DEBUG pr_fmt(fmt), ##__VA_ARGS__); 0; }) | ||
| 387 | #endif | ||
| 388 | |||
| 380 | /* If you are writing a driver, please use dev_dbg instead */ | 389 | /* If you are writing a driver, please use dev_dbg instead */ |
| 381 | #if defined(DEBUG) | 390 | #if defined(DEBUG) |
| 382 | #define pr_debug(fmt, ...) \ | 391 | #define pr_debug(fmt, ...) \ |
diff --git a/include/linux/platform_device.h b/include/linux/platform_device.h index 76e470a299b..72736fd8223 100644 --- a/include/linux/platform_device.h +++ b/include/linux/platform_device.h | |||
| @@ -77,4 +77,46 @@ extern int platform_driver_probe(struct platform_driver *driver, | |||
| 77 | #define platform_get_drvdata(_dev) dev_get_drvdata(&(_dev)->dev) | 77 | #define platform_get_drvdata(_dev) dev_get_drvdata(&(_dev)->dev) |
| 78 | #define platform_set_drvdata(_dev,data) dev_set_drvdata(&(_dev)->dev, (data)) | 78 | #define platform_set_drvdata(_dev,data) dev_set_drvdata(&(_dev)->dev, (data)) |
| 79 | 79 | ||
| 80 | /* early platform driver interface */ | ||
| 81 | struct early_platform_driver { | ||
| 82 | const char *class_str; | ||
| 83 | struct platform_driver *pdrv; | ||
| 84 | struct list_head list; | ||
| 85 | int requested_id; | ||
| 86 | }; | ||
| 87 | |||
| 88 | #define EARLY_PLATFORM_ID_UNSET -2 | ||
| 89 | #define EARLY_PLATFORM_ID_ERROR -3 | ||
| 90 | |||
| 91 | extern int early_platform_driver_register(struct early_platform_driver *epdrv, | ||
| 92 | char *buf); | ||
| 93 | extern void early_platform_add_devices(struct platform_device **devs, int num); | ||
| 94 | |||
| 95 | static inline int is_early_platform_device(struct platform_device *pdev) | ||
| 96 | { | ||
| 97 | return !pdev->dev.driver; | ||
| 98 | } | ||
| 99 | |||
| 100 | extern void early_platform_driver_register_all(char *class_str); | ||
| 101 | extern int early_platform_driver_probe(char *class_str, | ||
| 102 | int nr_probe, int user_only); | ||
| 103 | extern void early_platform_cleanup(void); | ||
| 104 | |||
| 105 | |||
| 106 | #ifndef MODULE | ||
| 107 | #define early_platform_init(class_string, platform_driver) \ | ||
| 108 | static __initdata struct early_platform_driver early_driver = { \ | ||
| 109 | .class_str = class_string, \ | ||
| 110 | .pdrv = platform_driver, \ | ||
| 111 | .requested_id = EARLY_PLATFORM_ID_UNSET, \ | ||
| 112 | }; \ | ||
| 113 | static int __init early_platform_driver_setup_func(char *buf) \ | ||
| 114 | { \ | ||
| 115 | return early_platform_driver_register(&early_driver, buf); \ | ||
| 116 | } \ | ||
| 117 | early_param(class_string, early_platform_driver_setup_func) | ||
| 118 | #else /* MODULE */ | ||
| 119 | #define early_platform_init(class_string, platform_driver) | ||
| 120 | #endif /* MODULE */ | ||
| 121 | |||
| 80 | #endif /* _PLATFORM_DEVICE_H_ */ | 122 | #endif /* _PLATFORM_DEVICE_H_ */ |
diff --git a/init/main.c b/init/main.c index 3585f073d63..3bbf93be744 100644 --- a/init/main.c +++ b/init/main.c | |||
| @@ -492,6 +492,11 @@ static int __init do_early_param(char *param, char *val) | |||
| 492 | return 0; | 492 | return 0; |
| 493 | } | 493 | } |
| 494 | 494 | ||
| 495 | void __init parse_early_options(char *cmdline) | ||
| 496 | { | ||
| 497 | parse_args("early options", cmdline, NULL, 0, do_early_param); | ||
| 498 | } | ||
| 499 | |||
| 495 | /* Arch code calls this early on, or if not, just before other parsing. */ | 500 | /* Arch code calls this early on, or if not, just before other parsing. */ |
| 496 | void __init parse_early_param(void) | 501 | void __init parse_early_param(void) |
| 497 | { | 502 | { |
| @@ -503,7 +508,7 @@ void __init parse_early_param(void) | |||
| 503 | 508 | ||
| 504 | /* All fall through to do_early_param. */ | 509 | /* All fall through to do_early_param. */ |
| 505 | strlcpy(tmp_cmdline, boot_command_line, COMMAND_LINE_SIZE); | 510 | strlcpy(tmp_cmdline, boot_command_line, COMMAND_LINE_SIZE); |
| 506 | parse_args("early options", tmp_cmdline, NULL, 0, do_early_param); | 511 | parse_early_options(tmp_cmdline); |
| 507 | done = 1; | 512 | done = 1; |
| 508 | } | 513 | } |
| 509 | 514 | ||
diff --git a/lib/kobject_uevent.c b/lib/kobject_uevent.c index dafeecf5b14..920a3ca6e25 100644 --- a/lib/kobject_uevent.c +++ b/lib/kobject_uevent.c | |||
| @@ -328,7 +328,7 @@ static int __init kobject_uevent_init(void) | |||
| 328 | "kobject_uevent: unable to create netlink socket!\n"); | 328 | "kobject_uevent: unable to create netlink socket!\n"); |
| 329 | return -ENODEV; | 329 | return -ENODEV; |
| 330 | } | 330 | } |
| 331 | 331 | netlink_set_nonroot(NETLINK_KOBJECT_UEVENT, NL_NONROOT_RECV); | |
| 332 | return 0; | 332 | return 0; |
| 333 | } | 333 | } |
| 334 | 334 | ||
