Linux驱动(四)platform总线匹配过程

1、前言

在上一篇文章Linux驱动(三)platform总线驱动中讲解了platform的驱动框架,设备与驱动相匹配后会调用驱动的probe函数,设备与驱动的匹配则是platform总线中的match函数实现的,本文将详细讲解match函数的匹配过程。

2、match函数

match函数原型如下:

/**
 * platform_match - 将平台设备与平台驱动程序绑定。
 * @dev: 设备。
 * @drv: 驱动程序。
 *
 * 假定平台设备的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);

	/* 当 driver_override 被设置时,只绑定到匹配的驱动程序 */
	if (pdev->driver_override)
		return !strcmp(pdev->driver_override, drv->name);

	/* 首先尝试 OF 风格的匹配 */
	if (of_driver_match_device(dev, drv))
		return 1;

	/* 然后尝试 ACPI 风格的匹配 */
	if (acpi_driver_match_device(dev, drv))
		return 1;

	/* 然后尝试与 id 表进行匹配 */
	if (pdrv->id_table)
		return platform_match_id(pdrv->id_table, pdev) != NULL;

	/* 回退到驱动程序名称匹配 */
	return (strcmp(pdev->name, drv->name) == 0);
}

在设备与驱动匹配比较的时候调用:

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

该接口在__platform_driver_register中赋值:

int __platform_driver_register(struct platform_driver *drv,
				struct module *owner)
{
	……
	drv->driver.bus = &platform_bus_type;
	……
}

其中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,
};

3、匹配过程

3.1 匹配优先级

match函数中代码执行顺序则代表了匹配的优先级:

struct platform_device *pdev = to_platform_device(dev);
struct platform_driver *pdrv = to_platform_driver(drv);
if (pdev->driver_override)
	return !strcmp(pdev->driver_override, drv->name);

if (of_driver_match_device(dev, drv))
	return 1;

if (acpi_driver_match_device(dev, drv))
	return 1;

if (pdrv->id_table)
	return platform_match_id(pdrv->id_table, pdev) != NULL;

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

其中to_platform_device和to_platform_driver是两个宏定义,在其内部使用了另一个宏定义container_of,用于根据结构体成员的地址来获取整个结构体本身的地址。

3.2 driver_override匹配

如果设置了driver_override,即driver_override不为NULL,那么只会进行driver_override的匹配,其优先级是最高的:

3.3 设备树匹配

设备树的匹配从of_driver_match_device开始分析,其函数调用关系如下:

of_driver_match_device(struct device *dev,const struct device_driver *drv)
-->of_match_device(drv->of_match_table, dev)
---->of_match_node(matches, dev->of_node);
------>__of_match_node(matches, node);
-------->__of_device_is_compatible(node, matches->compatible,
									  matches->type, matches->name);

分析内核代码可以得到设备树匹配比较的具体对象,其中device的device_node信息是通过解析设备树的节点得到的:

3.4 ACPI匹配

acpi的驱动在开发中没有使用到过,在此仅做简单分析,其代码调用如下,当没有设置acpi_match_table的时候会调用acpi_of_match_device进行匹配,设置了acpi_match_table的话会调用__acpi_match_device进行匹配:

bool acpi_driver_match_device(struct device *dev,
			      const struct device_driver *drv)
{
	if (!drv->acpi_match_table)
		return acpi_of_match_device(ACPI_COMPANION(dev),
					    drv->of_match_table);

	return !!__acpi_match_device(acpi_companion_match(dev),
				     drv->acpi_match_table, drv->of_match_table);
}

跟踪代码,其流程大致如下,后面的联合体内容较多未全部展开:

3.5 id_table匹配

id_table的匹配代码如下,通过比较pdev和id的name变量是否相等进行判定:

static const struct platform_device_id *platform_match_id(
			const struct platform_device_id *id,
			struct platform_device *pdev)
{
	while (id->name[0]) {
		if (strcmp(pdev->name, id->name) == 0) {
			pdev->id_entry = id;
			return id;
		}
		id++;
	}
	return NULL;
}

3.6 名称匹配

名称匹配代码如下,仅通过名称判定:

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

汇总所有优先级的图示如下:

4、总结

match函数的整体匹配流程基本上可以由上图表示,分析过程中有错误的地方欢迎评论指出。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/313523.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

PostgreSQL16中的新增功能:双向逻辑复制

在这篇博客中&#xff0c;我们将深入探讨Postgres 16中引入的一些更高级的新功能。为了更好地理解这些功能&#xff0c;读者应具备一些Linux、Postgres和SQL的基础知识&#xff0c;因为我们将深入探讨这些新功能并指导如何实现它们。 本博客以在Ubuntu 23.04上运行的PostgreSQL…

cmake 中的set用法

可以后面跟一串字符串 set — CMake 3.0.2 Documentation

ES6前端学习笔记

修正 ES6是ECMA为JavaScript制定的第6个标准版本&#xff0c;相关历史可查看此章节《ES6-ECMAScript6简介》。 标准委员会最终决定&#xff0c;标准在每年6月正式发布并作为当年的正式版本&#xff0c;接下来的时间里就在此版本的基础上进行改动&#xff0c;直到下一年6月草案…

2024 年1月12日最热CV论文:Distilling Vision-Language Models on Millions of Videos

谷歌研究新突破&#xff1a;Distilling VLM模型自动生成百万视频字幕&#xff0c;视频语言模型性能提升6%&#xff01; 引言&#xff1a;视频理解的挑战与机遇 在数字化时代&#xff0c;视频内容的爆炸式增长为计算机视觉和自然语言处理领域带来了前所未有的挑战与机遇。视频…

仲晶同志简历

女&#xff0c;汉族。1972年出生&#xff0c;国防大学科技与装备教研室教官。1992年&#xff0c;仲晶毕业于军事气象学院&#xff0c;1996年成为国防大学国防科技发展战略学硕士研究生&#xff0c;毕业后留校任教。曾出版过9部军事专著&#xff0c;先后发表学术论文100多万字。…

电动机智能综合保护器在煤矿内的应用分析——安科瑞赵嘉敏

摘要 &#xff1a;介绍了矿用电动机智能综合保护器系统的总体结构&#xff0c;采用直接将交流信号整流、滤波、调理、采样的方式变为微控制器能够识别的直流信号&#xff0c;通过对微控制器采集到的直流信号编程判断来实现对电动机的相关保护控制、故障显示与报警以及与上位机的…

Blazor 错误笔记

1. 运行时问题 Microsoft.NETCore.App.Runtime.Mono.browser-wasm Microsoft.NETCore.App.Runtime.Mono.browser-wasm 是一个 .NET Core 运行时的包&#xff0c;用于在浏览器中运行 .NET Core 应用程序。它是针对 WebAssembly 架构的 .NET Core 运行时&#xff0c;可以在浏览…

云服务器ECS_GPU云服务器_AIGC_弹性计算-阿里云

阿里云高性能云服务器60%单实例最大性能提升&#xff0c;35Gbps内网带宽&#xff0c;网络增强&通用型云服务器、本地SSD型云服务器、大数据型云服务器、GPU异构型云服务器&#xff0c;阿里云百科aliyunbaike.com分享阿里云高性能云服务器&#xff1a; 阿里云高性能云服务器…

java项目之家政服务中介网(ssm)

风定落花生&#xff0c;歌声逐流水&#xff0c;大家好我是风歌&#xff0c;混迹在java圈的辛苦码农。今天要和大家聊的是一款基于ssm的家政服务中介网。项目源码以及部署相关请联系风歌&#xff0c;文末附上联系信息 。 项目简介&#xff1a; 管理员&#xff1a;首页、个人中…

[redis] redis高可用之持久化

一、Redis 高可用的相关知识 1.1 什么是高可用 在web服务器中&#xff0c;高可用是指服务器可以正常访问的时间&#xff0c;衡量的标准是在多长时间内可以提供正常服务(99.9%、99.99%、99.999%等等)。 但是在Redis语境中&#xff0c;高可用的含义似乎要宽泛一些&#xff0c;…

网络传输(TCP)

前言 我们tcpdump抓包时会看到除报文数据外&#xff0c;前面还有一段其他的数据&#xff0c;这段数据分为两部分&#xff0c;ip包头&#xff08;一般20字节&#xff09;和tcp包头&#xff08;一般20字节&#xff09;&#xff0c;一般这两个头长度和为40&#xff0c;我们直接跳…

初识 Elasticsearch 应用知识,一文读懂 Elasticsearch 知识文集(1)

&#x1f3c6;作者简介&#xff0c;普修罗双战士&#xff0c;一直追求不断学习和成长&#xff0c;在技术的道路上持续探索和实践。 &#x1f3c6;多年互联网行业从业经验&#xff0c;历任核心研发工程师&#xff0c;项目技术负责人。 &#x1f389;欢迎 &#x1f44d;点赞✍评论…

TMC2226步进电机驱动---学习记录

基于TMC2226数据手册的学习 主要内容介绍&#xff1a; Package Outline TMC2226 手册中引脚解释&#xff08;按照手册表格顺序&#xff09; 了解每个引脚是接什么的&#xff0c;之后看原理图 &#xff08;借用立创广场kirito的原理图&#xff0c;后期换个&#xff09; 以前的疑…

如何将后端带过来的字符串通过‘,’号作为判断依据,分割字符串然后生成数组

在实际开发工程中我们会遇到我们调用后端接口获取图片、文件、视频甚至选择的对象时&#xff0c;如果是这样的&#xff1a; 这种数据类型如果想渲染在html中的话就会很麻烦&#xff0c;我们可以通过","号为切割点将它放入数组中&#xff0c;通过列表进行渲染 由于实…

C#,入门教程(14)——字符串与其他数据类型的转换

上一篇&#xff1a; C#&#xff0c;入门教程(13)——字符&#xff08;char&#xff09;及字符串&#xff08;string&#xff09;的基础知识https://blog.csdn.net/beijinghorn/article/details/123928151 数据只有可视化才能更好地体现其价值&#xff0c;因而 string 与 image…

【双指针】001移动零_C++

题目链接&#xff1a;移动零 目录 题目解析 代码书写 知识补充 题目解析 题目让我们求必须在不复制数组的情况下,编写一个函数将所有 0 移动到数组的末尾&#xff0c;同时保持非零元素的相对顺序。 这题我们可以用双指针的方法来写&#xff1a; 我们这里将用两个数组下标来…

权限系统模型:RBAC模型与ABAC模型

权限系统 基于角色的访问控制&#xff08;RBAC&#xff09; 基于角色的控制访问&#xff08;Role-Based Access Control&#xff0c;简称 RBAC&#xff09;&#xff0c;即&#xff1a;给予该账号角色&#xff08;Role&#xff09;&#xff0c;授权角色对应的相关权限&#xf…

【GNN 1】PyG实现图神经网络,完成节点分类任务,人话、保姆级教程

我们来做一个节点分类的任务&#xff0c;选择的数据集是Karate Club&#xff0c;Karate是空手道的意思&#xff0c;所以这就是一个空手道俱乐部的数据。 简而言之&#xff0c;这个数据集&#xff0c;包含34个节点&#xff0c;156条无向无权边&#xff0c;结点总共分为4类&…

SQL-DCL-如何用户管理,如何给用户权限?

&#x1f389;欢迎您来到我的MySQL基础复习专栏 ☆* o(≧▽≦)o *☆哈喽~我是小小恶斯法克&#x1f379; ✨博客主页&#xff1a;小小恶斯法克的博客 &#x1f388;该系列文章专栏&#xff1a;重拾MySQL &#x1f379;文章作者技术和水平很有限&#xff0c;如果文中出现错误&am…

【一周安全资讯0106】国家标准《信息安全技术 网络安全信息报送指南》正式发布;全球1100万SSH服务器面临“水龟攻击”威胁

要闻速览 1、国家标准GB/T 43557-2023《信息安全技术 网络安全信息报送指南》发布 2、《未成年人网络保护条例》元旦起施行 织密未成年人网络保护立体“安全网” 3、深圳证监局&#xff1a;证券期货经营机构应建立健全网络安全应急处置机制 4、黑客大规模恶意注册与ChatGPT相似…