1. 程式人生 > >關於platform_driver 是如何匹配 platform_device的和如何呼叫到platform_driver中的probe函式的研究

關於platform_driver 是如何匹配 platform_device的和如何呼叫到platform_driver中的probe函式的研究

在linux中platform平臺驅動又三大部分組成,第一是bus、第二是驅動、第三是裝置。

      第一匯流排也就是platform_bus,匯流排也是一種特殊的device,到底層下面還是要呼叫device_register來註冊該匯流排裝置,然後是用來註冊匯流排的屬性結構體 bus_type(platform_bus_type),至此platform平臺的匯流排已經準備好。具體介紹可以看我另一篇部落格。

      第二是裝置,platform_device,它的註冊流程是:platform_device_register(struct platform_device *pdev)->device_initialize(&pdev->dev)->platform_device_add(pdev)->pdev->dev.bus = &platform_bus_type->device_add(&pdev->dev)->把裝置掛在虛擬的platform bus下。

       第三是驅動,現在匯流排、裝置都準備好了,然後等著驅動來匹配裝置進行驅動,具體的驅動匹配裝置流程如下:

 1、

[cpp] view plaincopyprint?
  1. <SPAN style="FONT-SIZE: 16px">int platform_driver_register(struct platform_driver *drv)  
  2. {  
  3.     drv->driver.bus = &platform_bus_type;//驅動的匯流排型別指向platform_bus_type   
  4.     if (drv->probe)  
  5.         drv->driver.probe = platform_drv_probe;  
  6.     if (drv->remove)  
  7.         drv->driver.remove = platform_drv_remove;  
  8.     if (drv->shutdown)  
  9.         drv->driver.shutdown = platform_drv_shutdown;  
  10.     if (drv->suspend)  
  11.         drv->driver.suspend = platform_drv_suspend;  
  12.     if (drv->resume)  
  13.         drv->driver.resume = platform_drv_resume;  
  14.     return driver_register(&drv->driver);  
  15. }</SPAN>  
int platform_driver_register(struct platform_driver *drv)
{
	drv->driver.bus = &platform_bus_type;//驅動的匯流排型別指向platform_bus_type
	if (drv->probe)
		drv->driver.probe = platform_drv_probe;
	if (drv->remove)
		drv->driver.remove = platform_drv_remove;
	if (drv->shutdown)
		drv->driver.shutdown = platform_drv_shutdown;
	if (drv->suspend)
		drv->driver.suspend = platform_drv_suspend;
	if (drv->resume)
		drv->driver.resume = platform_drv_resume;
	return driver_register(&drv->driver);
}

 2、

[cpp] view plaincopyprint?
  1. <SPAN style="FONT-SIZE: 16px">int driver_register(struct device_driver *drv)  
  2. {  
  3.     int ret;  
  4.     struct device_driver *other;  
  5.     BUG_ON(!drv->bus->p);  
  6. //檢測匯流排的操作函式和驅動的操作函式是否同時存在,同時存在則提示使用匯流排提供的操作函式   
  7.     if ((drv->bus->probe && drv->probe) ||  
  8.         (drv->bus->remove && drv->remove) ||  
  9.         (drv->bus->shutdown && drv->shutdown))  
  10.         printk(KERN_WARNING "Driver '%s' needs updating - please use "  
  11.             "bus_type methods\n", drv->name);  
  12.     //查詢這個驅動是否已經在總線上註冊,並增加引用計數,若已經註冊,則返回提示資訊。   
  13.     other = driver_find(drv->name, drv->bus);  
  14.     if (other) {  
  15.     //如果已經被註冊,則返回提示錯誤並且減少引用計數。   
  16.         put_driver(other);  
  17.         printk(KERN_ERR "Error: Driver '%s' is already registered, "  
  18.             "aborting...\n", drv->name);  
  19.         return -EEXIST;  
  20.     }  
  21.     //若還沒有註冊,則在總線上註冊該驅動   
  22.     ret = bus_add_driver(drv);  
  23.     if (ret)  
  24.         return ret;  
  25.     ret = driver_add_groups(drv, drv->groups);  
  26.     if (ret)  
  27.         bus_remove_driver(drv);  
  28.     return ret;  
  29. }</SPAN>  
int driver_register(struct device_driver *drv)
{
	int ret;
	struct device_driver *other;

	BUG_ON(!drv->bus->p);
//檢測匯流排的操作函式和驅動的操作函式是否同時存在,同時存在則提示使用匯流排提供的操作函式
	if ((drv->bus->probe && drv->probe) ||
	    (drv->bus->remove && drv->remove) ||
	    (drv->bus->shutdown && drv->shutdown))
		printk(KERN_WARNING "Driver '%s' needs updating - please use "
			"bus_type methods\n", drv->name);
	//查詢這個驅動是否已經在總線上註冊,並增加引用計數,若已經註冊,則返回提示資訊。
	other = driver_find(drv->name, drv->bus);
	if (other) {
	//如果已經被註冊,則返回提示錯誤並且減少引用計數。
		put_driver(other);
		printk(KERN_ERR "Error: Driver '%s' is already registered, "
			"aborting...\n", drv->name);
		return -EEXIST;
	}
	//若還沒有註冊,則在總線上註冊該驅動
	ret = bus_add_driver(drv);
	if (ret)
		return ret;
	ret = driver_add_groups(drv, drv->groups);
	if (ret)
		bus_remove_driver(drv);
	return ret;
}


3、

[cpp] view plaincopyprint?
  1. <SPAN style="FONT-SIZE: 16px">int bus_add_driver(struct device_driver *drv)  
  2. {  
  3.     struct bus_type *bus;  
  4.     struct driver_private *priv;  
  5.     int error = 0;  
  6. //用於增加該bus所屬的頂層bus的kobject的引用計數,返回的是其所屬的頂層bus的指標。   
  7.     bus = bus_get(drv->bus);  
  8.     if (!bus)  
  9.         return -EINVAL;  
  10.     pr_debug("bus: '%s': add driver %s\n", bus->name, drv->name);  
  11.     priv = kzalloc(sizeof(*priv), GFP_KERNEL);  
  12.     if (!priv) {  
  13.         error = -ENOMEM;  
  14.         goto out_put_bus;  
  15.     }  
  16.     klist_init(&priv->klist_devices, NULL, NULL);  
  17.     //將這兩個結構體連線起來   
  18.     priv->driver = drv;  
  19.     drv->p = priv;  
  20. //指向頂層的bus的p->drivers_kset   
  21. //設定私有資料的父容器,在這一步中,設定了kset為platform下的drivers_kset結構,也就是drivers呢個目錄    
  22.     priv->kobj.kset = bus->p->drivers_kset;  
  23. //初始化kobj物件,設定容器操作集並建立相應的目錄,這裡由於沒有提供parent,所以會使用父容器中的kobj為父物件     
  24.     error = kobject_init_and_add(&priv->kobj, &driver_ktype, NULL,  
  25.                      "%s", drv->name);  
  26.     if (error)  
  27.         goto out_unregister;  
  28. //檢測所屬匯流排的drivers_autoprobe屬性是否為真      
  29.   //為真則進行與裝置的匹配,到這裡,就會與我們之前註冊的test_device連線上了,   
  30.   //至於如何連線,進行了什麼操作,將在別的文章中詳細描述    
  31.     if (drv->bus->p->drivers_autoprobe) {  
  32.         error = driver_attach(drv);  
  33.         if (error)  
  34.             goto out_unregister;  
  35.     }  
  36.     //掛載到所屬匯流排驅動連結串列上   
  37.     klist_add_tail(&priv->knode_bus, &bus->p->klist_drivers);  
  38.     module_add_driver(drv->owner, drv);  
  39. //建立uevent屬性檔案   
  40.     error = driver_create_file(drv, &driver_attr_uevent);  
  41.     if (error) {  
  42.         printk(KERN_ERR "%s: uevent attr (%s) failed\n",  
  43.             __func__, drv->name);  
  44.     }  
  45.     //建立裝置屬性檔案   
  46.     error = driver_add_attrs(bus, drv);  
  47.     if (error) {  
  48.         /* How the hell do we get out of this pickle? Give up */  
  49.         printk(KERN_ERR "%s: driver_add_attrs(%s) failed\n",  
  50.             __func__, drv->name);  
  51.     }  
  52.     error = add_bind_files(drv);  
  53.     if (error) {  
  54.         /* Ditto */  
  55.         printk(KERN_ERR "%s: add_bind_files(%s) failed\n",  
  56.             __func__, drv->name);  
  57.     }  
  58.     kobject_uevent(&priv->kobj, KOBJ_ADD);  
  59.     return 0;  
  60. out_unregister:  
  61.     kfree(drv->p);  
  62.     drv->p = NULL;  
  63.     kobject_put(&priv->kobj);  
  64. out_put_bus:  
  65.     bus_put(bus);  
  66.     return error;  
  67. }</SPAN>  
int bus_add_driver(struct device_driver *drv)
{
	struct bus_type *bus;
	struct driver_private *priv;
	int error = 0;
//用於增加該bus所屬的頂層bus的kobject的引用計數,返回的是其所屬的頂層bus的指標。
	bus = bus_get(drv->bus);
	if (!bus)
		return -EINVAL;

	pr_debug("bus: '%s': add driver %s\n", bus->name, drv->name);

	priv = kzalloc(sizeof(*priv), GFP_KERNEL);
	if (!priv) {
		error = -ENOMEM;
		goto out_put_bus;
	}
	klist_init(&priv->klist_devices, NULL, NULL);
	//將這兩個結構體連線起來
	priv->driver = drv;
	drv->p = priv;
//指向頂層的bus的p->drivers_kset
//設定私有資料的父容器,在這一步中,設定了kset為platform下的drivers_kset結構,也就是drivers呢個目錄 
	priv->kobj.kset = bus->p->drivers_kset;
//初始化kobj物件,設定容器操作集並建立相應的目錄,這裡由於沒有提供parent,所以會使用父容器中的kobj為父物件  
	error = kobject_init_and_add(&priv->kobj, &driver_ktype, NULL,
				     "%s", drv->name);
	if (error)
		goto out_unregister;
//檢測所屬匯流排的drivers_autoprobe屬性是否為真   
  //為真則進行與裝置的匹配,到這裡,就會與我們之前註冊的test_device連線上了,
  //至於如何連線,進行了什麼操作,將在別的文章中詳細描述 
	if (drv->bus->p->drivers_autoprobe) {
		error = driver_attach(drv);
		if (error)
			goto out_unregister;
	}
	//掛載到所屬匯流排驅動連結串列上
	klist_add_tail(&priv->knode_bus, &bus->p->klist_drivers);
	module_add_driver(drv->owner, drv);
//建立uevent屬性檔案
	error = driver_create_file(drv, &driver_attr_uevent);
	if (error) {
		printk(KERN_ERR "%s: uevent attr (%s) failed\n",
			__func__, drv->name);
	}
	//建立裝置屬性檔案
	error = driver_add_attrs(bus, drv);
	if (error) {
		/* How the hell do we get out of this pickle? Give up */
		printk(KERN_ERR "%s: driver_add_attrs(%s) failed\n",
			__func__, drv->name);
	}
	error = add_bind_files(drv);
	if (error) {
		/* Ditto */
		printk(KERN_ERR "%s: add_bind_files(%s) failed\n",
			__func__, drv->name);
	}

	kobject_uevent(&priv->kobj, KOBJ_ADD);
	return 0;
out_unregister:
	kfree(drv->p);
	drv->p = NULL;
	kobject_put(&priv->kobj);
out_put_bus:
	bus_put(bus);
	return error;
}

 4、驅動的匹配關鍵是上面函式中的

[cpp] view plaincopyprint?
  1. <SPAN style="FONT-SIZE: 16px">  if (drv->bus->p->drivers_autoprobe) {//drivers_autoprobe在初始化的時候定義為1,系統則會呼叫下面的driver_attach函式進行驅動與裝置的匹配   
  2.         error = driver_attach(drv);  
  3.         if (error)  
  4.             goto out_unregister;  
  5.     }</SPAN>  
	if (drv->bus->p->drivers_autoprobe) {//drivers_autoprobe在初始化的時候定義為1,系統則會呼叫下面的driver_attach函式進行驅動與裝置的匹配
		error = driver_attach(drv);
		if (error)
			goto out_unregister;
	}
[cpp] view plaincopyprint?
  1. <SPAN style="FONT-SIZE: 16px">int driver_attach(struct device_driver *drv)  
  2. {  
  3.     return bus_for_each_dev(drv->bus, NULL, drv, __driver_attach);  
  4. }</SPAN>  
int driver_attach(struct device_driver *drv)
{
	return bus_for_each_dev(drv->bus, NULL, drv, __driver_attach);
}
[cpp] view plaincopyprint?
  1. <SPAN style="FONT-SIZE: 16px"//bus_for_each_dev(drv->bus, NULL, drv, __driver_attach);   
  2. int bus_for_each_dev(struct bus_type *bus, struct device *start,  
  3.              void *data, int (*fn)(struct device *, void *))  
  4. {/* 
  5. struct klist_iter { 
  6.     struct klist        *i_klist; 
  7.     struct klist_node   *i_cur; 
  8. }; 
  9. */  
  10.     struct klist_iter i;  
  11.     struct device *dev;  
  12.     int error = 0;  
  13.     if (!bus)  
  14.         return -EINVAL;  
  15. //如果第三個引數不為空就增加引用計數   
  16.     klist_iter_init_node(&bus->p->klist_devices, &i,  
  17.                  (start ? &start->p->knode_bus : NULL));//一直是NULL   
  18. //經過上面的巨集之後,i實際上變成了i->i_klist=&bus->p->klist_devices,bus->p->klist_devices指向的是掛接在它上面的所有的裝置的指標                 
  19.     while ((dev = next_device(&i)) && !error)  
  20. //fu函式傳入的是device的指標和device_driver的指標,   
  21.         error = fn(dev, data);  
  22. //如果klist_iter_init_node第三個引數不為空則減少引用計數   
  23.     klist_iter_exit(&i);  
  24.     return error;  
  25. }</SPAN>  
 //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 {
	struct klist		*i_klist;
	struct klist_node	*i_cur;
};

*/
	struct klist_iter i;
	struct device *dev;
	int error = 0;

	if (!bus)
		return -EINVAL;
//如果第三個引數不為空就增加引用計數
	klist_iter_init_node(&bus->p->klist_devices, &i,
			     (start ? &start->p->knode_bus : NULL));//一直是NULL
//經過上面的巨集之後,i實際上變成了i->i_klist=&bus->p->klist_devices,bus->p->klist_devices指向的是掛接在它上面的所有的裝置的指標			     
	while ((dev = next_device(&i)) && !error)
//fu函式傳入的是device的指標和device_driver的指標,
		error = fn(dev, data);
//如果klist_iter_init_node第三個引數不為空則減少引用計數
	klist_iter_exit(&i);
	return error;
}

 //尋找到下一個裝置的節點

[cpp] view plaincopyprint?
  1. <SPAN style="FONT-SIZE: 16px">static struct device *next_device(struct klist_iter *i)  
  2. {  
  3.     struct klist_node *n = klist_next(i);  
  4.     struct device *dev = NULL;  
  5.     struct device_private *dev_prv;  
  6.     if (n) {  
  7.         dev_prv = to_device_private_bus(n);  
  8.         dev = dev_prv->device;  
  9.     }  
  10.     return dev;  
  11. }</SPAN>  
static struct device *next_device(struct klist_iter *i)
{
	struct klist_node *n = klist_next(i);
	struct device *dev = NULL;
	struct device_private *dev_prv;

	if (n) {
		dev_prv = to_device_private_bus(n);
		dev = dev_prv->device;
	}
	return dev;
}

 函式error = fn(dev, data)的原型如下:

傳進來的引數第一個引數為不斷遍歷到的裝置節點的指標,第二個引數為固定的一個驅動所對應的struct device_driver *drv指標,這樣就實現驅動和裝置的匹配

[cpp] view plaincopyprint?
  1. <SPAN style="FONT-SIZE: 16px">static int __driver_attach(struct device *dev, void *data)  
  2. {  
  3.     struct device_driver *drv = data;  
  4.     /* 
  5.      * Lock device and try to bind to it. We drop the error 
  6.      * here and always return 0, because we need to keep trying 
  7.      * to bind to devices and some drivers will return an error 
  8.      * simply if it didn't support the device. 
  9.      * 
  10.      * driver_probe_device() will spit a warning if there 
  11.      * is an error. 
  12.      */  
  13. //當裝置和驅動的名字不匹配的時候返回的是0,然後就會呼叫下面的return 0;   
  14.     if (!driver_match_device(drv, dev))  
  15.         return 0;  
  16.     if (dev->parent) /* Needed for USB */  
  17.         down(&dev->parent->sem);  
  18.     down(&dev->sem);  
  19.     if (!dev->driver)  
  20.         driver_probe_device(drv, dev);//呼叫探測函式進行探測,並且呼叫platform_driver中的probe函式   
  21.     up(&dev->sem);  
  22.     if (dev->parent)  
  23.         up(&dev->parent->sem);  
  24.     return 0;  
  25. }  
  26. </SPAN>  
static int __driver_attach(struct device *dev, void *data)
{
	struct device_driver *drv = data;

	/*
	 * Lock device and try to bind to it. We drop the error
	 * here and always return 0, because we need to keep trying
	 * to bind to devices and some drivers will return an error
	 * simply if it didn't support the device.
	 *
	 * driver_probe_device() will spit a warning if there
	 * is an error.
	 */
//當裝置和驅動的名字不匹配的時候返回的是0,然後就會呼叫下面的return 0;
	if (!driver_match_device(drv, dev))
		return 0;

	if (dev->parent)	/* Needed for USB */
		down(&dev->parent->sem);
	down(&dev->sem);
	if (!dev->driver)
		driver_probe_device(drv, dev);//呼叫探測函式進行探測,並且呼叫platform_driver中的probe函式
	up(&dev->sem);
	if (dev->parent)
		up(&dev->parent->sem);

	return 0;
}


在上面有兩個比較關鍵的函式driver_match_device(dre,dev),函式原型如下:

[cpp] view plaincopyprint?
  1. <SPAN style="FONT-SIZE: 16px">static inline int driver_match_device(struct device_driver *drv,  
  2.                       struct device *dev)  
  3. {  
  4.     return drv->bus->match ? drv->bus->match(dev, drv) : 1;//無論裝置與驅動是否匹配成功都會返回1   
  5. }</SPAN>  
static inline int driver_match_device(struct device_driver *drv,
				      struct device *dev)
{
	return drv->bus->match ? drv->bus->match(dev, drv) : 1;//無論裝置與驅動是否匹配成功都會返回1
}

當驅動的指標不為空的時候,這個drv->bus所指向的的這個驅動所屬的的匯流排的bus_type中的match函式,然後傳進去的是該驅動的指標和裝置的指標

[cpp] view plaincopyprint?
  1. <SPAN style="FONT-SIZE: 16px">static int platform_match(struct device *dev, struct device_driver *drv)  
  2. {  
  3.     struct platform_device *pdev = to_platform_device(dev);  
  4.     struct platform_driver *pdrv = to_platform_driver(drv);  
  5.     /* match against the id table first */  
  6.     if (pdrv->id_table)//為空,不會被呼叫   
  7.         return platform_match_id(pdrv->id_table, pdev) != NULL;  
  8.     /* fall-back to driver name match */  
  9.     return (strcmp(pdev->name, drv->name) == 0);  
  10. }</SPAN>  
static int platform_match(struct device *dev, struct device_driver *drv)
{
	struct platform_device *pdev = to_platform_device(dev);
	struct platform_driver *pdrv = to_platform_driver(drv);

	/* match against the id table first */
	if (pdrv->id_table)//為空,不會被呼叫
		return platform_match_id(pdrv->id_table, pdev) != NULL;

	/* fall-back to driver name match */
	return (strcmp(pdev->name, drv->name) == 0);
}


最後呼叫驅動的probe函式進行裝置的探測

driver_probe_device(drv, dev);//呼叫探測函式進行探測,並且呼叫platform_driver中的probe函式

[cpp] view plaincopyprint?
  1. <SPAN style="FONT-SIZE: 16px">int driver_probe_device(struct device_driver *drv, struct device *dev)  
  2. {  
  3.     int ret = 0;  
  4. //再次檢查裝置有沒有在總線上註冊,當發現還沒有註冊的時候,返回一個錯誤   
  5.     if (!device_is_registered(dev))  
  6.         return -ENODEV;  
  7.     pr_debug("bus: '%s': %s: matched device %s with driver %s\n",  
  8.          drv->bus->name, __func__, dev_name(dev), drv->name);  
  9.     ret = really_probe(dev, drv);  
  10.     return ret;  
  11. }</SPAN>  
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);

	ret = really_probe(dev, drv);

	return ret;
}
[cpp] view plaincopyprint?
  1. <SPAN style="FONT-SIZE: 16px">static int really_probe(struct device *dev, struct device_driver *drv)  
  2. {  
  3.     int ret = 0;  
  4.     atomic_inc(&probe_count);  
  5.     pr_debug("bus: '%s': %s: probing driver %s with device %s\n",  
  6.          drv->bus->name, __func__, drv->name, dev_name(dev));  
  7.     WARN_ON(!list_empty(&dev->devres_head));  
  8. //找到了裝置的驅動,並且將dev->driver指標指向自己的這個驅動   
  9.     dev->driver = drv;  
  10.     if (driver_sysfs_add(dev)) {//在sys目錄下建立連線指向自己的在sys中的drivers   
  11.         printk(KERN_ERR "%s: driver_sysfs_add(%s) failed\n",  
  12.             __func__, dev_name(dev));  
  13.         goto probe_failed;  
  14.     }  
  15. //在bus_type  platform_bus_type中並沒有設定probe函式,所以下面函式並不會被呼叫   
  16.     if (dev->bus->probe) {  
  17.         ret = dev->bus->probe(dev);  
  18.         if (ret)  
  19.             goto probe_failed;  
  20.     } else if (drv->probe) {//上面匯流排沒有probe函式,所以直接呼叫驅動當中的probe函式   
  21.         ret = drv->probe(dev);  
  22.         if (ret)  
  23.             goto probe_failed;  
  24.     }  
  25.     driver_bound(dev);  
  26.     ret = 1;  
  27.     pr_debug("bus: '%s': %s: bound device %s to driver %s\n",  
  28.          drv->bus->name, __func__, dev_name(dev), drv->name);  
  29.     goto done;  
  30. probe_failed:  
  31.     devres_release_all(dev);  
  32.     driver_sysfs_remove(dev);  
  33.     dev->driver = NULL;  
  34.     if (ret != -ENODEV && ret != -ENXIO) {  
  35.         /* driver matched but the probe failed */  
  36.         printk(KERN_WARNING  
  37.                "%s: probe of %s failed with error %d\n",  
  38.                drv->name, dev_name(dev), ret);  
  39.     }  
  40.     /* 
  41.      * Ignore errors returned by ->probe so that the next driver can try 
  42.      * its luck. 
  43.      */  
  44.     ret = 0;  
  45. done:  
  46.     atomic_dec(&probe_count);  
  47.     wake_up(&probe_waitqueue);  
  48.     return ret;  
  49. }</SPAN>  
static int really_probe(struct device *dev, struct device_driver *drv)
{
	int ret = 0;

	atomic_inc(&probe_count);
	pr_debug("bus: '%s': %s: probing driver %s with device %s\n",
		 drv->bus->name, __func__, drv->name, dev_name(dev));
	WARN_ON(!list_empty(&dev->devres_head));
//找到了裝置的驅動,並且將dev->driver指標指向自己的這個驅動
	dev->driver = drv;
	if (driver_sysfs_add(dev)) {//在sys目錄下建立連線指向自己的在sys中的drivers
		printk(KERN_ERR "%s: driver_sysfs_add(%s) failed\n",
			__func__, dev_name(dev));
		goto probe_failed;
	}
//在bus_type  platform_bus_type中並沒有設定probe函式,所以下面函式並不會被呼叫
	if (dev->bus->probe) {
		ret = dev->bus->probe(dev);
		if (ret)
			goto probe_failed;
	} else if (drv->probe) {//上面匯流排沒有probe函式,所以直接呼叫驅動當中的probe函式
		ret = drv->probe(dev);
		if (ret)
			goto probe_failed;
	}

	driver_bound(dev);
	ret = 1;
	pr_debug("bus: '%s': %s: bound device %s to driver %s\n",
		 drv->bus->name, __func__, dev_name(dev), drv->name);
	goto done;

probe_failed:
	devres_release_all(dev);
	driver_sysfs_remove(dev);
	dev->driver = NULL;

	if (ret != -ENODEV && ret != -ENXIO) {
		/* driver matched but the probe failed */
		printk(KERN_WARNING
		       "%s: probe of %s failed with error %d\n",
		       drv->name, dev_name(dev), ret);
	}
	/*
	 * Ignore errors returned by ->probe so that the next driver can try
	 * its luck.
	 */
	ret = 0;
done:
	atomic_dec(&probe_count);
	wake_up(&probe_waitqueue);
	return ret;
}

        至此platform_driver的probe函式實現了呼叫並且匹配了platform_device