1.1 问题简要分析
在学习I2c驱动的过程中,一直没有理解probe函数中的client是如何传入的,在这里记录并分享追踪源码的过程。
static int i2c_wds_probe(struct i2c_client *client, const struct i2c_device_id *id)
要明白这个问题,需要分析i2c_driver以及i2c_client的注册过程,接下来本文将详细分析i2c总线流程。
1.2 i2c_driver注册过程
static int __init i2c_wds_driver_init(void)
{
return i2c_add_driver(&i2c_wds_driver);
}
调用i2c_add_driver函数注册一个i2c设备驱动,我们可以追踪这个函数,看一下i2c_driver是如何注册到总线中。
/* use a define to avoid include chaining to get THIS_MODULE */
#define i2c_add_driver(driver) \
i2c_register_driver(THIS_MODULE, driver)
struct bus_type i2c_bus_type = {
.name = "i2c",
.match = i2c_device_match,
.probe = i2c_device_probe,
.remove = i2c_device_remove,
.shutdown = i2c_device_shutdown,
};
int i2c_register_driver(struct module *owner, struct i2c_driver *driver)
{
int res;
/* Can't register until after driver model init */
if (unlikely(WARN_ON(!i2c_bus_type.p)))
return -EAGAIN;
/* add the driver to the list of i2c drivers in the driver core */
driver->driver.owner = owner;
driver->driver.bus = &i2c_bus_type;
/* When registration returns, the driver core
* will have called probe() for all matching-but-unbound devices.
*/
res = driver_register(&driver->driver);
if (res)
return res;
pr_debug("i2c-core: driver [%s] registered\n", driver->driver.name);
INIT_LIST_HEAD(&driver->clients);
/* Walk the adapters that are already present */
i2c_for_each_dev(driver, __process_new_driver);
return 0;
}
driver->driver.bus = &i2c_bus_type; 此函数会将i2c_driver与i2c总线关联,关联的作用是可以在新设备注册到i2c总线时,i2c设备可以遍历并匹配总线上的驱动,后面我们还会分析这个问题,并且该总线结构体存在probe函数(请大家记住这点,后面分析会用到)。,进入到driver_register函数中。
int driver_register(struct device_driver *drv)
{
int ret;
struct device_driver *other;
.....
.....
.....
ret = bus_add_driver(drv);
....
return ret;
}
bus_add_driver(struct device_driver *drv)此函数会将i2c驱动注册到总线中,由于函数体太长,下面仅介绍重要代码段,进入到该函数找到 driver_attach(struct device_driver *drv)。
int driver_attach(struct device_driver *drv)
{
return bus_for_each_dev(drv->bus, NULL, drv, __driver_attach);
}
int bus_for_each_dev(struct bus_type *bus, struct device *start,
void *data, int (*fn)(struct device *, void *))
{
struct klist_iter i;
struct device *dev;
int error = 0;
if (!bus || !bus->p)
return -EINVAL;
klist_iter_init_node(&bus->p->klist_devices, &i,
(start ? &start->p->knode_bus : NULL));
while ((dev = next_device(&i)) && !error)
error = fn(dev, data);
klist_iter_exit(&i);
return error;
}
static int __driver_attach(struct device *dev, void *data)
{
struct device_driver *drv = data;
.....
if (!driver_match_device(drv, dev))
return 0;
if (dev->parent) /* Needed for USB */
device_lock(dev->parent);
device_lock(dev);
if (!dev->driver)
driver_probe_device(drv, dev);
device_unlock(dev);
if (dev->parent)
device_unlock(dev->parent);
return 0;
}
在bus_for_each_dev函数中遍历bus总线上的设备,并在__driver_attach函数中进行匹配,driver_match_device(drv, dev)匹配成功之后调用driver_probe_device(drv, dev)函数,进入到该函数中。
int driver_probe_device(struct device_driver *drv, struct device *dev)
{
int ret = 0;
if (!device_is_registered(dev))
return -ENODEV;
pr_debug("bus: '%s': %s: matched device %s with driver %s\n",
drv->bus->name, __func__, dev_name(dev), drv->name);
pm_runtime_barrier(dev);
ret = really_probe(dev, drv);
pm_request_idle(dev);
return ret;
}
匹配成功之后调用really_probe(dev, drv)函数,并传入匹配成功的i2c设备中的device和i2c驱动中的device_driver。进入到该函数,找到下面函数段:
.......
.......
.......
if (dev->bus->probe) {
ret = dev->bus->probe(dev);
if (ret)
goto probe_failed;
} else if (drv->probe) {
ret = drv->probe(dev);
if (ret)
goto probe_failed;
}
.......
.......
.......
根据代码可以知道如果总线上存在probe函数,优先调用总线中的probe函数。因此我们进入到总线中的probe函数中
static int i2c_device_probe(struct device *dev)
{
struct i2c_client *client = i2c_verify_client(dev);
struct i2c_driver *driver;
int status;
if (!client)
return 0;
if (!client->irq && dev->of_node) {
int irq = of_irq_get(dev->of_node, 0);
if (irq == -EPROBE_DEFER)
return irq;
if (irq < 0)
irq = 0;
client->irq = irq;
}
driver = to_i2c_driver(dev->driver);
if (!driver->probe || !driver->id_table)
return -ENODEV;
if (!device_can_wakeup(&client->dev))
device_init_wakeup(&client->dev,
client->flags & I2C_CLIENT_WAKE);
dev_dbg(dev, "probe\n");
status = of_clk_set_defaults(dev->of_node, false);
if (status < 0)
return status;
status = dev_pm_domain_attach(&client->dev, true);
if (status != -EPROBE_DEFER) {
status = driver->probe(client, i2c_match_id(driver->id_table,
client));
if (status)
dev_pm_domain_detach(&client->dev, true);
}
return status;
}
在代码中,首先根据传入的dev找到client结构体,再根据dev中绑定的驱动找到i2c_driver驱动结构体。然后通过driver->probe(client, i2c_match_id(driver->id_table, client))调用我们编写的i2c_driver中的probe函数,并将client传入。