How does the probe function gets called on a PCI device driver?

Henrique Montenegro typoon at gmail.com
Sat Jan 30 17:54:00 EST 2016


Thanks Bjørn! I will investigate this better and see if I can understand it
better. I really appreciate the pointers!

Henrique

On Sat, Jan 30, 2016 at 2:41 PM, Bjørn Mork <bjorn at mork.no> wrote:

> Henrique Montenegro <typoon at gmail.com> writes:
>
> > Hello list,
> >
> > I am reading through the e1000 driver and trying to figure out how the
> > probe function on it gets called.
> >
> > The driver initialization function calls pci_register_driver:
> >
> >
> ----------------------------------------------------------------------------->8
> > static struct pci_driver e1000_driver = {
> > .name     = e1000_driver_name,
> > .id_table = e1000_pci_tbl,
> > .probe    = e1000_probe,
> > .remove   = e1000_remove,
> >     // ...
> > };
> >
> > static int __init e1000_init_module(void)
> > {
> >     // ...
> > ret = pci_register_driver(&e1000_driver);
> >     // ...
> > }
> >
> ----------------------------------------------------------------------------->8
> >
> > And pci_register_driver is defined as (on linux/pci.h):
> >
> >
> ----------------------------------------------------------------------------->8
> > #define pci_register_driver(driver)             \
> >          __pci_register_driver(driver, THIS_MODULE, KBUILD_MODNAME)
> >
> ----------------------------------------------------------------------------->8
> >
> > Function __pci_register_driver is defined as (drivers/pci/pci-driver.c):
> >
> >
> ----------------------------------------------------------------------------->8
> > int __pci_register_driver(struct pci_driver *drv, struct module *owner,
> >                           const char *mod_name)
> > {
> >         /* initialize common driver fields */
> >         drv->driver.name = drv->name;
> >         drv->driver.bus = &pci_bus_type;
> >         drv->driver.owner = owner;
> >         drv->driver.mod_name = mod_name;
> >
> >         spin_lock_init(&drv->dynids.lock);
> >         INIT_LIST_HEAD(&drv->dynids.list);
> >
> >         /* register with core */
> >         return driver_register(&drv->driver);
> > }
> > EXPORT_SYMBOL(__pci_register_driver);
> >
> ----------------------------------------------------------------------------->8
> >
> > This is the point where I am getting lost. I can't figure out how the
> Kernel
> > will know about the functions defined in the e1000_driver struct
> mentioned
> > before, since it does not seem to pass a reference to it anywhere.
> >
> > How does the kernel know where the probe function for this module is in
> this
> > case? To be honest, for any driver that calls pci_register_driver, how
> will
> > the
> > kernel know where the probe function is since it does not seem like it is
> > being passed to driver_register?
>
> The magic is in the 'drv->driver.bus = &pci_bus_type;' assigment.  This
> is where the driver core will look for functions knowing how to handle
> this specific driver.  See Documentation/driver-model/bus.txt etc
>
> Look at the defintion of pci_bus_type in  drivers/pci/pci-driver.c :
>
> struct bus_type pci_bus_type = {
>         .name           = "pci",
>         .match          = pci_bus_match,
>         .uevent         = pci_uevent,
>         .probe          = pci_device_probe,
>         .remove         = pci_device_remove,
>         .shutdown       = pci_device_shutdown,
>         .dev_groups     = pci_dev_groups,
>         .bus_groups     = pci_bus_groups,
>         .drv_groups     = pci_drv_groups,
>         .pm             = PCI_PM_OPS_PTR,
> };
> EXPORT_SYMBOL(pci_bus_type);
>
> And then look at the different callbacks.  These explain how the generic
> &drv->driver above is turned back into a pci_driver on probing:
>
> static int pci_device_probe(struct device *dev)
> {
>         int error;
>         struct pci_dev *pci_dev = to_pci_dev(dev);
>         struct pci_driver *drv = to_pci_driver(dev->driver);
>
>
> to_pci_dev() and to_pci_driver() are just macros simplifying the usual
> container_of trick.  From include/linux/pci.h :
>
> #define to_pci_dev(n) container_of(n, struct pci_dev, dev)
> ..
> #define to_pci_driver(drv) container_of(drv, struct pci_driver, driver)
>
>
>
> Hope this helps.
>
>
> Bjørn
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://lists.kernelnewbies.org/pipermail/kernelnewbies/attachments/20160130/109aac9e/attachment.html 


More information about the Kernelnewbies mailing list