Linux | PCIe Hotplug | 概念及工作原理的不完全总结

本文深入探讨了PCIe热插拔在Linux系统中的实现,包括通知式和暴力热插拔的区别,以及热插拔的组成部件如指示器、手动保留锁等。文章详细解析了Linux内核中PCIe热插拔驱动的中断处理流程,介绍了如何处理电源管理、意外移除错误和整合错误处理。此外,还提到了即将引入的BAR移除功能,以优化资源分配。通过对驱动代码的分析,展示了如何在设备插入和移除时协调中断和线程,确保系统的稳定性和效率。

本文对 PCIe 热插拔的概念及工作原理进行不完全总结。

更新: 2022 / 12 / 31


参考这里 12345

1992年初始版本的 PCI 规范并不支持运行时的板卡添加和移除。在20世纪90年代后期到21世纪初期,各种专有的热拔插控制器或者与厂商无关的标准热拔插控制器被构思出来,同时 Linux 通过位于 drivers/pci/hotplug 的驱动开始支持热拔插功能。然而,直到2002年 Linux 才开始支持PCI Express 的热拔插功能,但是具体的形式随时间不断变化。最初,PCI Express 热拔插主要是为服务器的热交换板卡或笔记本的 ExpressCards 设计的,如今,它已经广泛地应用于数据中心 ( 数据中心 NVMe Flash 硬盘需要运行时拔插 ) 和雷电接口。


热插拔

PCIe 热插拔,是指在系统上电运行时,允许插入或拔出 PCIe 设备。拔出时不需要平台提前下电,插入时直接生效,不需要系统重启。这对于服务器实现高可靠性而言是一个必不可少的特性。

热插拔可以分为2种,通知式热插拔暴力热插拔。这两种差异主要体现在拔盘的操作上。

  • 设备插入时, 内核 pciehp 驱动走的都是通知式热插流程,以盘插入时在位信号的变化或者通知按钮的按下作为触发条件。通知式热拔时,需要先通过软件指令,停止业务,移除 pcie 设备,再进行拔盘操作。
  • 暴力热拔时,没有任何通知,直接进行拔盘动作。

组成部件

为了 pcie 热插拔功能的实现,PCIe 协议定义了一系列需要实现的组件:

组件 目的
Indicator show the power and attention state of the slot。

标准模型中定义两个 indicators:一个Power Indicator 和一个 Attention Indicator。都会有三种状态:ONOFFBlinking
Attention Indicator 是黄色的灯,用来指示出现了操作的问题,或者表示 hotplug slot 已经被识别到了,手动操作可以很容易定位到。

ON: 表示热插拔槽位故障
OFF: 表示一切正常
BLINKING: 表示热插拔流程正在执行
Power Indicator 是绿色的灯,表示 slotpower 状态,可以用 blink 指示总线对用户的操作产生了响应。

OFF: 表示槽位下电,可以进行设备的热插或热拔
ON: 表示热插拔操作已完成,槽位上电,不可以进行热插或热拔
BLINKING: 表示此时正在处于上电或下电槽位, 或者此时 attention button 被按下,正在等待反馈,或者表示 hot-plug 操作正在进行软件的初始化
Manually-operated Retention Latch (MRL) Holds adds-in cards in place
MRL Sensor Allows the Port and system software to detect the MRL being opened

MRL 是一种手动操作保留机制。保持插入卡在 slot 上,防止用户移除卡。系统添加了一个 MRL sensor,以便侦测每个 port 对应的 slotMRL
Electromechanical Interlock Prevents removal of add-in cards while slot is powered

一种互斥机制,确保在热插拔流程都执行完成后 PCIe 设备才可被物理移除。
Attention Button Allows user to request Hot-Plug operations

hotplug 中定义的一个开关按钮,一般会在 slot 上或者在卡片上,按一下表明要做一个 hotplug 动作或者 removal 动作。
Software User Interface Allows user to request Hot-Plug operations
Slot Numbering Provides visual identification of slots

槽位编号,由底板号( Classic Number )和物理槽位号( Physical Slot Number ) 组成,可在用户接口上显示。

实现代码

通知式热插拔

热拔的流程图如下所示:
在这里插入图片描述
热插流程类似,不再赘述。

PCIe 热插拔功能的实现需要 pcie 热插拔控制器和 pcie 热插拔驱动的配合。
代码主要集中在 driver/pci/hotplug/pciehp_hpc.c 6driver/pci/hotplug/pciehp_ctrl.c 7

  • pciehp_hpc.c 主要负责控制器的初始化以及检测设备在位变化、attention button pressed、电源错误等事件检测,检测到这些事件后,会上报热插拔中断。
  • pciehp_ctrl.c 代码主要是对热插拔各个 events 的具体处理。
  1. pciehp 初始化
    PCIe 热插拔是作为 pcie 端口服务实现的,它已在 driver/pci/hotplug/pciehp_core.c 8 中的 pcie 端口驱动程序中注册:
int __init pcie_hp_init(void)
{
   
   
	int retval = 0;

	retval = pcie_port_service_register(&hpdriver_portdrv);
	pr_debug("pcie_port_service_register = %d\n", retval);
	if (retval)
		pr_debug("Failure to register service\n");

	return retval;
}

之后会调用 pcie_probe 进行端口注册,

+->pciehp_probe(struct pcie_device *dev)
	+-> pcie_init()
		+-> pcie_init_slot() 
		// 该函数中会创建hotplug_slot, hotplug_slot_info, hotplug_slot_ops等热插拔驱动关键的数据结构
		
	+-> init_slot()
		+-> pci_hp_initialize()
			+-> pci_create_slot()
				+-> kobject_init_and_add()  
				// 添加sysfs对象
				+-> list_add(&slot->list, &parent->slots) 
				//  将hotplug_slot添加到pci_hotplug_slot_list
	
	+-> pcie_init_notification()
		+-> pciehp_request_irq() 
		//中断申请
		+-> pcie_enable_notification()
	
	+->  pciehp_enable_slot() 
	// 使能hp槽位
		+-> board_added()
  1. 注册热插拔中断服务 6
static inline int pciehp_request_irq(struct controller 
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值