Subject: Re: Drivers with interrupts as LKMs
To: None <tech-kern@netbsd.org>
From: Jeremy Gale <jgale.work@gmail.com>
List: tech-kern
Date: 01/24/2005 15:48:02
OK, I've got this 99% working. I can load the driver and use it.
Thanks very much for your help!

I only have one problem left. After loading/unloading once then
reloading the LKM I see errors like this:

Data modified on freelist: word 198 of object 0x800a0c00 size 1024 previous type
 bar (0x800a2230 != 0xdeadbeef)

This sometimes happens during a modstat, sometimes during unloading,
sometimes during ifconfig (the driver provides a network interface),
etc.

I think I must be forgetting to free or detach something. What should
get called first - the LKM detach function or the network interface
detach function? According to printfs, the LKM detach function seems
to get called first. Does this mean the memory is deallocated before
the interface is detached? (if_detach())

Here is what I'm doing in my detach functions, in order.

LKM detach:
config_detach()
config_cfattach_detach()
config_cfdriver_detach()

Network interface detach:
if_detach()
bus_space_unmap()

Am I missing anything obvious?

Thanks,
Jeremy

On Fri, 21 Jan 2005 03:55:15 +0100, Jachym Holecek <freza@liberouter.org> wrote:
> > Thanks for the help everyone. This is my first NetBSD driver so there
> > are a lot of gaps in my knowledge. Please excuse my ignorance.
> 
> No problem. For a first driver, I'd really recommend doing it the static
> way -- that's well documented, the interfaces are stable and it's easier.
> Unless you have to do an LKM, of course.
> 
> > > This scheme is independent of whether you work with an LKM or a compiled-in
> > > driver -- provided that the bus in question has a function to locate device
> > > on the bus (such as pci_find_device(9)).
> >
> > Do you mean the locators remain in the kernel config file even when
> > using the driver as an LKM?
> 
> No, in that case the kernel contains no information about your driver
> and you have to do everything manually. What I meant is that autoconf(9)
> does not make any difference between static vs. LKM drivers. Sorry if
> the wording was confusing.
> 
> > Do you avoid the driver from being statically compiled-in by just not
> > including the source in the *.files?
> 
> The files* are used only to supply information when config(8) is run.
> The kernel configuration file (${arch}/conf/${NAME}) decides what
> will be compiled into the kernel. You disable a driver just by commenting
> out relevant entry of ${arch}/conf/${NAME}.
> 
> In case of an LKM-only driver, you don't need to touch files* at all.
> 
> > I don't believe the bus does have such a function. There is a
> > v2opb_search but that just seems to be part of the standard autoconf
> > stuff. It fills in the OBP-specific attach args struct and then calls
> > config_match/attach.
> >
> > I'm not too interested in doing this correctly; I just want an LKM for
> > development. I'd be more than happy with the hack that Allen mentioned
> > - hardcoding the base address and irq number - I just don't know how
> > to do it.
> 
> Fill them into the attach args (you'll want to fill them anyway) and
> have foo_attach() just believe what the parent (you, really) says.
> Chances are you can "steal" most code from v2opb_search() -- but I
> haven't seen Wasabi's code.
> 
> > I guess I eventually need to call config_attach. I can fake out most
> > of the information but I still need things like pointers to the parent
> > bus.
> 
> You can obtain parent's "struct device *" like this (from kern_drvctl.c):
> 
> ===
>         struct device *d;
> 
>         TAILQ_FOREACH(d, &alldevs, dv_list) {
>                 if (!strcmp("opb0", d->dv_xname))
>                         /* got him */
> ===
> 
> Alternatively, if you have more opb instances (and if it's possible for
> any of them to be parent for your device), you could do something like
> (not tested):
> 
> ===
>         struct device *d;
>         int i;
> 
>         for (i = 0; i < opb_cd.cd_ndevs; i++)
>                 d = opb_cd.cd_devs[i];
>                 /* do something with d */
> ===
> 
> [And you're correct in that you need to call config_attach().]
> 
>         Regards,
>                 -- Jachym Holecek
>