如何重置/重启 PCIe 设备的电源?

zac*_*618 33 pci power-management devices

我有一个 PCIe 设备,只有在计算机完全关闭然后再次打开时才能正常工作。发出简单rebootreboot -p命令似乎不会为 PCIe 卡重新通电,这会导致它在重新启动后无法工作。

有没有办法从操作系统为 PCIe 插槽中的设备循环供电?我可以在 中找到它/sys/bus/pci/devices/0000*/,但我不知道如何正确重置电路板。切换权力似乎是唯一的方法。

除此之外,我可以在某处更改会导致reboot命令完全重启的设置吗?

顺便说一下,我正在运行 Ubuntu 12.10。

slm*_*slm 18

潜在方法#1

我认为您可以使用以下命令来完成:

禁用

echo 0 > /sys/bus/pci/slots/$NUMBER/power
Run Code Online (Sandbox Code Playgroud)

使能够

echo 1 > /sys/bus/pci/slots/$NUMBER/power
Run Code Online (Sandbox Code Playgroud)

$NUMBERPCI插槽的编号在哪里。

lspci -vv可能有助于识别设备。这不是很好的记录...

潜在方法#2

在 U&L 上遇到了这个线程,类似的问题:这个问题有一些答案说你可以用这个命令重置:

echo "1" > /sys/bus/pci/devices/$NUMBER/reset
Run Code Online (Sandbox Code Playgroud)

但是,我会阅读那里的答案!这样做是有条件的!具体来说,我会阅读这个答案

潜在方法#3

有一个 Unix 命令,setpci,它可以为您提供一种重置 PCI 总线中设备的方法。

我没有看到此命令的任何具体示例,因此您必须在 google 上搜索示例并查看手册页。在你对它的使用有信心之前,我会轻率地使用这个命令。从我读到的内容来看,它直接操作硬件,因此与使用暴露此类功能的工具相比,自己动手总是存在风险!

  • 即使我插入了多张卡,插槽中也没有显示任何内容。我在“/sys/bus/pci/devices/$NUMBER/”中确实有一个电源目录。但似乎没有什么理由设置 0 或 1 (3认同)

小智 17

移除设备并重新扫描 PCIe 总线

通过remove其目录中的函数删除 PCIe 设备并通过 PCIe 总线的rescan函数重新加载它会导致内核在不重新启动计算机的情况下重新启动 PCIe 设备。

echo "1" > /sys/bus/pci/devices/DDDD\:BB\:DD.F/remove
sleep 1
echo "1" > /sys/bus/pci/rescan
Run Code Online (Sandbox Code Playgroud)

在上面的代码中,DDDD:BB:DD.F是设备槽格式Domain:Bus:Device.Function


ale*_*ich 14

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"
Run Code Online (Sandbox Code Playgroud)

确保在运行此脚本之前卸载所有连接的驱动程序。此脚本将尝试移除 PCIe 设备,然后命令上游交换机端口发出热重置,然后尝试重新扫描 PCIe 总线。此脚本也仅在具有单一功能的设备上进行了测试,因此对于具有多种功能的设备可能需要进行一些修改。