学习《Linux设备模型浅析之设备篇》笔记(三)
文件/drivers/base/core.c
static struct kobject *get_device_parent(struct device *dev,
struct device *parent)
{
if (dev->class) {
static DEFINE_MUTEX(gdp_mutex);
struct kobject *kobj = NULL;
struct kobject *parent_kobj;
struct kobject *k;
#ifdef CONFIG_BLOCK
/* block disks show up in /sys/block */
if (sysfs_deprecated && dev->class == &block_class) {
if (parent && parent->class == &block_class)
return &parent->kobj;
return &block_class.p->subsys.kobj;
}
#endif
/*
* 如果没有parent, 就放在"/sys/devices/virtual"下.
* Class-devices会把一个非class-device作为parent, 放在
* 一个"glue"目录下避免命名空间冲突.
*/
if (parent == NULL)
parent_kobj = virtual_device_parent(dev);
else if (parent->class && !dev->class->ns_type)
return &parent->kobj;
else
parent_kobj = &parent->kobj;
mutex_lock(&gdp_mutex);
/* 在parent下找到我们的class目录,并引用它*/
spin_lock(&dev->class->p->glue_dirs.list_lock);
list_for_each_entry(k, &dev->class->p->glue_dirs.list, entry)
if (k->parent == parent_kobj) {
kobj = kobject_get(k);
break;
}
spin_unlock(&dev->class->p->glue_dirs.list_lock);
if (kobj) {
mutex_unlock(&gdp_mutex);
return kobj;
}
/* 或在父设备下创建一个新的class目录 */
k = class_dir_create_and_add(dev->class, parent_kobj);
/* 不要为这个简单的“glue”目录发出uevent*/
mutex_unlock(&gdp_mutex);
return k;
}
/* 子系统可以为他们的设备指定一个默认的root目录 */
if (!parent && dev->bus && dev->bus->dev_root)
return &dev->bus->dev_root->kobj;
if (parent)
return &parent->kobj;
return NULL;
}
文件/drivers/base/core.c
static int device_add_class_symlinks(struct device *dev)
{
int error;
if (!dev->class)
return 0;
error = sysfs_create_link(&dev->kobj, &dev->class->p->subsys.kobj, "subsystem");
if (error)
goto out;
if (dev->parent && device_is_not_partition(dev)) {
error = sysfs_create_link(&dev->kobj, &dev->parent->kobj, "device");
if (error)
goto out_subsys;
}
#ifdef CONFIG_BLOCK
/* /sys/block has directories and does not need symlinks */
if (sysfs_deprecated && dev->class == &block_class)
return 0;
#endif
/* link in the class directory pointing to the device */
error = sysfs_create_link(&dev->class->p->subsys.kobj, &dev->kobj, dev_name(dev));
if (error)
goto out_device;
return 0;
out_device:
sysfs_remove_link(&dev->kobj, "device");
out_subsys:
sysfs_remove_link(&dev->kobj, "subsystem");
out:
return error;
}
文件/drivers/base/bus.c
/**
* bus_probe_device - 为一个新设备探测驱动
* @dev: 要探测的设备
*
* - 当总线允许的时候,自动探测驱动
*/
void bus_probe_device(struct device *dev)
{
struct bus_type *bus = dev->bus;
struct subsys_interface *sif;
int ret;
if (!bus)
return;
if (bus->p->drivers_autoprobe) {
ret = device_attach(dev);
WARN_ON(ret < 0);
}
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);
}
文件/drivers/base/dd.c
/**
* device_attach - 尝试把一个设备粘附上一个驱动
* @dev: device.
*
* 步进遍历该总线拥有的驱动list,并为每一对调用driver_probe_device()。
* 如果找到了一个兼容对,就break并return.
*
* 如果一个设备绑定到了一个驱动上就返回1;
* 没有没有匹配的驱动找到,就返回0;
* 如果设备未注册返回-ENODEV
*
* 当其实为一个USB接口调用,必须要有一个@dev->parent的lock。
*/
int device_attach(struct device *dev)
{
int ret = 0;
device_lock(dev);
if (dev->driver) {
if (klist_node_attached(&dev->p->knode_driver)) {
ret = 1;
goto out_unlock;
}
ret = device_bind_driver(dev);
if (ret == 0)
ret = 1;
else {
dev->driver = NULL;
ret = 0;
}
} else {
ret = bus_for_each_drv(dev->bus, NULL, dev, __device_attach);
pm_request_idle(dev);
}
out_unlock:
device_unlock(dev);
return ret;
}
static int __device_attach(struct device_driver *drv, void *data)
{
struct device *dev = data;
if (!driver_match_device(drv, dev))
return 0;
return driver_probe_device(drv, dev);
}
文件/drivers/base/dd.c
/**
* driver_probe_device - 尝试把设备和驱动绑定在一起
* @drv: 要绑定到设备的驱动
* @dev: 尝试绑定到驱动上的设备
*
* 如果设备未注册,该方法返回-ENODEV,
* 如果设备绑定成功返回1,否则返回0
*
* 该方法必须在@dev被锁的情况下调用。 如果是为USB接口调用,
* @dev->parent也必须被锁。
*/
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;
}
文件/drivers/base/platform.c
/**
* platform_match - 绑定platform设备到platform驱动
* @dev: device.
* @drv: driver.
*
* Platform 设备ID被认定为这样编码:
* "<name><instance>", <name>是一个设备类型的短描述符,
* 如"pci"或"floppy",而<instance>是该设备的枚举实例,如'0'
* 或'42'. 驱动ID是简单的"<name>"。 所以提取platform_device
* 结构的<name>并拿他和驱动的名称比较。返回它们是否匹配。
*/
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);
/* Attempt an OF style match first */
if (of_driver_match_device(dev, drv))
return 1;
/* Then try ACPI style match */
if (acpi_driver_match_device(dev, drv))
return 1;
/* Then try to match against the id table */
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);
}
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 = drv;
/* 如果使用pinctrl, 在探测前绑定pins */
ret = pinctrl_bind_pins(dev);
if (ret)
goto probe_failed;
if (driver_sysfs_add(dev)) {
printk(KERN_ERR "%s: driver_sysfs_add(%s) failed\n",__func__, dev_name(dev));
goto probe_failed;
}
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;
}
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;
dev_set_drvdata(dev, NULL);
if (ret == -EPROBE_DEFER) {
/* Driver requested deferred probing */
dev_info(dev, "Driver %s requests probe deferral\n", drv->name);
driver_deferred_probe_add(dev);
} else 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);
} else {
pr_debug("%s: probe of %s rejects match %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;
}
学习《Linux设备模型浅析之设备篇》笔记(三)相关推荐
- 学习《Linux设备模型浅析之设备篇》笔记(一)
最近在学习Linux设备模型,前面几篇文章也是读这篇的时候遇到问题,然后为了搞清楚先转去摸索才写出来的. 当然了,刚开始是先读到<Linux那些事儿之我是Sysfs>,搞不清楚才去读的&l ...
- 学习《Linux设备模型浅析之设备篇》笔记(二)
文件/drivers/base/platform.c int __init platform_bus_init(void) { int error; early_platform_cl ...
- 学习《Linux设备模型浅析之驱动篇》笔记(一)
原文中说了,内核版本为2.6.29:这里都贴3.15的内核源码: 文件/drivers/rtc/rtc-s3c.c static struct platform_driver s3c_rtc_driv ...
- 学习《Linux设备模型浅析之设备篇》笔记(深挖二)
/** * platform_add_devices - 添加一些platform设备 * @devs: 要添加的platform设备的队列 * @num: platform设备队列的书目 * ...
- 学习《Linux设备模型浅析之设备篇》笔记(深挖一)
这篇文章既然说了是浅析,那就是跳过了一些东西,我们把这些跳过的东西给它尽可能的补回来 今天登陆 lxr.free-electrons.com 发现内核版本已经升级到3.15了,那以后都使用3.15的源 ...
- Linux设备模型之platform设备
Linux设备模型之platform设备 1. Platform模块的软件架构 2. Platform设备 2.1 platform_device原型 2.2 注册添加device 2.2.1 pla ...
- RT-Thread记录(十三、I/O 设备模型之PIN设备)
讲完UART设备之后,我们已经熟悉RT-Thread I/O 设备模型了,回头看看基本的 PIN 设备. 目录 前言 一.PIN 设备模型解析 1.1 初识 GPIO 操作函数 1.2 PIN 设备框 ...
- RT-Thread记录(十二、I/O 设备模型之UART设备 — 使用测试)
从 UART 设备开始学会使用 RT-Thread I/O 设备模型 . 目录 前言 一.UART 设备操作 1.1 UART 设备控制块 1.2 UART 操作函数 1.2.1 查找 UART 设备 ...
- Linux设备模型、平台设备驱动、设备树(device tree)、GPIO子系统以及pinctrl子系统介绍
文章目录 一.Linux设备模型介绍 (1)设备驱动模型总体介绍 (2)设备驱动模型文件表现 (3)设备驱动模型工作原理 [1]总线 [2]设备 [3]驱动 [4]注册流程 二.平台设备驱动介绍 (1 ...
最新文章
- Space-Filling Designs
- dmx512协议c语言编程,DMX512协议+c程序代码.pdf
- HALCON示例程序vessel.hdev血管的分割与测量
- 简单的小工具wordlight——让VS变量高亮起来
- google annotation笔记
- AndroidStudio安卓原生开发_android按钮防止短时间内连续点击_在android_java中都能使用---Android原生开发工作笔记131
- jQuery 表格排序插件 Tablesorter 使用
- C#_未在本地计算机上注册“Microsoft.Jet.OLEDB.4.0”提供程序
- spring扩展点一:BeanDefinitionRegistryPostProcessor在框架中的应用
- 小学五年级计算机课评课,小学生信息技术课《复制与变换》评课稿
- 计算机网络二进制计算题
- 《我想吃掉你的胰脏》观后感
- Java小游戏中加背景音乐--有图有真相
- php plaintext,php从邮件正文中提取text / plain
- 科研写作——常见句式(一)
- C语言--指针之空指针(void *)
- 1.第三章 选择结构(一)
- 王道书P41 T21(单链表实现)
- C语言-大端存储和小端存储
- idea 不识别java文件,类文件变成灰色,而且有橙色角标