diff options
-rw-r--r-- | Documentation/driver-model/design-patterns.txt | 116 |
1 files changed, 116 insertions, 0 deletions
diff --git a/Documentation/driver-model/design-patterns.txt b/Documentation/driver-model/design-patterns.txt new file mode 100644 index 000000000000..9ef8c1684558 --- /dev/null +++ b/Documentation/driver-model/design-patterns.txt | |||
@@ -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 a 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 a a 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. | ||