driver,bus,device

无论是device还是driver都注册到bus总线上,bus负责driver和device的匹配

device1
device2
device3
bus
driver1
driver2
driver3

bus的结构体如下所示:

struct bus_type 
	const char		*name;       //总线的名字
	const char		*dev_name;
	struct device		*dev_root;
	struct device_attribute	*dev_attrs;	/* use dev_groups instead */
	const struct attribute_group **bus_groups;
	const struct attribute_group **dev_groups;
	const struct attribute_group **drv_groups;
	int (*match)(struct device *dev, struct device_driver *drv);   //匹配设备和驱动的函数
	int (*uevent)(struct device *dev, struct kobj_uevent_env *env);
	int (*probe)(struct device *dev);								//如果设备和驱动匹配成功,则会调用此函数,这个函数由
																	//struct device_driver里面的probe函数实现,bus里面
																	//probe最后会调用device_driver里面的probe函数。
																	//这个函数用来初始化设备。这个函数Linux内核里面已经实现
	int (*remove)(struct device *dev);
	void (*shutdown)(struct device *dev);
	int (*online)(struct device *dev);
	int (*offline)(struct device *dev);
	int (*suspend)(struct device *dev, pm_message_t state);
	int (*resume)(struct device *dev);
	const struct dev_pm_ops *pm;
	const struct iommu_ops *iommu_ops;
	struct subsys_private *p;
	struct lock_class_key lock_key;
};

下面以platform总线为例,讲解总线的注册。

int __init platform_bus_init(void)

{
   int error;
   early_platform_cleanup();
   error = device_register(&platform_bus);
   if (error)
   	return error;
   error =  bus_register(&platform_bus_type); //这里调用总线的注册函数。
   if (error)
   	device_unregister(&platform_bus);
   of_platform_register_reconfig_notifier();
   return error;
}

主要看platform_bus_type结构体

struct bus_type platform_bus_type = {
   .name		= "platform",    //总线的名字
   .dev_groups	= platform_dev_groups,
   .match		= platform_match,  //总线的匹配函数
   .uevent		= platform_uevent,	
   .pm		= &platform_dev_pm_ops,
;

platform_match函数原型如下:

static int platform_match(struct device *dev, struct device_driver *drv)

{
	return (strcmp(pdev->name, drv->name) == 0);
}

从上面可以看出,platform总线是通过设备和驱动的名字来实现匹配的。

内核实现的probe函数如下:

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_get_suppliers(dev);
   if (dev->parent)
   	pm_runtime_get_sync(dev->parent);
   pm_runtime_barrier(dev);
   ret = really_probe(dev, drv); //调用驱动中的probe函数.
   pm_request_idle(dev);
   if (dev->parent)
   	pm_runtime_put(dev->parent);
   pm_runtime_put_suppliers(dev);
   return ret;
}

really_probe函数中调用驱动中的probe函数的源码:

   if (dev->bus->probe) {  //platform总线的bus中的probe为空
   	ret = dev->bus->probe(dev);
   	if (ret)
   		goto probe_failed;

   } else if (drv->probe) { //drv->probe的条件满足,所以调用drv中probe
   	ret = drv->probe(dev);
   	if (ret)
   		goto probe_failed;
   }

2.设备device

设备device的结构体如下所示:

struct device {

   struct device		*parent;//父设备
   struct device_private	*p;//设备的私有数据
   struct kobject kobj;		//表示该设备并把它链接到设备模型中的kobject中
	const char		*init_name; /* initial name of the device */
	const struct device_type *type; //设备的类型
	struct mutex		mutex;	/* mutex to synchronize calls to
					 * its driver.
					 */
	struct bus_type	*bus;		/* type of bus device is on设备链接到那个总线上*/
	struct device_driver *driver;	/* 管理该设备的驱动which driver has allocated this device */
	void		*platform_data;	/* 平台的特有数据Platform specific data, device core doesn't touch it */
	void		*driver_data;	/* 驱动的特有数据Driver data, set and get with dev_set/get_drvdata */
	struct dev_links_info	links;
	struct dev_pm_info	power; 
	struct dev_pm_domain	*pm_domain;

#ifdef CONFIG_GENERIC_MSI_IRQ_DOMAIN
	struct irq_domain	*msi_domain;
#endif
    
#ifdef CONFIG_PINCTRL
	struct dev_pin_info	*pins;
#endif

#ifdef CONFIG_GENERIC_MSI_IRQ
	struct list_head	Smsi_list;
#endif

#ifdef CONFIG_NUMA
   int		numa_node;	/* NUMA node this device is close to */
#endif
   u64		*dma_mask;	/* dma mask (if dma'able device) */
   u64		coherent_dma_mask;/* Like dma_mask, but for
   				   alloc_coherent mappings as
   			   not all hardware supports
   				   64 bit addresses for consistent
   				   allocations such descriptors. */
   unsigned long	dma_pfn_offset;
   struct device_dma_parameters *dma_parms;
   struct list_head	dma_pools;	/* dma pools (if dma'ble) */
   struct dma_coherent_mem	*dma_mem; /* internal for coherent mem
   				   override */
\#ifdef CONFIG_DMA_CMA

	struct cma *cma_area;		/* contiguous memory area for dma

					  allocations */
\#endif

	/* arch specific additions */
 	struct dev_archdata	archdata;
 	struct device_node	*of_node; /* associated device tree node */
 	struct fwnode_handle	*fwnode; /* firmware device node */
 	dev_t			devt;	/* dev_t, creates the sysfs "dev" */
 	u32			id;	/* device instance */
 	spinlock_t		devres_lock;
 	struct list_head	devres_head;
 	struct klist_node	knode_class;
 	struct class		*class; //指向所属的类
   const struct attribute_group **groups;	/* optional groups */
   void	(*release)(struct device *dev);
   struct iommu_group	*iommu_group;
	struct iommu_fwspec	*iommu_fwspec;
   bool			offline_disabled:1;
	bool			offline:1;

};

// 它一般作为一个基类,就像kobject一样,比如在struct platform_device中就包含了这个结构体。它包含了设备的基本信息,设备所属的bus、管理设备的驱动、设备的私有数据等内容。

// 设备device的API如下所示:

int device_register(struct device *dev)

{
   device_initialize(dev);			//初始化struct device	
   return device_add(dev);			//在内核中添加一个设备并在内核中建立目录层次结构,
}

int device_add(struct device *dev)

{
   dev = get_device(dev);	//struct device中的struct kobject引用计数+1
   if (!dev->p) {
   	error = device_private_init(dev); //dev->p->device = 
   }
   if (dev->init_name) {
   	dev_set_name(dev, "%s", dev->init_name);  //将名字赋值给struct device里面的kobject  
   	dev->init_name = NULL;
   }

   /* subsystems can specify simple device enumeration */
   if (!dev_name(dev) && dev->bus && dev->bus->dev_name)
   	dev_set_name(dev, "%s%u", dev->bus->dev_name, dev->id);

   if (!dev_name(dev)) {
   	error = -EINVAL;
   	goto name_error;
   }
   parent = get_device(dev->parent);//返回父节点,且父节点的引用计数+1
   kobj = get_device_parent(dev, parent);
   if (kobj)
   	dev->kobj.parent = kobj; //重新设计父节点

   /* use parent numa_node */

   if (parent && (dev_to_node(dev) == NUMA_NO_NODE))
 		set_dev_node(dev, dev_to_node(parent));
 	/* first, register with generic layer. */
 	/* we require the name to be set before, and pass NULL */
 	error = kobject_add(&dev->kobj, dev->kobj.parent, NULL); //建立文件夹
 	if (error) {
 		glue_dir = get_glue_dir(dev);
 		goto Error;
 	}
 	/* notify platform of device entry */
 	if (platform_notify)
   	platform_notify(dev);
 	error = device_create_file(dev, &dev_attr_uevent); //在dev所创建的文件夹下创建属性文件
 	if (error)
 		goto attrError;
	//建立subsystem链接文件到所属class   //sys文件夹下的目标文件夹建立软链接

   error = device_add_class_symlinks(dev);
	if (error)
 		goto SymlinkError;
 	//添加dev的属性描述文件
 	error = device_add_attrs(dev);
   if (error)
   	goto AttrsError;
   //添加链接文件到所属bus
   error = bus_add_device(dev);
   if (error)
   	goto BusError;
   error = dpm_sysfs_add(dev);
   if (error)
   	goto DPMError;
   device_pm_add(dev);

	if (MAJOR(dev->devt)) {
 		//建立设备的属性文件
 		error = device_create_file(dev, &dev_attr_dev);
		if (error)
   		goto DevAttrError;
   	error = device_create_sys_dev_entry(dev);
   	if (error)
   		goto SysEntryError;
   	devtmpfs_create_node(dev);
	}
   /* Notify clients of device addition.  This call must come
    * after dpm_sysfs_add() and before kobject_uevent().
    */
   if (dev->bus)
   	blocking_notifier_call_chain(&dev->bus->p->bus_notifier,
					   BUS_NOTIFY_ADD_DEVICE, dev);
   kobject_uevent(&dev->kobj, KOBJ_ADD);
   bus_probe_device(dev);		//检测驱动中有无适合的设备进行匹配,现在只添加了设备,还没有加载驱动,
   if (parent)
   	klist_add_tail(&dev->p->knode_parent,
   		    &parent->p->klist_children);
   if (dev->class) {
   	mutex_lock(&dev->class->p->mutex);
   	/* tie the class to the device */
   	klist_add_tail(&dev->knode_class,
   		    &dev->class->p->klist_devices);
   	/* notify any interfaces that the device is here */
   	list_for_each_entry(class_intf,
   			  &dev->class->p->interfaces, node)
   		if (class_intf->add_dev)
				class_intf->add_dev(dev, class_intf);
		mutex_unlock(&dev->class->p->mutex);
	}

}
void bus_probe_device(struct device *dev)

{
	struct bus_type *bus = dev->bus;
	struct subsys_interface *sif;
	if (!bus)
		return;
	if (bus->p->drivers_autoprobe)//设置了自动匹配初始化那么就开始匹配
		device_initial_probe(dev);
	mutex_lock(&bus->p->mutex);
	list_for_each_entry(sif, &bus->p->interfaces, node)
		if (sif->add_dev)
			sif->add_dev(dev, sif);
	mutex_unlock(&bus->p->mutex);

}



void device_initial_probe(struct device *dev)

{
	__device_attach(dev, true);
}
static int __device_attach(struct device *dev, bool allow_async)

{
	int ret = 0;
	device_lock(dev);
	if (dev->driver) {  //默认制定了driver就直接绑定
		if (device_is_bound(dev)) {
			ret = 1;
			goto out_unlock;
		}
		ret = device_bind_driver(dev);
		if (ret == 0)
			ret = 1;
		else {
			dev->driver = NULL;
			ret = 0;
		}
	} else {//如果没有就进行遍历
		struct device_attach_data data = {
			.dev = dev,
			.check_async = allow_async,
			.want_async = false,
		};
		if (dev->parent)
			pm_runtime_get_sync(dev->parent);
		ret = bus_for_each_drv(dev->bus, NULL, &data,
					__device_attach_driver);
		if (!ret && allow_async && data.have_async) {
			/*
			 * If we could not find appropriate driver
			 * synchronously and we are allowed to do
			 * async probes and there are drivers that
			 * want to probe asynchronously, we'll
			 * try them.
			 */
			dev_dbg(dev, "scheduling asynchronous probe\n");
			get_device(dev);
			async_schedule(__device_attach_async_helper, dev);
		} else {
			pm_request_idle(dev);
		}
		if (dev->parent)
			pm_runtime_put(dev->parent);
	}
out_unlock:
	device_unlock(dev);
	return ret;
}
static int __device_attach_driver(struct device_driver *drv, void *_data)
{
	struct device_attach_data *data = _data;
	struct device *dev = data->dev;
	bool async_allowed;
	int ret;
	/*
	 * Check if device has already been claimed. This may
	 * happen with driver loading, device discovery/registration,
	 * and deferred probe processing happens all at once with
	 * multiple threads.
	 */

	if (dev->driver)
		return -EBUSY;
	ret = driver_match_device(drv, dev); //内核写的设备和驱动的匹配函数
	if (ret == 0) {
		/* no match */
		return 0;
	} else if (ret == -EPROBE_DEFER) {
		dev_dbg(dev, "Device match requests probe deferral\n");
		driver_deferred_probe_add(dev);
	} else if (ret < 0) {
		dev_dbg(dev, "Bus failed to match device: %d", ret);
		return ret;
	} /* ret > 0 means positive match */
	async_allowed = driver_allows_async_probing(drv);
	if (async_allowed)
		data->have_async = true;
	if (data->check_async && async_allowed != data->want_async)
		return 0;
	return driver_probe_device(drv, dev);//内核写的探测函数,如果匹配成功就会执行此函数

}

匹配函数原型如下:

static inline int driver_match_device(struct device_driver *drv,
   			      struct device *dev)
{ 
   return drv->bus->match ? drv->bus->match(dev, drv) : 1; //bind driver_probe_device 
}

从里面可以看出,还是调用的bus注册时候的match函数。

探测函数原型如下:

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_get_suppliers(dev);
	if (dev->parent)
		pm_runtime_get_sync(dev->parent);
	pm_runtime_barrier(dev);
	if (initcall_debug)
		ret = really_probe_debug(dev, drv);
	else
		ret = really_probe(dev, drv); //really_probe
	pm_request_idle(dev);

	if (dev->parent)
		pm_runtime_put(dev->parent);

	pm_runtime_put_suppliers(dev);
	return ret;
}

static int really_probe(struct device *dev, struct device_driver *drv)
{
	ret = device_links_check_suppliers(dev);	//suppliers检查,仅在device的所有suppliers状态正常时才会触发probe
	if (ret == -EPROBE_DEFER)
		driver_deferred_probe_add_trigger(dev, local_trigger_count); 
	if (ret)
		return ret;    
    
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;
	}
}

在里面首先要检查驱动所需要的supplier是否正常,例如上下电,时钟等驱动,检查之后会调用bus注册时候的probe函数,如果没有则调用驱动中的函数。如果检查失败,驱动会延后再次触发driver_probe_device。

3.设备驱动driver

driver结构体如下所示:

struct device_driver {
	const char		*name;
	struct bus_type		*bus;
	struct module		*owner;
	const char		*mod_name;	/* used for built-in modules */
	bool suppress_bind_attrs;	/* disables bind/unbind via sysfs */
	enum probe_type probe_type;
	const struct of_device_id	*of_match_table;
	const struct acpi_device_id	*acpi_match_table;
	int (*probe) (struct device *dev);
	int (*remove) (struct device *dev);
	void (*shutdown) (struct device *dev);
	int (*suspend) (struct device *dev, pm_message_t state);
	int (*resume) (struct device *dev);
	const struct attribute_group **groups;
	const struct dev_pm_ops *pm;
	struct driver_private *p;

};

设备驱动的加载流程:

driver_register

​ bus_add_driver

​ driver_attach

​ bus_for_each_dev

​ __driver_attach

​ driver_match_device()

​ driver_probe_device

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值