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