Skip to content

Commit d3bad75

Browse files
committed
Merge tag 'driver-core-3.14-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/driver-core
Pull driver core / sysfs patches from Greg KH: "Here's the big driver core and sysfs patch set for 3.14-rc1. There's a lot of work here moving sysfs logic out into a "kernfs" to allow other subsystems to also have a virtual filesystem with the same attributes of sysfs (handle device disconnect, dynamic creation / removal as needed / unneeded, etc) This is primarily being done for the cgroups filesystem, but the goal is to also move debugfs to it when it is ready, solving all of the known issues in that filesystem as well. The code isn't completed yet, but all should be stable now (there is a big section that was reverted due to problems found when testing) There's also some other smaller fixes, and a driver core addition that allows for a "collection" of objects, that the DRM people will be using soon (it's in this tree to make merges after -rc1 easier) All of this has been in linux-next with no reported issues" * tag 'driver-core-3.14-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/driver-core: (113 commits) kernfs: associate a new kernfs_node with its parent on creation kernfs: add struct dentry declaration in kernfs.h kernfs: fix get_active failure handling in kernfs_seq_*() Revert "kernfs: fix get_active failure handling in kernfs_seq_*()" Revert "kernfs: replace kernfs_node->u.completion with kernfs_root->deactivate_waitq" Revert "kernfs: remove KERNFS_ACTIVE_REF and add kernfs_lockdep()" Revert "kernfs: remove KERNFS_REMOVED" Revert "kernfs: restructure removal path to fix possible premature return" Revert "kernfs: invoke kernfs_unmap_bin_file() directly from __kernfs_remove()" Revert "kernfs: remove kernfs_addrm_cxt" Revert "kernfs: make kernfs_get_active() block if the node is deactivated but not removed" Revert "kernfs: implement kernfs_{de|re}activate[_self]()" Revert "kernfs, sysfs, driver-core: implement kernfs_remove_self() and its wrappers" Revert "pci: use device_remove_file_self() instead of device_schedule_callback()" Revert "scsi: use device_remove_file_self() instead of device_schedule_callback()" Revert "s390: use device_remove_file_self() instead of device_schedule_callback()" Revert "sysfs, driver-core: remove unused {sysfs|device}_schedule_callback_owner()" Revert "kernfs: remove unnecessary NULL check in __kernfs_remove()" kernfs: remove unnecessary NULL check in __kernfs_remove() drivers/base: provide an infrastructure for componentised subsystems ...
2 parents 9f67627 + db4aad2 commit d3bad75

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

42 files changed

+4186
-2914
lines changed
Lines changed: 116 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,116 @@
1+
2+
Device Driver Design Patterns
3+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
4+
5+
This document describes a few common design patterns found in device drivers.
6+
It is likely that subsystem maintainers will ask driver developers to
7+
conform to these design patterns.
8+
9+
1. State Container
10+
2. container_of()
11+
12+
13+
1. State Container
14+
~~~~~~~~~~~~~~~~~~
15+
16+
While the kernel contains a few device drivers that assume that they will
17+
only be probed() once on a certain system (singletons), it is custom to assume
18+
that the device the driver binds to will appear in several instances. This
19+
means that the probe() function and all callbacks need to be reentrant.
20+
21+
The most common way to achieve this is to use the state container design
22+
pattern. It usually has this form:
23+
24+
struct foo {
25+
spinlock_t lock; /* Example member */
26+
(...)
27+
};
28+
29+
static int foo_probe(...)
30+
{
31+
struct foo *foo;
32+
33+
foo = devm_kzalloc(dev, sizeof(*foo), GFP_KERNEL);
34+
if (!foo)
35+
return -ENOMEM;
36+
spin_lock_init(&foo->lock);
37+
(...)
38+
}
39+
40+
This will create an instance of struct foo in memory every time probe() is
41+
called. This is our state container for this instance of the device driver.
42+
Of course it is then necessary to always pass this instance of the
43+
state around to all functions that need access to the state and its members.
44+
45+
For example, if the driver is registering an interrupt handler, you would
46+
pass around a pointer to struct foo like this:
47+
48+
static irqreturn_t foo_handler(int irq, void *arg)
49+
{
50+
struct foo *foo = arg;
51+
(...)
52+
}
53+
54+
static int foo_probe(...)
55+
{
56+
struct foo *foo;
57+
58+
(...)
59+
ret = request_irq(irq, foo_handler, 0, "foo", foo);
60+
}
61+
62+
This way you always get a pointer back to the correct instance of foo in
63+
your interrupt handler.
64+
65+
66+
2. container_of()
67+
~~~~~~~~~~~~~~~~~
68+
69+
Continuing on the above example we add an offloaded work:
70+
71+
struct foo {
72+
spinlock_t lock;
73+
struct workqueue_struct *wq;
74+
struct work_struct offload;
75+
(...)
76+
};
77+
78+
static void foo_work(struct work_struct *work)
79+
{
80+
struct foo *foo = container_of(work, struct foo, offload);
81+
82+
(...)
83+
}
84+
85+
static irqreturn_t foo_handler(int irq, void *arg)
86+
{
87+
struct foo *foo = arg;
88+
89+
queue_work(foo->wq, &foo->offload);
90+
(...)
91+
}
92+
93+
static int foo_probe(...)
94+
{
95+
struct foo *foo;
96+
97+
foo->wq = create_singlethread_workqueue("foo-wq");
98+
INIT_WORK(&foo->offload, foo_work);
99+
(...)
100+
}
101+
102+
The design pattern is the same for an hrtimer or something similar that will
103+
return a single argument which is a pointer to a struct member in the
104+
callback.
105+
106+
container_of() is a macro defined in <linux/kernel.h>
107+
108+
What container_of() does is to obtain a pointer to the containing struct from
109+
a pointer to a member by a simple subtraction using the offsetof() macro from
110+
standard C, which allows something similar to object oriented behaviours.
111+
Notice that the contained member must not be a pointer, but an actual member
112+
for this to work.
113+
114+
We can see here that we avoid having global pointers to our struct foo *
115+
instance this way, while still keeping the number of parameters passed to the
116+
work function to a single pointer.

Documentation/kobject.txt

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -342,7 +342,10 @@ kset use:
342342

343343
When you are finished with the kset, call:
344344
void kset_unregister(struct kset *kset);
345-
to destroy it.
345+
to destroy it. This removes the kset from sysfs and decrements its reference
346+
count. When the reference count goes to zero, the kset will be released.
347+
Because other references to the kset may still exist, the release may happen
348+
after kset_unregister() returns.
346349

347350
An example of using a kset can be seen in the
348351
samples/kobject/kset-example.c file in the kernel tree.

arch/x86/kernel/cpu/microcode/amd.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -433,7 +433,7 @@ static enum ucode_state request_microcode_amd(int cpu, struct device *device,
433433
if (c->x86 >= 0x15)
434434
snprintf(fw_name, sizeof(fw_name), "amd-ucode/microcode_amd_fam%.2xh.bin", c->x86);
435435

436-
if (request_firmware(&fw, (const char *)fw_name, device)) {
436+
if (request_firmware_direct(&fw, (const char *)fw_name, device)) {
437437
pr_debug("failed to load file %s\n", fw_name);
438438
goto out;
439439
}

arch/x86/kernel/cpu/microcode/intel.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -278,7 +278,7 @@ static enum ucode_state request_microcode_fw(int cpu, struct device *device,
278278
sprintf(name, "intel-ucode/%02x-%02x-%02x",
279279
c->x86, c->x86_model, c->x86_mask);
280280

281-
if (request_firmware(&firmware, name, device)) {
281+
if (request_firmware_direct(&firmware, name, device)) {
282282
pr_debug("data file %s load failed\n", name);
283283
return UCODE_NFOUND;
284284
}

drivers/base/Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# Makefile for the Linux device tree
22

3-
obj-y := core.o bus.o dd.o syscore.o \
3+
obj-y := component.o core.o bus.o dd.o syscore.o \
44
driver.o class.o platform.o \
55
cpu.o firmware.o init.o map.o devres.o \
66
attribute_container.o transport_class.o \

drivers/base/bus.c

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -146,8 +146,19 @@ void bus_remove_file(struct bus_type *bus, struct bus_attribute *attr)
146146
}
147147
EXPORT_SYMBOL_GPL(bus_remove_file);
148148

149+
static void bus_release(struct kobject *kobj)
150+
{
151+
struct subsys_private *priv =
152+
container_of(kobj, typeof(*priv), subsys.kobj);
153+
struct bus_type *bus = priv->bus;
154+
155+
kfree(priv);
156+
bus->p = NULL;
157+
}
158+
149159
static struct kobj_type bus_ktype = {
150160
.sysfs_ops = &bus_sysfs_ops,
161+
.release = bus_release,
151162
};
152163

153164
static int bus_uevent_filter(struct kset *kset, struct kobject *kobj)
@@ -953,8 +964,6 @@ void bus_unregister(struct bus_type *bus)
953964
kset_unregister(bus->p->devices_kset);
954965
bus_remove_file(bus, &bus_attr_uevent);
955966
kset_unregister(&bus->p->subsys);
956-
kfree(bus->p);
957-
bus->p = NULL;
958967
}
959968
EXPORT_SYMBOL_GPL(bus_unregister);
960969

0 commit comments

Comments
 (0)