diff --git a/drivers/acpi/ibm_acpi.c b/drivers/acpi/ibm_acpi.c index 003a9876c968..5a8445959f67 100644 --- a/drivers/acpi/ibm_acpi.c +++ b/drivers/acpi/ibm_acpi.c @@ -352,7 +352,7 @@ static char *next_cmd(char **cmds) return start; } -static int driver_init(void) +static int ibm_acpi_driver_init(void) { printk(IBM_INFO "%s v%s\n", IBM_DESC, IBM_VERSION); printk(IBM_INFO "%s\n", IBM_URL); @@ -1605,7 +1605,7 @@ static int fan_write(char *buf) static struct ibm_struct ibms[] = { { .name = "driver", - .init = driver_init, + .init = ibm_acpi_driver_init, .read = driver_read, }, { diff --git a/include/linux/device.h b/include/linux/device.h index 49ab53ce92dc..f44247fe8135 100644 --- a/include/linux/device.h +++ b/include/linux/device.h @@ -433,6 +433,8 @@ static inline int device_is_registered(struct device *dev) return dev->is_registered; } +void driver_init(void); + /* * High level routines for use by the bus drivers */ diff --git a/include/linux/kobject.h b/include/linux/kobject.h index d1c8d28fa92e..76538fcf2c4e 100644 --- a/include/linux/kobject.h +++ b/include/linux/kobject.h @@ -265,8 +265,8 @@ extern int __must_check subsys_create_file(struct subsystem * , struct subsys_attribute *); #if defined(CONFIG_HOTPLUG) -void kobject_uevent(struct kobject *kobj, enum kobject_action action); -void kobject_uevent_env(struct kobject *kobj, enum kobject_action action, +int kobject_uevent(struct kobject *kobj, enum kobject_action action); +int kobject_uevent_env(struct kobject *kobj, enum kobject_action action, char *envp[]); int add_uevent_var(char **envp, int num_envp, int *cur_index, @@ -274,11 +274,12 @@ int add_uevent_var(char **envp, int num_envp, int *cur_index, const char *format, ...) __attribute__((format (printf, 7, 8))); #else -static inline void kobject_uevent(struct kobject *kobj, enum kobject_action action) { } -static inline void kobject_uevent_env(struct kobject *kobj, +static inline int kobject_uevent(struct kobject *kobj, enum kobject_action action) +{ return 0; } +static inline int kobject_uevent_env(struct kobject *kobj, enum kobject_action action, char *envp[]) -{ } +{ return 0; } static inline int add_uevent_var(char **envp, int num_envp, int *cur_index, char *buffer, int buffer_size, int *cur_len, diff --git a/init/main.c b/init/main.c index e3f0bb20b4dd..2b1cdaab45e6 100644 --- a/init/main.c +++ b/init/main.c @@ -53,6 +53,7 @@ #include #include #include +#include #include #include @@ -94,7 +95,6 @@ extern void pidmap_init(void); extern void prio_tree_init(void); extern void radix_tree_init(void); extern void free_initmem(void); -extern void driver_init(void); extern void prepare_namespace(void); #ifdef CONFIG_ACPI extern void acpi_early_init(void); diff --git a/lib/kobject_uevent.c b/lib/kobject_uevent.c index a1922765ff31..84272ed77f03 100644 --- a/lib/kobject_uevent.c +++ b/lib/kobject_uevent.c @@ -63,8 +63,11 @@ static char *action_to_string(enum kobject_action action) * @action: action that is happening (usually KOBJ_MOVE) * @kobj: struct kobject that the action is happening to * @envp_ext: pointer to environmental data + * + * Returns 0 if kobject_uevent() is completed with success or the + * corresponding error when it fails. */ -void kobject_uevent_env(struct kobject *kobj, enum kobject_action action, +int kobject_uevent_env(struct kobject *kobj, enum kobject_action action, char *envp_ext[]) { char **envp; @@ -79,14 +82,16 @@ void kobject_uevent_env(struct kobject *kobj, enum kobject_action action, u64 seq; char *seq_buff; int i = 0; - int retval; + int retval = 0; int j; pr_debug("%s\n", __FUNCTION__); action_string = action_to_string(action); - if (!action_string) - return; + if (!action_string) { + pr_debug("kobject attempted to send uevent without action_string!\n"); + return -EINVAL; + } /* search the kset we belong to */ top_kobj = kobj; @@ -95,31 +100,39 @@ void kobject_uevent_env(struct kobject *kobj, enum kobject_action action, top_kobj = top_kobj->parent; } while (!top_kobj->kset && top_kobj->parent); } - if (!top_kobj->kset) - return; + if (!top_kobj->kset) { + pr_debug("kobject attempted to send uevent without kset!\n"); + return -EINVAL; + } kset = top_kobj->kset; uevent_ops = kset->uevent_ops; /* skip the event, if the filter returns zero. */ if (uevent_ops && uevent_ops->filter) - if (!uevent_ops->filter(kset, kobj)) - return; + if (!uevent_ops->filter(kset, kobj)) { + pr_debug("kobject filter function caused the event to drop!\n"); + return 0; + } /* environment index */ envp = kzalloc(NUM_ENVP * sizeof (char *), GFP_KERNEL); if (!envp) - return; + return -ENOMEM; /* environment values */ buffer = kmalloc(BUFFER_SIZE, GFP_KERNEL); - if (!buffer) + if (!buffer) { + retval = -ENOMEM; goto exit; + } /* complete object path */ devpath = kobject_get_path(kobj, GFP_KERNEL); - if (!devpath) + if (!devpath) { + retval = -ENOENT; goto exit; + } /* originating subsystem */ if (uevent_ops && uevent_ops->name) @@ -204,7 +217,7 @@ void kobject_uevent_env(struct kobject *kobj, enum kobject_action action, kfree(devpath); kfree(buffer); kfree(envp); - return; + return retval; } EXPORT_SYMBOL_GPL(kobject_uevent_env); @@ -214,10 +227,13 @@ EXPORT_SYMBOL_GPL(kobject_uevent_env); * * @action: action that is happening (usually KOBJ_ADD and KOBJ_REMOVE) * @kobj: struct kobject that the action is happening to + * + * Returns 0 if kobject_uevent() is completed with success or the + * corresponding error when it fails. */ -void kobject_uevent(struct kobject *kobj, enum kobject_action action) +int kobject_uevent(struct kobject *kobj, enum kobject_action action) { - kobject_uevent_env(kobj, action, NULL); + return kobject_uevent_env(kobj, action, NULL); } EXPORT_SYMBOL_GPL(kobject_uevent); diff --git a/lib/kref.c b/lib/kref.c index 4a467faf1367..0d07cc31c818 100644 --- a/lib/kref.c +++ b/lib/kref.c @@ -52,12 +52,7 @@ int kref_put(struct kref *kref, void (*release)(struct kref *kref)) WARN_ON(release == NULL); WARN_ON(release == (void (*)(struct kref *))kfree); - /* - * if current count is one, we are the last user and can release object - * right now, avoiding an atomic operation on 'refcount' - */ - if ((atomic_read(&kref->refcount) == 1) || - (atomic_dec_and_test(&kref->refcount))) { + if (atomic_dec_and_test(&kref->refcount)) { release(kref); return 1; }