[PATCH 3/7] s3c-hsudc: add a remove function
Russell King - ARM Linux
linux at arm.linux.org.uk
Sun Dec 18 09:43:19 EST 2011
On Sun, Dec 18, 2011 at 02:44:39PM +0100, Heiko Stübner wrote:
> Am Sonntag 18 Dezember 2011, 09:10:48 schrieb Russell King - ARM Linux:
> > On Sat, Dec 17, 2011 at 08:26:33PM +0100, Heiko Stübner wrote:
> > > As the driver is also buildable as a module it should need
> > > a cleanup function for the removal of the module.
> >
> > My guess is that this wasn't implemented because of the embedded struct
> > device lifetime rules for the gadget - to prevent the unbinding of the
> > driver.
> >
> > Until the struct device lifetime gets fixed, you must not allow the module
> > nor the data structure containing the struct device to be freed.
>
> I understand where this problem comes from (the release method is potentially
> gone with the module before it is called) but after more reading, I have a
> hard time believing that a lot of the other gadget drivers would be wrong as
> well. Some of them since 2009 or possibly earlier.
>
> Gadgets with embedded release methods: langwell_udc, goku_udc, fsl_qe_udc (and
> fsl_udc_core), amd5536udc, net2280, pch_udc, cil13xxx_udc, dummy_hcd,
> omap_udc, net2272, mc_udc_core
>
> Gadgets which use the release method from its pdev->dev but also free the
> struct with the gadget in their remove method: r8a66597-udc, m66592-udc,
> fusb300_udc. (possibly before the release function is called)
>
> On the other hand, the gets and puts of the udc->gadget.dev should be paired
> correctly and it's only an intermediate device between the udc and the gadget
> driver, so that the call to device_unregister in the remove method should put
> the refcount to 0 and thus init the cleanup (including the call to release)
> before the module is removed.
>
> So, I am very confused :-).
Try this patch. If your system oopses 5 seconds after you remove the
module, you have a lifetime bug.
diff --git a/include/linux/kobject.h b/include/linux/kobject.h
index ad81e1c..be1c97a 100644
--- a/include/linux/kobject.h
+++ b/include/linux/kobject.h
@@ -26,6 +26,9 @@
#include <linux/kernel.h>
#include <linux/wait.h>
#include <linux/atomic.h>
+#include <linux/workqueue.h>
+
+#define KOBJECT_DEBUG_RELEASE
#define UEVENT_HELPER_PATH_LEN 256
#define UEVENT_NUM_ENVP 32 /* number of env pointers */
@@ -65,6 +68,9 @@ struct kobject {
struct kobj_type *ktype;
struct sysfs_dirent *sd;
struct kref kref;
+#ifdef KOBJECT_DEBUG_RELEASE
+ struct delayed_work release;
+#endif
unsigned int state_initialized:1;
unsigned int state_in_sysfs:1;
unsigned int state_add_uevent_sent:1;
diff --git a/lib/kobject.c b/lib/kobject.c
index 640bd98..fe57f3a 100644
--- a/lib/kobject.c
+++ b/lib/kobject.c
@@ -575,9 +575,23 @@ static void kobject_cleanup(struct kobject *kobj)
}
}
+#ifdef KOBJECT_DEBUG_RELEASE
+static void kobject_delayed_cleanup(struct work_struct *work)
+{
+ kobject_cleanup(container_of(to_delayed_work(work),
+ struct kobject, release));
+}
+#endif
+
static void kobject_release(struct kref *kref)
{
- kobject_cleanup(container_of(kref, struct kobject, kref));
+ struct kobject *kobj = container_of(kref, struct kobject, kref);
+#ifdef KOBJECT_DEBUG_RELEASE
+ INIT_DELAYED_WORK(&kobj->release, kobject_delayed_cleanup);
+ schedule_delayed_work(&kobj->release, 5 * HZ);
+#else
+ kobject_cleanup(kobj);
+#endif
}
/**
More information about the linux-arm-kernel
mailing list