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 16:19:18
Oops, ignore me. I found a few other things I needed to detach:

evcnt_detach()s
bpfdetach()
intr_disestablish()

Everything seems to be working now. Thanks again for the help. :)

Jeremy


On Mon, 24 Jan 2005 15:48:02 -0700, Jeremy Gale <jgale.work@gmail.com> wrote:
> 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
> >
>