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