@@ -836,23 +836,36 @@ static struct kobject *get_device_parent(struct device *dev,
836836 return NULL ;
837837}
838838
839+ static inline bool live_in_glue_dir (struct kobject * kobj ,
840+ struct device * dev )
841+ {
842+ if (!kobj || !dev -> class ||
843+ kobj -> kset != & dev -> class -> p -> glue_dirs )
844+ return false;
845+ return true;
846+ }
847+
848+ static inline struct kobject * get_glue_dir (struct device * dev )
849+ {
850+ return dev -> kobj .parent ;
851+ }
852+
853+ /*
854+ * make sure cleaning up dir as the last step, we need to make
855+ * sure .release handler of kobject is run with holding the
856+ * global lock
857+ */
839858static void cleanup_glue_dir (struct device * dev , struct kobject * glue_dir )
840859{
841860 /* see if we live in a "glue" directory */
842- if (!glue_dir || !dev -> class ||
843- glue_dir -> kset != & dev -> class -> p -> glue_dirs )
861+ if (!live_in_glue_dir (glue_dir , dev ))
844862 return ;
845863
846864 mutex_lock (& gdp_mutex );
847865 kobject_put (glue_dir );
848866 mutex_unlock (& gdp_mutex );
849867}
850868
851- static void cleanup_device_parent (struct device * dev )
852- {
853- cleanup_glue_dir (dev , dev -> kobj .parent );
854- }
855-
856869static int device_add_class_symlinks (struct device * dev )
857870{
858871 struct device_node * of_node = dev_of_node (dev );
@@ -1028,6 +1041,7 @@ int device_add(struct device *dev)
10281041 struct kobject * kobj ;
10291042 struct class_interface * class_intf ;
10301043 int error = - EINVAL ;
1044+ struct kobject * glue_dir = NULL ;
10311045
10321046 dev = get_device (dev );
10331047 if (!dev )
@@ -1072,8 +1086,10 @@ int device_add(struct device *dev)
10721086 /* first, register with generic layer. */
10731087 /* we require the name to be set before, and pass NULL */
10741088 error = kobject_add (& dev -> kobj , dev -> kobj .parent , NULL );
1075- if (error )
1089+ if (error ) {
1090+ glue_dir = get_glue_dir (dev );
10761091 goto Error ;
1092+ }
10771093
10781094 /* notify platform of device entry */
10791095 if (platform_notify )
@@ -1154,9 +1170,10 @@ int device_add(struct device *dev)
11541170 device_remove_file (dev , & dev_attr_uevent );
11551171 attrError :
11561172 kobject_uevent (& dev -> kobj , KOBJ_REMOVE );
1173+ glue_dir = get_glue_dir (dev );
11571174 kobject_del (& dev -> kobj );
11581175 Error :
1159- cleanup_device_parent (dev );
1176+ cleanup_glue_dir (dev , glue_dir );
11601177 put_device (parent );
11611178name_error :
11621179 kfree (dev -> p );
@@ -1232,6 +1249,7 @@ EXPORT_SYMBOL_GPL(put_device);
12321249void device_del (struct device * dev )
12331250{
12341251 struct device * parent = dev -> parent ;
1252+ struct kobject * glue_dir = NULL ;
12351253 struct class_interface * class_intf ;
12361254
12371255 /* Notify clients of device removal. This call must come
@@ -1276,8 +1294,9 @@ void device_del(struct device *dev)
12761294 blocking_notifier_call_chain (& dev -> bus -> p -> bus_notifier ,
12771295 BUS_NOTIFY_REMOVED_DEVICE , dev );
12781296 kobject_uevent (& dev -> kobj , KOBJ_REMOVE );
1279- cleanup_device_parent (dev );
1297+ glue_dir = get_glue_dir (dev );
12801298 kobject_del (& dev -> kobj );
1299+ cleanup_glue_dir (dev , glue_dir );
12811300 put_device (parent );
12821301}
12831302EXPORT_SYMBOL_GPL (device_del );
0 commit comments