PCI Express中的复位有点复杂。重置主要有两种类型-常规重置和功能级别重置。还有两种类型的常规重置,基本重置和非基本重置。有关所有详细信息,请参见PCI Express规范。
“冷复位”是在对PCIe设备通电后发生的基本复位。似乎没有触发冷复位的标准方法,除了关闭系统然后重新打开之外。在我的机器上,/sys/bus/pci/slots
目录为空。
“热复位”是在不断开设备电源的情况下触发的基本复位。似乎没有触发热复位的标准方法。
“热重置”是通过PCI Express链路触发的常规重置。当链路被迫进入电气空闲状态或通过发送带有热复位位的TS1和TS2有序集来触发热复位。软件可以通过设置然后清除设备上游桥接端口的PCI配置空间中桥接控制寄存器中的辅助总线复位位来启动热复位。
“功能级别重置”(FLR)是仅影响PCI Express设备的单个功能的重置。它不得重置整个PCIe设备。PCIe规范不需要实现功能级别的重置。通过在PCI配置空间中的PCI Express功能结构中的功能的设备控制寄存器中设置启动功能级别重置位,可以启动功能级别重置。
Linux以形式公开功能级别的重置功能/sys/bus/pci/devices/$dev/reset
。向该文件写入1将启动相应功能的功能级复位。请注意,这仅影响设备的特定功能,而不影响整个设备,并且不要求设备按照PCIe规范实施功能级别的重置。
我不知道触发热重置的任何“不错”方法(没有sysfs条目)。但是,可以使用setpci这样做:
#!/bin/bash
dev=$1
if [ -z "$dev" ]; then
echo "Error: no device specified"
exit 1
fi
if [ ! -e "/sys/bus/pci/devices/$dev" ]; then
dev="0000:$dev"
fi
if [ ! -e "/sys/bus/pci/devices/$dev" ]; then
echo "Error: device $dev not found"
exit 1
fi
port=$(basename $(dirname $(readlink "/sys/bus/pci/devices/$dev")))
if [ ! -e "/sys/bus/pci/devices/$port" ]; then
echo "Error: device $port not found"
exit 1
fi
echo "Removing $dev..."
echo 1 > "/sys/bus/pci/devices/$dev/remove"
echo "Performing hot reset of port $port..."
bc=$(setpci -s $port BRIDGE_CONTROL)
echo "Bridge control:" $bc
setpci -s $port BRIDGE_CONTROL=$(printf "%04x" $(("0x$bc" | 0x40)))
sleep 0.01
setpci -s $port BRIDGE_CONTROL=$bc
sleep 0.5
echo "Rescanning bus..."
echo 1 > "/sys/bus/pci/devices/$port/rescan"
运行此脚本之前,请确保卸载所有附加的驱动程序。该脚本将尝试删除PCIe设备,然后命令上游交换机端口发出热重置,然后尝试重新扫描PCIe总线。此脚本也仅在具有单个功能的设备上进行了测试,因此可能需要对具有多个功能的设备进行一些重新设计。
reboot -f
吗?这类似于按下CPU的电源按钮。