aboutsummaryrefslogtreecommitdiffstats
path: root/f1.patch
blob: 9ec82dbd94bf70ea346bd15f7a83ceabb2268ae9 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
#From foo@baz Tue Apr  9 12:12:43 2002
#Date: Thu, 01 Nov 2007 13:31:26 -0700
#To: Greg KH <greg@kroah.com>
#From: Greg Kroah-Hartman <gregkh@suse.de>
#Subject: driver core: remove fields from struct bus_type

DOES NOT BUILD AND IS NOT FULLY TESTED!!!

struct bus_type is static everywhere in the kernel.  This moves the
kobject in the structure out of it, and a bunch of other private only to
the driver core fields are now moved to a private structure.  This lets
us dynamically create the backing kobject properly and gives us the
chance to be able to document to users exactly how to use the struct
bus_type as there are no fields they can improperly access.

Cc: Kay Sievers <kay.sievers@vrfy.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>


---
 drivers/base/base.h    |   30 ++++++++++++-
 drivers/base/bus.c     |  110 ++++++++++++++++++++++++++++---------------------
 drivers/base/core.c    |    6 +-
 include/linux/device.h |   12 -----
 4 files changed, 97 insertions(+), 61 deletions(-)

--- a/drivers/base/base.h
+++ b/drivers/base/base.h
@@ -1,6 +1,34 @@
 
-/* initialisation functions */
+/**
+ * struct bus_type_private - structure to hold the private to the driver core portions of the bus_type structure.
+ *
+ * @subsys - the struct kset that defines this bus.  This is the main kobject
+ * @drivers_kset - the list of drivers associated with this bus
+ * @devices_kset - the list of devices associated with this bus
+ * @klist_devices - the klist to iterate over the @devices_kset
+ * @klist_drivers - the klist to iterate over the @drivers_kset
+ * @bus_notifier - the bus notifier list for anything that cares about things
+ * on this bus.
+ * @bus - pointer back to the struct bus_type that this structure is associated
+ * with.
+ *
+ * This structure is the one that is the actual kobject allowing struct
+ * bus_type to be statically allocated safely.  Nothing outside of the driver
+ * core should ever touch these fields.
+ */
+struct bus_type_private {
+	struct kset subsys;
+	struct kset *drivers_kset;
+	struct kset *devices_kset;
+	struct klist klist_devices;
+	struct klist klist_drivers;
+	struct blocking_notifier_head bus_notifier;
+	unsigned int drivers_autoprobe:1;
+	struct bus_type *bus;
+};
+
 
+/* initialisation functions */
 extern int devices_init(void);
 extern int buses_init(void);
 extern int classes_init(void);
--- a/drivers/base/bus.c
+++ b/drivers/base/bus.c
@@ -18,7 +18,7 @@
 #include "power/power.h"
 
 #define to_bus_attr(_attr) container_of(_attr, struct bus_attribute, attr)
-#define to_bus(obj) container_of(obj, struct bus_type, subsys.kobj)
+#define to_bus(obj) container_of(obj, struct bus_type_private, subsys.kobj)
 
 /*
  * sysfs bindings for drivers
@@ -33,13 +33,17 @@ static int __must_check bus_rescan_devic
 
 static struct bus_type *bus_get(struct bus_type *bus)
 {
-	return bus ? container_of(kset_get(&bus->subsys),
-				struct bus_type, subsys) : NULL;
+	if (bus) {
+		kset_get(&bus->p->subsys);
+		return bus;
+	}
+	return NULL;
 }
 
 static void bus_put(struct bus_type *bus)
 {
-	kset_put(&bus->subsys);
+	if (bus)
+		kset_put(&bus->p->subsys);
 }
 
 static ssize_t
@@ -105,11 +109,11 @@ static ssize_t
 bus_attr_show(struct kobject * kobj, struct attribute * attr, char * buf)
 {
 	struct bus_attribute * bus_attr = to_bus_attr(attr);
-	struct bus_type * bus = to_bus(kobj);
+	struct bus_type_private *bus_priv = to_bus(kobj);
 	ssize_t ret = 0;
 
 	if (bus_attr->show)
-		ret = bus_attr->show(bus, buf);
+		ret = bus_attr->show(bus_priv->bus, buf);
 	return ret;
 }
 
@@ -118,11 +122,11 @@ bus_attr_store(struct kobject * kobj, st
 	       const char * buf, size_t count)
 {
 	struct bus_attribute * bus_attr = to_bus_attr(attr);
-	struct bus_type * bus = to_bus(kobj);
+	struct bus_type_private *bus_priv = to_bus(kobj);
 	ssize_t ret = 0;
 
 	if (bus_attr->store)
-		ret = bus_attr->store(bus, buf, count);
+		ret = bus_attr->store(bus_priv->bus, buf, count);
 	return ret;
 }
 
@@ -135,7 +139,7 @@ int bus_create_file(struct bus_type * bu
 {
 	int error;
 	if (bus_get(bus)) {
-		error = sysfs_create_file(&bus->subsys.kobj, &attr->attr);
+		error = sysfs_create_file(&bus->p->subsys.kobj, &attr->attr);
 		bus_put(bus);
 	} else
 		error = -EINVAL;
@@ -145,7 +149,7 @@ int bus_create_file(struct bus_type * bu
 void bus_remove_file(struct bus_type * bus, struct bus_attribute * attr)
 {
 	if (bus_get(bus)) {
-		sysfs_remove_file(&bus->subsys.kobj, &attr->attr);
+		sysfs_remove_file(&bus->p->subsys.kobj, &attr->attr);
 		bus_put(bus);
 	}
 }
@@ -238,16 +242,16 @@ static DRIVER_ATTR(bind, S_IWUSR, NULL, 
 
 static ssize_t show_drivers_autoprobe(struct bus_type *bus, char *buf)
 {
-	return sprintf(buf, "%d\n", bus->drivers_autoprobe);
+	return sprintf(buf, "%d\n", bus->p->drivers_autoprobe);
 }
 
 static ssize_t store_drivers_autoprobe(struct bus_type *bus,
 				       const char *buf, size_t count)
 {
 	if (buf[0] == '0')
-		bus->drivers_autoprobe = 0;
+		bus->p->drivers_autoprobe = 0;
 	else
-		bus->drivers_autoprobe = 1;
+		bus->p->drivers_autoprobe = 1;
 	return count;
 }
 
@@ -301,7 +305,7 @@ int bus_for_each_dev(struct bus_type * b
 	if (!bus)
 		return -EINVAL;
 
-	klist_iter_init_node(&bus->klist_devices, &i,
+	klist_iter_init_node(&bus->p->klist_devices, &i,
 			     (start ? &start->knode_bus : NULL));
 	while ((dev = next_device(&i)) && !error)
 		error = fn(dev, data);
@@ -334,7 +338,7 @@ struct device * bus_find_device(struct b
 	if (!bus)
 		return NULL;
 
-	klist_iter_init_node(&bus->klist_devices, &i,
+	klist_iter_init_node(&bus->p->klist_devices, &i,
 			     (start ? &start->knode_bus : NULL));
 	while ((dev = next_device(&i)))
 		if (match(dev, data) && get_device(dev))
@@ -380,7 +384,7 @@ int bus_for_each_drv(struct bus_type * b
 	if (!bus)
 		return -EINVAL;
 
-	klist_iter_init_node(&bus->klist_drivers, &i,
+	klist_iter_init_node(&bus->p->klist_drivers, &i,
 			     start ? &start->knode_bus : NULL);
 	while ((drv = next_driver(&i)) && !error)
 		error = fn(drv, data);
@@ -450,12 +454,12 @@ int bus_add_device(struct device * dev)
 		error = device_add_attrs(bus, dev);
 		if (error)
 			goto out_put;
-		error = sysfs_create_link(&bus->devices_kset->kobj,
+		error = sysfs_create_link(&bus->p->devices_kset->kobj,
 						&dev->kobj, dev->bus_id);
 		if (error)
 			goto out_id;
 		error = sysfs_create_link(&dev->kobj,
-				&dev->bus->subsys.kobj, "subsystem");
+				&dev->bus->p->subsys.kobj, "subsystem");
 		if (error)
 			goto out_subsys;
 		error = make_deprecated_bus_links(dev);
@@ -467,7 +471,7 @@ int bus_add_device(struct device * dev)
 out_deprecated:
 	sysfs_remove_link(&dev->kobj, "subsystem");
 out_subsys:
-	sysfs_remove_link(&bus->devices_kset->kobj, dev->bus_id);
+	sysfs_remove_link(&bus->p->devices_kset->kobj, dev->bus_id);
 out_id:
 	device_remove_attrs(bus, dev);
 out_put:
@@ -493,7 +497,7 @@ void bus_attach_device(struct device * d
 			ret = device_attach(dev);
 		WARN_ON(ret < 0);
 		if (ret >= 0)
-			klist_add_tail(&dev->knode_bus, &bus->klist_devices);
+			klist_add_tail(&dev->knode_bus, &bus->p->klist_devices);
 		else
 			dev->is_registered = 0;
 	}
@@ -513,7 +517,7 @@ void bus_remove_device(struct device * d
 	if (dev->bus) {
 		sysfs_remove_link(&dev->kobj, "subsystem");
 		remove_deprecated_bus_links(dev);
-		sysfs_remove_link(&dev->bus->devices_kset->kobj, dev->bus_id);
+		sysfs_remove_link(&dev->bus->p->devices_kset->kobj, dev->bus_id);
 		device_remove_attrs(dev->bus, dev);
 		if (dev->is_registered) {
 			dev->is_registered = 0;
@@ -639,7 +643,7 @@ int bus_add_driver(struct device_driver 
 	error = kobject_set_name(&drv->kobj, "%s", drv->name);
 	if (error)
 		goto out_put_bus;
-	drv->kobj.kset = bus->drivers_kset;
+	drv->kobj.kset = bus->p->drivers_kset;
 	drv->kobj.ktype = &driver_ktype;
 	error = kobject_register(&drv->kobj);
 	if (error)
@@ -650,7 +654,7 @@ int bus_add_driver(struct device_driver 
 		if (error)
 			goto out_unregister;
 	}
-	klist_add_tail(&drv->knode_bus, &bus->klist_drivers);
+	klist_add_tail(&drv->knode_bus, &bus->p->klist_drivers);
 	module_add_driver(drv->owner, drv);
 
 	error = driver_create_file(drv, &driver_attr_uevent);
@@ -829,7 +833,7 @@ static ssize_t bus_uevent_store(struct b
 	enum kobject_action action;
 
 	if (kobject_action_type(buf, count, &action) == 0)
-		kobject_uevent(&bus->subsys.kobj, action);
+		kobject_uevent(&bus->p->subsys.kobj, action);
 	return count;
 }
 static BUS_ATTR(uevent, S_IWUSR, NULL, bus_uevent_store);
@@ -845,17 +849,25 @@ static BUS_ATTR(uevent, S_IWUSR, NULL, b
 int bus_register(struct bus_type * bus)
 {
 	int retval;
+	struct bus_type_private *priv;
+
+	priv = kzalloc(sizeof(struct bus_type_private), GFP_KERNEL);
+	if (!priv)
+		return -ENOMEM;
+
+	priv->bus = bus;
+	bus->p = priv;
 
-	BLOCKING_INIT_NOTIFIER_HEAD(&bus->bus_notifier);
+	BLOCKING_INIT_NOTIFIER_HEAD(&priv->bus_notifier);
 
-	retval = kobject_set_name(&bus->subsys.kobj, "%s", bus->name);
+	retval = kobject_set_name(&priv->subsys.kobj, "%s", bus->name);
 	if (retval)
 		goto out;
 
-	bus->subsys.kobj.kset = bus_kset;
-	bus->subsys.kobj.ktype = &bus_ktype;
+	priv->subsys.kobj.kset = bus_kset;
+	priv->subsys.kobj.ktype = &bus_ktype;
 
-	retval = subsystem_register(&bus->subsys);
+	retval = subsystem_register(&priv->subsys);
 	if (retval)
 		goto out;
 
@@ -863,22 +875,24 @@ int bus_register(struct bus_type * bus)
 	if (retval)
 		goto bus_uevent_fail;
 
-	bus->devices_kset = kset_create_and_register("devices", NULL,
-						     &bus->subsys.kobj, NULL);
-	if (IS_ERR(bus->devices_kset)) {
-		retval = PTR_ERR(bus->devices_kset);
+	priv->devices_kset = kset_create_and_register("devices", NULL,
+						      &priv->subsys.kobj,
+						      NULL);
+	if (IS_ERR(priv->devices_kset)) {
+		retval = PTR_ERR(priv->devices_kset);
 		goto bus_devices_fail;
 	}
 
-	bus->drivers_kset = kset_create_and_register("drivers", NULL,
-						     &bus->subsys.kobj, NULL);
-	if (IS_ERR(bus->drivers_kset)) {
-		retval = PTR_ERR(bus->drivers_kset);
+	priv->drivers_kset = kset_create_and_register("drivers", NULL,
+						      &priv->subsys.kobj,
+						      NULL);
+	if (IS_ERR(priv->drivers_kset)) {
+		retval = PTR_ERR(priv->drivers_kset);
 		goto bus_drivers_fail;
 	}
 
-	klist_init(&bus->klist_devices, klist_devices_get, klist_devices_put);
-	klist_init(&bus->klist_drivers, NULL, NULL);
+	klist_init(&priv->klist_devices, klist_devices_get, klist_devices_put);
+	klist_init(&priv->klist_drivers, NULL, NULL);
 
 	bus->drivers_autoprobe = 1;
 	retval = add_probe_files(bus);
@@ -895,13 +909,14 @@ int bus_register(struct bus_type * bus)
 bus_attrs_fail:
 	remove_probe_files(bus);
 bus_probe_files_fail:
-	kset_unregister(bus->drivers_kset);
+	kset_unregister(bus->p->drivers_kset);
 bus_drivers_fail:
-	kset_unregister(bus->devices_kset);
+	kset_unregister(bus->p->devices_kset);
 bus_devices_fail:
 	bus_remove_file(bus, &bus_attr_uevent);
 bus_uevent_fail:
-	subsystem_unregister(&bus->subsys);
+	subsystem_unregister(&bus->p->subsys);
+	kfree(bus->p);
 out:
 	return retval;
 }
@@ -918,21 +933,22 @@ void bus_unregister(struct bus_type * bu
 	pr_debug("bus %s: unregistering\n", bus->name);
 	bus_remove_attrs(bus);
 	remove_probe_files(bus);
-	kset_unregister(bus->drivers_kset);
-	kset_unregister(bus->devices_kset);
+	kset_unregister(bus->p->drivers_kset);
+	kset_unregister(bus->p->devices_kset);
 	bus_remove_file(bus, &bus_attr_uevent);
-	subsystem_unregister(&bus->subsys);
+	subsystem_unregister(&bus->p->subsys);
+	kfree(bus->p);
 }
 
 int bus_register_notifier(struct bus_type *bus, struct notifier_block *nb)
 {
-	return blocking_notifier_chain_register(&bus->bus_notifier, nb);
+	return blocking_notifier_chain_register(&bus->p->bus_notifier, nb);
 }
 EXPORT_SYMBOL_GPL(bus_register_notifier);
 
 int bus_unregister_notifier(struct bus_type *bus, struct notifier_block *nb)
 {
-	return blocking_notifier_chain_unregister(&bus->bus_notifier, nb);
+	return blocking_notifier_chain_unregister(&bus->p->bus_notifier, nb);
 }
 EXPORT_SYMBOL_GPL(bus_unregister_notifier);
 
--- a/drivers/base/core.c
+++ b/drivers/base/core.c
@@ -762,7 +762,7 @@ int device_add(struct device *dev)
 
 	/* notify clients of device entry (new way) */
 	if (dev->bus)
-		blocking_notifier_call_chain(&dev->bus->bus_notifier,
+		blocking_notifier_call_chain(&dev->bus->p->bus_notifier,
 					     BUS_NOTIFY_ADD_DEVICE, dev);
 
 	error = device_create_file(dev, &uevent_attr);
@@ -811,7 +811,7 @@ int device_add(struct device *dev)
 	device_pm_remove(dev);
  PMError:
 	if (dev->bus)
-		blocking_notifier_call_chain(&dev->bus->bus_notifier,
+		blocking_notifier_call_chain(&dev->bus->p->bus_notifier,
 					     BUS_NOTIFY_DEL_DEVICE, dev);
 	device_remove_attrs(dev);
  AttrsError:
@@ -990,7 +990,7 @@ void device_del(struct device * dev)
 	if (platform_notify_remove)
 		platform_notify_remove(dev);
 	if (dev->bus)
-		blocking_notifier_call_chain(&dev->bus->bus_notifier,
+		blocking_notifier_call_chain(&dev->bus->p->bus_notifier,
 					     BUS_NOTIFY_DEL_DEVICE, dev);
 	device_pm_remove(dev);
 	kobject_uevent(&dev->kobj, KOBJ_REMOVE);
--- a/include/linux/device.h
+++ b/include/linux/device.h
@@ -35,6 +35,7 @@ struct device_driver;
 struct class;
 struct class_device;
 struct bus_type;
+struct bus_type_private;
 
 struct bus_attribute {
 	struct attribute	attr;
@@ -51,15 +52,6 @@ extern void bus_remove_file(struct bus_t
 
 struct bus_type {
 	const char		* name;
-
-	struct kset		subsys;
-	struct kset		*drivers_kset;
-	struct kset		*devices_kset;
-	struct klist		klist_devices;
-	struct klist		klist_drivers;
-
-	struct blocking_notifier_head bus_notifier;
-
 	struct bus_attribute	* bus_attrs;
 	struct device_attribute	* dev_attrs;
 	struct driver_attribute	* drv_attrs;
@@ -75,7 +67,7 @@ struct bus_type {
 	int (*resume_early)(struct device * dev);
 	int (*resume)(struct device * dev);
 
-	unsigned int drivers_autoprobe:1;
+	struct bus_type_private *p;
 };
 
 extern int __must_check bus_register(struct bus_type * bus);