Linux驅動中probe函式的執行
這裡以static int__devinit sst25l_probe(struct spi_device *spi)為例看看傳遞進的引數structspi_device *spi到底是什麼,在哪定義,什麼時候定義,定義了有什麼用…?(本著“five W and H”的原則打破沙鍋問到底)。首先struct spi_device *spi不是我們定義的驅動裡定義的;其次在read,write等函式裡都有struct spi_device *spi的影子,不過不是直接傳遞進去的,而是通過傳遞進去struct mtd_info *mtd,然後to_sst25l_flash(mtd),即container_of()出包含mtd的struct sst25l_flash *flash,其中flash裡的第一個成員就是structspi_device *spi,而此成員的賦值就是將傳遞給probe中的struct spi_device *spi賦值給struct sst25l_flash *flash的,有程式碼為證:
static int __devinit sst25l_probe(structspi_device *spi)
{
structflash_info *flash_info;
structsst25l_flash *flash;
……
flash->spi = spi;// 將structspi_device *spi賦值給struct sst25l_flash *flash
mutex_init(&flash->lock);
dev_set_drvdata(&spi->dev,flash);// &spi->dev ->p->driver_data = flash保持flash
……
}
所以搞清楚structspi_device *spi的來源是搞清楚裝置驅動與主控驅動的聯絡紐帶的關鍵之一,當然要首先搞清楚probe函式什麼時候呼叫才能搞清楚struct spi_device *spi怎麼傳遞的,其重要性不言而喻(雖然言了很多,^-^,有點唐僧了)。我們先從驅動的init開始入手,畢竟這是驅動註冊開始的地方,也是一系列後續操作引發的地方:
static int __init sst25l_init(void)
{
returnspi_register_driver(&sst25l_driver);
}
裡面只有一個函式,最喜歡這樣的函數了:
int spi_register_driver(struct spi_driver*sdrv)
{
sdrv->driver.bus= &spi_bus_type;
if(sdrv->probe)
sdrv->driver.probe= spi_drv_probe;
if(sdrv->remove)
sdrv->driver.remove= spi_drv_remove;
if(sdrv->shutdown)
sdrv->driver.shutdown= spi_drv_shutdown;
return driver_register(&sdrv->driver);
}
前面都是賦值,直接最後一個語句:
int driver_register(struct device_driver*drv)
{
intret;
structdevice_driver *other;
……
ret = bus_add_driver(drv);
if(ret)
returnret;
ret= driver_add_groups(drv, drv->groups);
if(ret)
bus_remove_driver(drv);
returnret;
}
bus_add_driver(drv)看著就像“好人”:
int bus_add_driver(struct device_driver*drv)
{
structbus_type *bus;
structdriver_private *priv;
interror = 0;
……
if(drv->bus->p->drivers_autoprobe) {
error= driver_attach(drv);
if(error)
goto out_unregister;
}
……
}
driver_attach看著也很“友善”(函式名中帶get,init的一般都不是,如果裡面有幾個“友善”的,一首歌中已經告訴了我們解決的辦法:“xx就像偶爾撥不通的電話號碼,多試幾次總會回答,……”,如果網上找不到,只好挨個跟蹤了,我就這樣找的,笨人只好採取笨辦法,也是沒有辦法的辦法了):
int driver_attach(struct device_driver*drv)
{
returnbus_for_each_dev(drv->bus, NULL, drv, __driver_attach);
}
裡面只有一個函式,goon:
int bus_for_each_dev(struct bus_type *bus,struct device *start, void *data, int (*fn)(struct device *, void *))
{
structklist_iter i;
structdevice *dev;
interror = 0;
if(!bus)
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);
returnerror;
}
看到這裡好像沒有我們想要找的attach,只執行了個fn()函式,腫麼回事?到回頭看看哪裡漏了,在bus_for_each_dev中傳遞了個 __driver_attach,也就是在bus_for_each_dev執行了__driver_attach(dev, data),那麼它裡面到底執行了什麼?
static int __driver_attach(struct device*dev, void *data)
{
structdevice_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);
return0;
}
有個driver_probe_device(drv,dev),繼續跟蹤:
int driver_probe_device(structdevice_driver *drv, struct device *dev)
{
intret = 0;
……
ret = really_probe(dev, drv);
pm_runtime_put_sync(dev);
returnret;
}
有個really_probe(dev,drv),linux神馬的就喜歡這樣,經常一個函式傳遞給另一函式,後一個函式就是在前一個函式前加“do_”、“really_”、“__”,還經常的就是巨集定義的或inline的。
static int really_probe(struct device *dev,struct device_driver *drv)
{
intret = 0;
……
if(dev->bus->probe) {
ret = dev->bus->probe(dev);
if(ret)
gotoprobe_failed;
}else if (drv->probe) {
ret = drv->probe(dev);
if(ret)
gotoprobe_failed;
}
……
returnret;
}
這裡如果有總線上的probe函式就呼叫匯流排的probe函式,如果沒有則呼叫drv的probe函式。
在static int__driver_attach(struct device *dev, void *data)中先呼叫了driver_match_device(drv,dev),用於匹配,成功才繼續執行,否則直接返回了。driver_match_device(drv, dev)中:
static inline intdriver_match_device(struct device_driver *drv,
struct device *dev)
{
returndrv->bus->match ? drv->bus->match(dev, drv) : 1;
}
即如果match函式的指標不為空,則執行此bus的match函式,也就是為什麼資料上老是說匯流排負責匹配裝置和驅動了。這裡也傳遞了引數struct device *dev,到底這個dev來自何方,會在下一篇文章中繼續跟蹤。