Linux PCIE热插拔设备及其驱动相关(on-going)

struct pci_device_id
用于定义PCI设备;

MODULE_DEVICE_TABLE;
导出pci_device_id中设备的相关信息至modules.pcimap
https://zhuanlan.zhihu.com/p/116478513
http://blog.chinaunix.net/uid-7187477-id-3221645.html

pci_driver
其中,成员id_table指向struct pci_device_id设备信息,其他成员为驱动相关的函数等;然后会调用pci_register_driver注册驱动

将可移动设备连入系统时,系统的后台中会依次发生如下事件: l 内核检测到新硬件入,然后分别通知hotplug和udev。前者用来装入相应的内核模块(如usb-storage),而后者用来在/dev中创建相应的设备节点(如/dev/sda1)。 l udev创建了相应的设备节点之后,会将这一消息通知hal的守护程序(hald)。当然udev还得保证新创建的设备节点可以被普通用户访问。 l hotplug装入了相应的内核模块之后,会把这一消息通知给hald。 l hald在受到hotplug和udev发出的消息之后,认为新硬件已经正式被系统认可了。此时它会通过一系列精心编写的规则文件(就是传说中的xxx-policy.fdi),把发现新硬件的消息通过dbus发送出去,同时还会调用update-fstab或fstab-sync来更新/etc/fstab,为相应的设备节点创建适合的挂载点。 l 卷管理器会监听dbus中发现新硬件的消息。根据所入的硬件(区分U盘和数码相机等)不同,卷管理器会先将相应的设备节点挂载到hald创建的挂载点上,然后再打开不同的应用程序。 当然,如果是在CDROM中入光盘,过程可能比较简单。因为CDROM本身就是一个固定的硬件,无需hotplug和udev的协助: l hald会自己监视CDROM,并且将光盘托架开合的消息通过dbus发出去。 l 卷管理器负责检查CDROM中的盘片内容,进行挂载,并调用合适的应用程序。 要注意,hald的工作是从上游得到硬件就绪的消息,然后将这个消息转发到dbus中。尽管它会调用程序来更新fstab,但实际上它自己并不执行挂载的工作。
<think>嗯,用户现在问的是Linux 5.10内核中PCIe热插拔驱动的实现流程。我需要结合之前关于飞腾ACPI的回答,以及用户提供的引用内容来构建答案。首先,用户之前的对话中提到了飞腾处理器使用ACPI来处理PCIe热插拔,特别是通过ACPI的_OST和_EJ0方法。现在用户想知道Linux 5.10内核中PCIe热插拔的具体实现流程。 首先,我需要回忆Linux内核中PCIe热插拔的基本机制。通常,这涉及到ACPI的事件处理和内核中的子系统,比如PCI子系统热插拔控制器驱动等。用户提供的引用[1]提到了SELinux的许可模式,这可能与内核模块的安全策略有关,但不太直接相关。引用[2]和[3]是关于内核编译和驱动的配置,可能涉及到编译时的选项,比如是否启用某些热插拔相关驱动支持。 接下来,我需要确定Linux 5.10内核中PCIe热插拔的具体流程。可能需要分步骤说明,从硬件事件触发到ACPI处理,再到内核驱动响应。例如,当用户入一个PCIe设备时,硬件会生成一个中断,ACPI解析这个事件,调用相应的AML方法,然后内核的热插拔驱动处理这个事件,加载驱动,更新设备列表等。 用户提供的引用[2]中提到了编译内核时的步骤,可能需要考虑在内核配置中启用PCIe热插拔相关的选项,比如CONFIG_HOTPLUG_PCI_PCIE,这可能是在Device Drivers部分配置的。而引用[3]中提到的设备驱动选项,如Userspace firmware loading support,可能影响固件的加载,但不确定是否直接关联到热插拔流程。 同时,用户之前的问题中涉及飞腾处理器的ACPI实现,所以可能需要对比Linux通用的实现和飞腾平台的特殊处理。比如,飞腾使用ACPI表来描述PCIe控制器,而Linux内核中的PCI子系统会解析这些表,注册热插拔事件的处理函数。 还需要考虑内核中的模块,比如pciehp,这是PCI Express HotPlug驱动模块。在实现流程中,这个模块如何与ACPI交互,如何处理拔事件,比如调用acpi_pcihp_ops中的函数。 另外,用户可能对内核代码结构感兴趣,比如哪些关键函数或文件涉及,比如drivers/pci/hotplug/pciehp* 中的代码,以及ACPI相关的处理部分,比如drivers/acpi/pci_hotplug.c。 还要注意用户提供的引用[1]中提到的SELinux许可模式,虽然主要与安全策略相关,但在调试热插拔驱动时,可能需要暂时禁用SELinux来排除权限问题,但这一点可能不是主要流程的一部分,但可以作为调试技巧提及。 总结来说,回答需要分步骤说明实现流程,从硬件事件到ACPI处理,再到内核驱动的响应,涉及的主要模块和函数,以及相关的内核配置选项。同时,结合用户之前的飞腾ACPI内容,指出在ARM64架构下可能的差异或特定处理。可能还需要提到用户空间的通知机制,比如udev规则,以及调试方法,如使用dmesg查看日志。</think>#### 一、Linux 5.10 PCIe热插拔驱动核心架构 Linux内核的PCIe热插拔实现基于**ACPI事件驱动模型**和**分层驱动框架**,主要包含以下组件: 1. **硬件事件触发层** - **ACPI热插拔信号**: PCIe槽状态变化(如卡入/拔出)通过ACPI的`_OST`(OSPM Status)和`_EJ0`(Eject Device)方法通知内核[^1]。例如,飞腾平台触发热插拔事件时,ACPI表定义的`Notify(PC00, 0x02)`会发送槽状态更新信号。 - **MRL(Manual Retention Latch)传感器**: 物理槽的机械锁状态通过GPIO或I2C总线反馈至内核,驱动层通过`pciehp`模块解析信号。 2. **内核驱动响应层** - **pciehp模块**(PCI Express HotPlug Driver): 位于`drivers/pci/hotplug/pciehp*`,通过轮询或中断检测槽状态变化,调用`pciehp_handle_presence_change()`处理设备拔事件。 ```c // 核心处理逻辑(drivers/pci/hotplug/pciehp_hpc.c) void pciehp_handle_presence_change(struct controller *ctrl) { u8 presence; pciehp_get_adapter_status(ctrl, &presence); // 读取槽状态 if (presence) pciehp_enable_slot(ctrl); // 激活设备 else pciehp_disable_slot(ctrl); // 停用设备 } ``` - **ACPI-PCI桥接层**: ACPI事件通过`acpi_pcihp_ops`接口(定义于`drivers/acpi/pci_hotplug.c`)传递至PCI子系统,例如`acpi_pcihp_check_ejectable()`验证设备是否支持拔。 3. **设备资源管理** - **PCIe设备枚举**: 热插拔设备入后,内核调用`pci_scan_slot()`扫描新设备,分配`struct pci_dev`对象并注册至系统- **驱动匹配与加载**: 通过`driver_attach()`触发设备驱动的匹配,若匹配成功则调用驱动的`probe()`方法。 --- #### 二、热插拔事件处理流程(以设备为例) 1. **硬件事件触发** - PCIe槽的PRSNT#引脚电平变化触发中断,ACPI固件生成`Notify`事件(类型为`ACPI_NOTIFY_DEVICE_CHECK`)。 2. **ACPI事件传递** - 内核ACPI子系统调用`acpi_install_notify_handler()`注册的回调函数,解析设备路径(如`\_SB.PC00.BR01`),通过`acpi_pcihp_check_handle()`验证是否为PCIe槽。 3. **槽状态检测** - `pciehp`模块通过`pciehp_query_power_controller()`读取槽控制器的Power Controller Capability寄存器(偏移0x04),确认设备是否就绪。 4. **设备激活与资源配置** - 调用`pci_assign_resource()`分配BAR空间,`pci_enable_device()`启用设备DMA和IRQ。 -设备需固件支持(如FPGA或GPU),通过`request_firmware()`从用户空间加载(引用[3]中`Userspace firmware loading support`配置相关)[^3]。 5. **用户空间通知** - 内核通过uevent机制发送`KOBJ_ADD`事件,触发udev规则加载驱动或执行自定义脚本。 --- #### 三、关键内核配置选项 在编译支持PCIe热插拔的内核时,需启用以下配置(引用[2]中提到的`make menuconfig`流程)[^2]: ```bash # 启用PCIe热插拔核心支持 CONFIG_HOTPLUG_PCI_PCIE=y # 选择中断驱动模式(替代轮询) CONFIG_HOTPLUG_PCI_PCIE_HP_IRQ=y # 支持ACPI热插拔事件处理 CONFIG_ACPI_HOTPLUG_PCI=y # 用户态固件加载(引用[3]配置) CONFIG_FW_LOADER_USER_HELPER=y ``` --- #### 四、调试与问题定位 1. **内核日志监控** ```bash dmesg | grep -i "pciehp\|hotplug" # 查看热插拔事件日志 ``` 典型输出示例: ``` pciehp 0000:00:1c.0:pcie004: Slot(0): Card present pciehp 0000:00:1c.0:pcie004: Link Up ``` 2. **ACPI表分析** 反编译DSDT表,检查热插拔相关AML代码: ```bash iasl -d DSDT.dat # 生成DSDT.dsl grep -A 10 "_EJ0" DSDT.dsl # 查找弹出方法定义 ``` 3. **强制许可模式调试** 若SELinux阻止设备访问(引用[1]),可临时切换至许可模式: ```bash echo 0 > /sys/fs/selinux/enforce # 关闭强制模式[^1] ``` --- ### 相关问题 1. 如何在ARM64架构(如飞腾平台)上验证PCIe热插拔驱动是否生效? 2. Linux内核中ACPI与设备树(DT)在PCIe热插拔实现上有何差异? 3. 热插拔过程中固件加载失败的可能原因及调试方法?
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值