1.总线bus
通常所说的总线都是cpu与设备之间通信的协议,就像两个地方,一个地方住着cpu,一个地方住着设备,总线就相当于CPU通过什么方式到达设备。(就像你要通过一个墓道,就要按照墓主人设计的方式过去,要不就会被暗器杀掉,永远也到达不了)。
但是,Linux里面的总线,我的理解就是连接设备和驱动,不是常规意义上的总线,最简单就是platform总线,它不是一个协议,它就是为了那些没有广义上协议(usb、spi、iic)的设备服务的。
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);
}
``
```c
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;
}
从里面可以看出,还是调用的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);
ret = really_probe(dev, drv); //真正的探测函数
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)
{
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;
}
}
在里面首先会调用bus注册时候的probe函数,如果没有则调用驱动中的函数。
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;
};
设备驱动的API:
driver_register
bus_add_driver
driver_attach
bus_for_each_dev
__driver_attach
driver_match_device
driver_probe_device
可以看到最后调用的还是内核所开放的接口,当然,上面文件夹、属性文件、链接文件都没有写出来。