From 5c11c52046eb0f7252574bad161db53d0345ea50 Mon Sep 17 00:00:00 2001 From: "minyard@acm.org" Date: Mon, 18 Apr 2005 21:57:30 -0700 Subject: [PATCH] kref: add documentation Add some documentation for krefs. Signed-off-by: Corey Minyard Signed-off-by: Greg Kroah-Hartman --- Documentation/kref.txt | 211 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 211 insertions(+) create mode 100644 Documentation/kref.txt diff --git a/Documentation/kref.txt b/Documentation/kref.txt new file mode 100644 index 00000000000..96d8f5666af --- /dev/null +++ b/Documentation/kref.txt @@ -0,0 +1,211 @@ + +krefs allow you to add reference counters to your objects. If you +have objects that are used in multiple places and passed around, and +you don't have refcounts, your code is almost certainly broken. If +you want refcounts, krefs are the way to go. + +To use a kref, add one to your data structures like: + +struct my_data +{ + . + . + struct kref refcount; + . + . +}; + +The kref can occur anywhere within the data structure. + +You must initialize the kref after you allocate it. To do this, call +kref_init as so: + + struct my_data *data; + + data = kmalloc(sizeof(*data), GFP_KERNEL); + if (!data) + return -ENOMEM; + kref_init(&data->refcount); + +This sets the refcount in the kref to 1. + +Once you have an initialized kref, you must follow the following +rules: + +1) If you make a non-temporary copy of a pointer, especially if + it can be passed to another thread of execution, you must + increment the refcount with kref_get() before passing it off: + kref_get(&data->refcount); + If you already have a valid pointer to a kref-ed structure (the + refcount cannot go to zero) you may do this without a lock. + +2) When you are done with a pointer, you must call kref_put(): + kref_put(&data->refcount, data_release); + If this is the last reference to the pointer, the release + routine will be called. If the code never tries to get + a valid pointer to a kref-ed structure without already + holding a valid pointer, it is safe to do this without + a lock. + +3) If the code attempts to gain a reference to a kref-ed structure + without already holding a valid pointer, it must serialize access + where a kref_put() cannot occur during the kref_get(), and the + structure must remain valid during the kref_get(). + +For example, if you allocate some data and then pass it to another +thread to process: + +void data_release(struct kref *ref) +{ + struct my_data *data = container_of(ref, struct my_data, refcount); + kfree(data); +} + +void more_data_handling(void *cb_data) +{ + struct my_data *data = cb_data; + . + . do stuff with data here + . + kref_put(data, data_release); +} + +int my_data_handler(void) +{ + int rv = 0; + struct my_data *data; + struct task_struct *task; + data = kmalloc(sizeof(*data), GFP_KERNEL); + if (!data) + return -ENOMEM; + kref_init(&data->refcount); + + kref_get(&data->refcount); + task = kthread_run(more_data_handling, data, "more_data_handling"); + if (task == ERR_PTR(-ENOMEM)) { + rv = -ENOMEM; + kref_put(&data->refcount, data_release); + goto out; + } + + . + . do stuff with data here + . + out: + kref_put(&data->refcount, data_release); + return rv; +} + +This way, it doesn't matter what order the two threads handle the +data, the kref_put() handles knowing when the data is not referenced +any more and releasing it. The kref_get() does not require a lock, +since we already have a valid pointer that we own a refcount for. The +put needs no lock because nothing tries to get the data without +already holding a pointer. + +Note that the "before" in rule 1 is very important. You should never +do something like: + + task = kthread_run(more_data_handling, data, "more_data_handling"); + if (task == ERR_PTR(-ENOMEM)) { + rv = -ENOMEM; + goto out; + } else + /* BAD BAD BAD - get is after the handoff */ + kref_get(&data->refcount); + +Don't assume you know what you are doing and use the above construct. +First of all, you may not know what you are doing. Second, you may +know what you are doing (there are some situations where locking is +involved where the above may be legal) but someone else who doesn't +know what they are doing may change the code or copy the code. It's +bad style. Don't do it. + +There are some situations where you can optimize the gets and puts. +For instance, if you are done with an object and enqueuing it for +something else or passing it off to something else, there is no reason +to do a get then a put: + + /* Silly extra get and put */ + kref_get(&obj->ref); + enqueue(obj); + kref_put(&obj->ref, obj_cleanup); + +Just do the enqueue. A comment about this is always welcome: + + enqueue(obj); + /* We are done with obj, so we pass our refcount off + to the queue. DON'T TOUCH obj AFTER HERE! */ + +The last rule (rule 3) is the nastiest one to handle. Say, for +instance, you have a list of items that are each kref-ed, and you wish +to get the first one. You can't just pull the first item off the list +and kref_get() it. That violates rule 3 because you are not already +holding a valid pointer. You must add locks or semaphores. For +instance: + +static DECLARE_MUTEX(sem); +static LIST_HEAD(q); +struct my_data +{ + struct kref refcount; + struct list_head link; +}; + +static struct my_data *get_entry() +{ + struct my_data *entry = NULL; + down(&sem); + if (!list_empty(&q)) { + entry = container_of(q.next, struct my_q_entry, link); + kref_get(&entry->refcount); + } + up(&sem); + return entry; +} + +static void release_entry(struct kref *ref) +{ + struct my_data *entry = container_of(ref, struct my_data, refcount); + + list_del(&entry->link); + kfree(entry); +} + +static void put_entry(struct my_data *entry) +{ + down(&sem); + kref_put(&entry->refcount, release_entry); + up(&sem); +} + +The kref_put() return value is useful if you do not want to hold the +lock during the whole release operation. Say you didn't want to call +kfree() with the lock held in the example above (since it is kind of +pointless to do so). You could use kref_put() as follows: + +static void release_entry(struct kref *ref) +{ + /* All work is done after the return from kref_put(). */ +} + +static void put_entry(struct my_data *entry) +{ + down(&sem); + if (kref_put(&entry->refcount, release_entry)) { + list_del(&entry->link); + up(&sem); + kfree(entry); + } else + up(&sem); +} + +This is really more useful if you have to call other routines as part +of the free operations that could take a long time or might claim the +same lock. Note that doing everything in the release routine is still +preferred as it is a little neater. + + +Corey Minyard + +A lot of this was lifted from Greg KH's OLS presentation on krefs. -- cgit v1.2.3-70-g09d2 From 6f31e42221c7deae4527136ce0dd73990d8bc1d1 Mon Sep 17 00:00:00 2001 From: "gregkh@suse.de" Date: Mon, 18 Apr 2005 21:57:30 -0700 Subject: [PATCH] kref: add link to original documentation to the kref documentation. Signed-off-by: Greg Kroah-Hartman --- Documentation/kref.txt | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/Documentation/kref.txt b/Documentation/kref.txt index 96d8f5666af..42fe2844591 100644 --- a/Documentation/kref.txt +++ b/Documentation/kref.txt @@ -208,4 +208,9 @@ preferred as it is a little neater. Corey Minyard -A lot of this was lifted from Greg KH's OLS presentation on krefs. +A lot of this was lifted from Greg Kroah-Hartman's 2004 OLS paper and +presentation on krefs, which can be found at: + http://www.kroah.com/linux/talks/ols_2004_kref_paper/Reprint-Kroah-Hartman-OLS2004.pdf +and: + http://www.kroah.com/linux/talks/ols_2004_kref_talk/ + -- cgit v1.2.3-70-g09d2 From 6897089c5f7989603ccb9c696050470ba1dbd262 Mon Sep 17 00:00:00 2001 From: "kay.sievers@vrfy.org" Date: Mon, 18 Apr 2005 21:57:31 -0700 Subject: [PATCH] add TIMEOUT to firmware_class hotplug event On Tue, 2005-03-15 at 09:25 +0100, Hannes Reinecke wrote: > The current implementation of the firmware class breaks a fundamental > assumption in udevd: that the physical device can be initialised fully > prior to executing the next event for that device. Here we add a TIMEOUT value to the hotplug environment of the firmware requesting event. I will adapt udevd not to wait for anything else, if it finds a TIMEOUT key. Signed-off-by: Kay Sievers Signed-off-by: Greg Kroah-Hartman --- drivers/base/firmware_class.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/base/firmware_class.c b/drivers/base/firmware_class.c index 26c9464af80..97fe13f7f07 100644 --- a/drivers/base/firmware_class.c +++ b/drivers/base/firmware_class.c @@ -102,6 +102,9 @@ firmware_class_hotplug(struct class_device *class_dev, char **envp, if (add_hotplug_env_var(envp, num_envp, &i, buffer, buffer_size, &len, "FIRMWARE=%s", fw_priv->fw_id)) return -ENOMEM; + if (add_hotplug_env_var(envp, num_envp, &i, buffer, buffer_size, &len, + "TIMEOUT=%i", loading_timeout)) + return -ENOMEM; envp[i] = NULL; -- cgit v1.2.3-70-g09d2 From 31e5abe9a6dab1ed3a5c30352bdb001353146318 Mon Sep 17 00:00:00 2001 From: Kay Sievers Date: Mon, 18 Apr 2005 21:57:32 -0700 Subject: [PATCH] sysfs: add sysfs_chmod_file() sysfs: allow changing the permissions for already created attributes Signed-off-by: Kay Sievers Signed-off-by: Greg Kroah-Hartman --- fs/sysfs/file.c | 35 +++++++++++++++++++++++++++++++++++ include/linux/sysfs.h | 7 +++++++ 2 files changed, 42 insertions(+) diff --git a/fs/sysfs/file.c b/fs/sysfs/file.c index 352f966a117..da25aeb0e06 100644 --- a/fs/sysfs/file.c +++ b/fs/sysfs/file.c @@ -427,6 +427,41 @@ int sysfs_update_file(struct kobject * kobj, const struct attribute * attr) } +/** + * sysfs_chmod_file - update the modified mode value on an object attribute. + * @kobj: object we're acting for. + * @attr: attribute descriptor. + * @mode: file permissions. + * + */ +int sysfs_chmod_file(struct kobject *kobj, struct attribute *attr, mode_t mode) +{ + struct dentry *dir = kobj->dentry; + struct dentry *victim; + struct sysfs_dirent *sd; + umode_t umode = (mode & S_IALLUGO) | S_IFREG; + int res = -ENOENT; + + down(&dir->d_inode->i_sem); + victim = sysfs_get_dentry(dir, attr->name); + if (!IS_ERR(victim)) { + if (victim->d_inode && + (victim->d_parent->d_inode == dir->d_inode)) { + sd = victim->d_fsdata; + attr->mode = mode; + sd->s_mode = umode; + victim->d_inode->i_mode = umode; + dput(victim); + res = 0; + } + } + up(&dir->d_inode->i_sem); + + return res; +} +EXPORT_SYMBOL_GPL(sysfs_chmod_file); + + /** * sysfs_remove_file - remove an object attribute. * @kobj: object we're acting for. diff --git a/include/linux/sysfs.h b/include/linux/sysfs.h index 6f502ff7902..38b58b30814 100644 --- a/include/linux/sysfs.h +++ b/include/linux/sysfs.h @@ -99,6 +99,9 @@ sysfs_create_file(struct kobject *, const struct attribute *); extern int sysfs_update_file(struct kobject *, const struct attribute *); +extern int +sysfs_chmod_file(struct kobject *kobj, struct attribute *attr, mode_t mode); + extern void sysfs_remove_file(struct kobject *, const struct attribute *); @@ -140,6 +143,10 @@ static inline int sysfs_update_file(struct kobject * k, const struct attribute * { return 0; } +static inline int sysfs_chmod_file(struct kobject *kobj, struct attribute *attr, mode_t mode) +{ + return 0; +} static inline void sysfs_remove_file(struct kobject * k, const struct attribute * a) { -- cgit v1.2.3-70-g09d2 From 46ea0d6c26de431a39c744f7ad63b30bfc800c1e Mon Sep 17 00:00:00 2001 From: Robert Schwebel Date: Mon, 18 Apr 2005 21:57:32 -0700 Subject: [PATCH] export platform_add_devices platform_add_devices can be used from within modules, so it should be exported. This can for example happen if you have hotpluggable firmware in an FPGA on a system on chip processor; in our case the FPGA is probed for devices and the FPGA base code registers the devices it has found with the kernel. (akpm: I think this is reasonable from a licensing POV: it's unlikely that anyone would be interested in merging such specialised modules into mainline, and it's a GPL export). Signed-off-by: Robert Schwebel Signed-off-by: Andrew Morton Signed-off-by: Greg Kroah-Hartman --- drivers/base/platform.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/base/platform.c b/drivers/base/platform.c index 996cbb4d508..cd6453905a9 100644 --- a/drivers/base/platform.c +++ b/drivers/base/platform.c @@ -341,6 +341,7 @@ EXPORT_SYMBOL_GPL(dma_get_required_mask); EXPORT_SYMBOL_GPL(platform_bus); EXPORT_SYMBOL_GPL(platform_bus_type); +EXPORT_SYMBOL_GPL(platform_add_devices); EXPORT_SYMBOL_GPL(platform_device_register); EXPORT_SYMBOL_GPL(platform_device_register_simple); EXPORT_SYMBOL_GPL(platform_device_unregister); -- cgit v1.2.3-70-g09d2 From 1694145854a309bebd12a5cce63c9b398304e3bb Mon Sep 17 00:00:00 2001 From: Steven Cole Date: Mon, 18 Apr 2005 21:57:33 -0700 Subject: [PATCH] 2.6.12-rc1-mm3 Fix ver_linux script for no udev utils. Without the attached patch, the ver_linux script gives the following if udev utils are not present. ./scripts/ver_linux: line 90: udevinfo: command not found The patch causes ver_linux to be silent in the case of no udevinfo command. Signed-off-by: Steven Cole Signed-off-by: Greg Kroah-Hartman --- scripts/ver_linux | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/ver_linux b/scripts/ver_linux index bb195a1c0f2..a28c279c49d 100755 --- a/scripts/ver_linux +++ b/scripts/ver_linux @@ -87,7 +87,7 @@ loadkeys -V 2>&1 | awk \ expr --v 2>&1 | awk 'NR==1{print "Sh-utils ", $NF}' -udevinfo -V | awk '{print "udev ", $3}' +udevinfo -V 2>&1 | grep version | awk '{print "udev ", $3}' if [ -e /proc/modules ]; then X=`cat /proc/modules | sed -e "s/ .*$//"` -- cgit v1.2.3-70-g09d2 From a7a76cefc4b12bb6508afa4c77f11c2752cc365d Mon Sep 17 00:00:00 2001 From: Roland Dreier Date: Mon, 18 Apr 2005 21:57:33 -0700 Subject: [PATCH] debugfs: Reduce dependencies The current include file is a little fragile in that it is not self-contained and hence may cause compile warnings or errors depending on the files included before it, the kernel config and the architecture. This patch makes things a little more robust by: - including to get definitions of u32, mode_t, and so on. - forward declaring struct file_operations. - including when CONFIG_DEBUG_FS is not set The last change is particularly useful, as a kernel developer is likely to build with debugfs always enabled and never see the build breakage cased if debugfs is disabled. Signed-off-by: Roland Dreier Signed-off-by: Greg Kroah-Hartman --- include/linux/debugfs.h | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/include/linux/debugfs.h b/include/linux/debugfs.h index f7a7b86f6ee..dcf847cdb5c 100644 --- a/include/linux/debugfs.h +++ b/include/linux/debugfs.h @@ -17,6 +17,10 @@ #include +#include + +struct file_operations; + #if defined(CONFIG_DEBUG_FS) struct dentry *debugfs_create_file(const char *name, mode_t mode, struct dentry *parent, void *data, @@ -36,6 +40,9 @@ struct dentry *debugfs_create_bool(const char *name, mode_t mode, struct dentry *parent, u32 *value); #else + +#include + /* * We do not return NULL from these functions if CONFIG_DEBUG_FS is not enabled * so users have a chance to detect if there was a real error or not. We don't -- cgit v1.2.3-70-g09d2 From 7b558637b0efc6ab3f3ca08f0b9cc0191665e9db Mon Sep 17 00:00:00 2001 From: Michal Ostrowski Date: Mon, 18 Apr 2005 21:57:34 -0700 Subject: [PATCH] debugfs: fix !debugfs prototypes - Fix prototypes for debugfs functions (in configurations where debugfs is disabled). Signed-off-by: Michal Ostrowski Signed-off-by: Greg Kroah-Hartman --- include/linux/debugfs.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/include/linux/debugfs.h b/include/linux/debugfs.h index dcf847cdb5c..a5fa6a6eede 100644 --- a/include/linux/debugfs.h +++ b/include/linux/debugfs.h @@ -75,21 +75,21 @@ static inline struct dentry *debugfs_create_u8(const char *name, mode_t mode, static inline struct dentry *debugfs_create_u16(const char *name, mode_t mode, struct dentry *parent, - u8 *value) + u16 *value) { return ERR_PTR(-ENODEV); } static inline struct dentry *debugfs_create_u32(const char *name, mode_t mode, struct dentry *parent, - u8 *value) + u32 *value) { return ERR_PTR(-ENODEV); } static inline struct dentry *debugfs_create_bool(const char *name, mode_t mode, struct dentry *parent, - u8 *value) + u32 *value) { return ERR_PTR(-ENODEV); } -- cgit v1.2.3-70-g09d2 From 18c3d5271b472c096adfc856e107c79f6fd30d7d Mon Sep 17 00:00:00 2001 From: "kay.sievers@vrfy.org" Date: Mon, 18 Apr 2005 21:57:34 -0700 Subject: [PATCH] kobject/hotplug split - kobject add/remove kobject_add() and kobject_del() don't emit hotplug events anymore. The user should do it itself if it has finished populating the device directory. Signed-off-by: Kay Sievers Signed-off-by: Greg Kroah-Hartman --- lib/kobject.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/lib/kobject.c b/lib/kobject.c index ff9491986b3..5df8441c44e 100644 --- a/lib/kobject.c +++ b/lib/kobject.c @@ -184,8 +184,6 @@ int kobject_add(struct kobject * kobj) unlink(kobj); if (parent) kobject_put(parent); - } else { - kobject_hotplug(kobj, KOBJ_ADD); } return error; @@ -207,7 +205,8 @@ int kobject_register(struct kobject * kobj) printk("kobject_register failed for %s (%d)\n", kobject_name(kobj),error); dump_stack(); - } + } else + kobject_hotplug(kobj, KOBJ_ADD); } else error = -EINVAL; return error; @@ -301,7 +300,6 @@ int kobject_rename(struct kobject * kobj, char *new_name) void kobject_del(struct kobject * kobj) { - kobject_hotplug(kobj, KOBJ_REMOVE); sysfs_remove_dir(kobj); unlink(kobj); } @@ -314,6 +312,7 @@ void kobject_del(struct kobject * kobj) void kobject_unregister(struct kobject * kobj) { pr_debug("kobject %s: unregistering\n",kobject_name(kobj)); + kobject_hotplug(kobj, KOBJ_REMOVE); kobject_del(kobj); kobject_put(kobj); } -- cgit v1.2.3-70-g09d2 From 0700f56bbca56bc930aab717bc5086336991441f Mon Sep 17 00:00:00 2001 From: "kay.sievers@vrfy.org" Date: Mon, 18 Apr 2005 21:57:35 -0700 Subject: [PATCH] kobject/hotplug split - class core kobject_add() and kobject_del() don't emit hotplug events anymore. Do it ourselves if we are finished populating the device directory. Signed-off-by: Kay Sievers Signed-off-by: Greg Kroah-Hartman --- drivers/base/class.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/base/class.c b/drivers/base/class.c index 6bf650fce78..d2a2f8f2b4e 100644 --- a/drivers/base/class.c +++ b/drivers/base/class.c @@ -430,6 +430,7 @@ int class_device_add(struct class_device *class_dev) sysfs_create_link(&class_dev->kobj, &class_dev->dev->kobj, "device"); + kobject_hotplug(&class_dev->kobj, KOBJ_ADD); register_done: if (error && parent) class_put(parent); @@ -461,6 +462,7 @@ void class_device_del(struct class_device *class_dev) sysfs_remove_link(&class_dev->kobj, "device"); class_device_remove_attrs(class_dev); + kobject_hotplug(&class_dev->kobj, KOBJ_REMOVE); kobject_del(&class_dev->kobj); if (parent) -- cgit v1.2.3-70-g09d2 From b41148c0d8d2fa0c36cebd9ba3ee4cfc0dc7cb9a Mon Sep 17 00:00:00 2001 From: "kay.sievers@vrfy.org" Date: Mon, 18 Apr 2005 21:57:36 -0700 Subject: [PATCH] kobject/hotplug split - block core kobject_add() and kobject_del() don't emit hotplug events anymore. Do it ourselves if we are finished populating the device directory. Signed-off-by: Kay Sievers Signed-off-by: Greg Kroah-Hartman --- fs/partitions/check.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/fs/partitions/check.c b/fs/partitions/check.c index 31cff785b3b..2cab98a9a62 100644 --- a/fs/partitions/check.c +++ b/fs/partitions/check.c @@ -337,6 +337,7 @@ void register_disk(struct gendisk *disk) if ((err = kobject_add(&disk->kobj))) return; disk_sysfs_symlinks(disk); + kobject_hotplug(&disk->kobj, KOBJ_ADD); /* No minors to use for partitions */ if (disk->minors == 1) { @@ -441,5 +442,6 @@ void del_gendisk(struct gendisk *disk) sysfs_remove_link(&disk->driverfs_dev->kobj, "block"); put_device(disk->driverfs_dev); } + kobject_hotplug(&disk->kobj, KOBJ_REMOVE); kobject_del(&disk->kobj); } -- cgit v1.2.3-70-g09d2 From e57cd73e2e844a3da25cc6b420674c81bbe1b387 Mon Sep 17 00:00:00 2001 From: "kay.sievers@vrfy.org" Date: Mon, 18 Apr 2005 21:57:36 -0700 Subject: [PATCH] kobject/hotplug split - devices core kobject_add() and kobject_del() don't emit hotplug events anymore. Do it ourselves if we are finished populating the device directory. Signed-off-by: Kay Sievers Signed-off-by: Greg Kroah-Hartman --- drivers/base/core.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/base/core.c b/drivers/base/core.c index 4e6cce8e6d3..a7cedd8cefe 100644 --- a/drivers/base/core.c +++ b/drivers/base/core.c @@ -260,6 +260,8 @@ int device_add(struct device *dev) /* notify platform of device entry */ if (platform_notify) platform_notify(dev); + + kobject_hotplug(&dev->kobj, KOBJ_ADD); Done: put_device(dev); return error; @@ -349,6 +351,7 @@ void device_del(struct device * dev) platform_notify_remove(dev); bus_remove_device(dev); device_pm_remove(dev); + kobject_hotplug(&dev->kobj, KOBJ_REMOVE); kobject_del(&dev->kobj); if (parent) put_device(parent); -- cgit v1.2.3-70-g09d2 From 089d42b013675b028a499c61bac59954067dc668 Mon Sep 17 00:00:00 2001 From: "kay.sievers@vrfy.org" Date: Mon, 18 Apr 2005 21:57:37 -0700 Subject: [PATCH] kobject/hotplug split - usb cris kobject_add() and kobject_del() don't emit hotplug events anymore. We need to do it ourselves now. Signed-off-by: Kay Sievers Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/hc_crisv10.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/usb/host/hc_crisv10.c b/drivers/usb/host/hc_crisv10.c index 4b12be822bd..376f8a034f6 100644 --- a/drivers/usb/host/hc_crisv10.c +++ b/drivers/usb/host/hc_crisv10.c @@ -4396,6 +4396,7 @@ static int __init etrax_usb_hc_init(void) device_initialize(&fake_device); kobject_set_name(&fake_device.kobj, "etrax_usb"); kobject_add(&fake_device.kobj); + kobject_hotplug(&fake_device.kobj, KOBJ_ADD); hc->bus->controller = &fake_device; usb_register_bus(hc->bus); -- cgit v1.2.3-70-g09d2 From f0e035f4b6940aae6836500b642029c289ed4535 Mon Sep 17 00:00:00 2001 From: "kay.sievers@vrfy.org" Date: Mon, 18 Apr 2005 21:57:37 -0700 Subject: [PATCH] kobject/hotplug split - net bridge kobject_add() and kobject_del() don't emit hotplug events anymore. We need to do it ourselves now. Signed-off-by: Kay Sievers Signed-off-by: Greg Kroah-Hartman --- net/bridge/br_sysfs_if.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/net/bridge/br_sysfs_if.c b/net/bridge/br_sysfs_if.c index 567249bf933..f6a19d53eae 100644 --- a/net/bridge/br_sysfs_if.c +++ b/net/bridge/br_sysfs_if.c @@ -248,6 +248,7 @@ int br_sysfs_addif(struct net_bridge_port *p) if (err) goto out2; + kobject_hotplug(&p->kobj, KOBJ_ADD); return 0; out2: kobject_del(&p->kobj); @@ -259,6 +260,7 @@ void br_sysfs_removeif(struct net_bridge_port *p) { pr_debug("br_sysfs_removeif\n"); sysfs_remove_link(&p->br->ifobj, p->dev->name); + kobject_hotplug(&p->kobj, KOBJ_REMOVE); kobject_del(&p->kobj); } -- cgit v1.2.3-70-g09d2