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

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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@xxxxxxx> wrote:
Henrique Montenegro <typoon@xxxxxxxxx> 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

_______________________________________________
Kernelnewbies mailing list
Kernelnewbies@xxxxxxxxxxxxxxxxx
http://lists.kernelnewbies.org/mailman/listinfo/kernelnewbies

[Index of Archives]     [Newbies FAQ]     [Linux Kernel Mentors]     [Linux Kernel Development]     [IETF Annouce]     [Git]     [Networking]     [Security]     [Bugtraq]     [Yosemite]     [MIPS Linux]     [ARM Linux]     [Linux RAID]     [Linux SCSI]     [Linux ACPI]
  Powered by Linux