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