On Friday 05 May 2006 01:55, Trent Piepho wrote: > On Thu, 4 May 2006, Andrew de Quincey wrote: > > There is one issue with using any of the methods in dvb_frontend_ops - > > the API is designed so that multiple devices can hook into the ops > > structure and override functions or even chain them - those methods > > aren't necessarily pointing at the demod module. It could be pointing at > > something else. In fact the lnbp21_attach() method does exactly this. > > That does throw a monkey wrench in my plan. > > How about this: > > The dvb_frontend struct gets a new field, 'module'. The FE attach function > sets it to THIS_MODULE, ie. it points to the FE module. After the card > driver calls the FE's release() method, it does a put on the module field > (it saves it before it calls release of course). If the FE attach function > is called without using dvb_attach() it doesn't matter, the module field is > set and then just ignored. > > This doesn't use symbol_put_addr() and doesn't use fe_ops either. Still > doesn't have any nice chaining ability. > > This means all the FEs have to add the module field and code to set it. > The first method didn't require the FEs to do anything, and if the kernel > was compiled without modules the whole attach/get/put business would just > automagically disappear. Yeah that would work for the single-module situation but as you say, it breaks the chaining.. hmm, maybe if we think along these lines we can come up with something. > > This is kinda why I am so keen on having the release() methods themselves > > do the counting; it would automatically tidy up these chained devices. > > Is there a race condition if that is done? If the card driver puts the > module after release, the module stays "locked" until nothing is using it > in any way. If the release() method puts itself, then the module is > "unlocked" while one of its methods is still executing. Maybe that's not a > problem and the kernel module unload code takes care of it? Hmm, that throws a monkey wrench into my plan as well :) OK... the release() method is only called from dvb_frontend.c/dvb_unregister_frontend(). What about something like this: each XXX_attach() method does the current behaviour - replace the current release() pointer and preserve the old pointer. When you call dvb_unregister_frontend(), it calls the the release() pointer as it does just now. This causes _only_ the last attached object to do whatever it has to. It then updates the release() pointer field with the previous release() pointer, and returns a THIS_MODULE pointer (or NULL). dvb_unregister_frontend can then decrement the module counter without having the possible race condition. Enclose that in a while loop, and you also support chaining... e.g.: while(fe->ops->release) { struct module *m = fe->ops->release(fe); if (m) module_put(m); } (the above is just a quick example; its probably got lots of errors :) _______________________________________________ linux-dvb@xxxxxxxxxxx http://www.linuxtv.org/cgi-bin/mailman/listinfo/linux-dvb