컴퓨터가 완전히 꺼졌다가 다시 켜질 때만 작동하는 PCIe 장치가 있습니다. 간단한 reboot
또는 reboot -p
명령을 실행해도 PCIe 카드의 전원이 껐다 켜지지 않아 재부팅 후 작동하지 않는 것 같습니다.
운영 체제에서 PCIe 슬롯에 있는 장치의 전원을 껐다 켜는 방법이 있습니까? 에서 찾을 수 있지만 /sys/bus/pci/devices/0000*/
보드를 올바르게 재설정하는 방법을 모르겠습니다. 전원을 바꾸는 것이 유일한 방법인 것 같습니다.
그 외에도 reboot
명령이 완전히 다시 시작되도록 하는 설정을 변경할 수 있습니까?
그런데 저는 Ubuntu 12.10을 실행하고 있습니다.
답변1
장치를 제거하고 PCIe 버스를 다시 검색하십시오.
해당 디렉터리의 기능을 통해 PCIe 장치를 제거 remove
하고 PCIe 버스의 기능을 통해 다시 로드하면 rescan
컴퓨터를 다시 시작하지 않고 커널이 PCIe 장치를 다시 시작합니다.
echo "1" > /sys/bus/pci/devices/DDDD\:BB\:DD.F/remove
sleep 1
echo "1" > /sys/bus/pci/rescan
위 코드에서는 DDDD:BB:DD.F
장치 슬롯 형식입니다.도메인:버스:device.function.
답변2
PCI Express에서 재설정하는 것은 약간 복잡합니다. 재설정에는 주로 일반 재설정과 기능 수준 재설정의 두 가지 유형이 있습니다. 일반 재설정에는 기본 재설정과 비기본 재설정이라는 두 가지 유형도 있습니다. 자세한 내용은 PCI Express 사양을 참조하세요.
"콜드 재설정"은 PCIe 장치의 전원을 켠 후 발생하는 기본 재설정입니다. 시스템을 껐다가 다시 켜는 것 외에 콜드 리셋을 실행하는 표준 방법은 없는 것 같습니다. 내 컴퓨터에서는 /sys/bus/pci/slots
디렉토리가 비어 있습니다.
"웜 리셋"은 장치의 전원을 제거하지 않고 실행되는 기본 리셋입니다. 핫 리셋을 실행하는 표준 방법은 없는 것 같습니다.
"핫 리셋"은 PCI Express 링크를 통해 트리거되는 전통적인 리셋입니다. 링크가 전기적 유휴 상태로 강제 전환되거나 웜 재설정 비트가 설정된 TS1 및 TS2 주문 세트를 전송하면 웜 재설정이 트리거됩니다. 소프트웨어는 장치 브리지 포트의 PCI 구성 공간 업스트림에 있는 브리지 제어 레지스터의 보조 버스 재설정 비트를 설정한 다음 삭제하여 웜 재설정을 시작할 수 있습니다.
FLR(기능 수준 재설정)은 PCI Express 장치의 단일 기능에만 영향을 미치는 재설정입니다. 전체 PCIe 장치를 재설정해서는 안 됩니다. PCIe 사양에는 기능 수준 재설정이 필요하지 않습니다. 기능 수준 재설정은 PCI 구성 공간의 PCI Express 기능 구조에 있는 기능 장치 제어 레지스터의 기능 수준 재설정 활성화 비트를 설정하여 시작됩니다.
Linux 를 사용하여 이 파일에 1을 쓰면 /sys/bus/pci/devices/$dev/reset
해당 기능의 기능 수준 재설정이 시작됩니다. 이는 전체 장치가 아닌 장치의 특정 기능에만 영향을 미치며 장치는 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 버스를 다시 검색하려고 시도합니다. 또한 이 스크립트는 단일 기능이 있는 장치에서만 테스트되었으므로 여러 기능이 있는 장치의 경우 일부 수정이 필요할 수 있습니다.
답변3
잠재적인 접근법 #1
다음 명령을 사용하면 가능하다고 생각합니다.
장애를 입히다
echo 0 > /sys/bus/pci/slots/$NUMBER/power
~할 수 있게 하다
echo 1 > /sys/bus/pci/slots/$NUMBER/power
$NUMBER
PCI 슬롯 번호는 어디에 있습니까?
lspci -vv
장치를 식별하는 데 도움이 될 수 있습니다. 이것은 잘 문서화되어 있지 않습니다 ...
잠재적인 접근법 #2
나는 이것을 만났다U&L의 스레드, 유사한 질문: 이 질문에 대한 일부 답변은 다음 명령을 사용하여 재설정할 수 있음을 나타냅니다.
echo "1" > /sys/bus/pci/devices/$NUMBER/reset
그러나 거기에서 답변을 읽을 것입니다! 그러기 위해서는 조건이 있습니다! 구체적으로 내가 할게이 답변을 읽어보세요!
잠재적인 접근법 #3
setpci
PCI 버스의 장치를 재설정하는 방법을 제공하는 Unix 명령이 있습니다 .
이 명령에 대한 구체적인 예가 표시되지 않으므로 Google에서 예를 찾아 찾아보아야 합니다.매뉴얼 페이지. 나는 당신이 이 명령을 사용하는 데 확신을 가질 때까지 이 명령을 주의해서 사용할 것입니다. 내가 읽은 바에 따르면 하드웨어에서 직접 작동하므로 이러한 기능을 제공하는 도구를 사용하는 것에 비해 직접 수행하는 것은 항상 위험이 있습니다!
답변4
alex.forencich가 게시한 답변을 바탕으로
CentOS 7에서 작동하려면 일부 변경이 필요했습니다. 부분적으로는 루트로 실행되지 않았기 때문입니다. 이 버전은 실행 중인 명령을 보여줍니다.
#!/bin/bash
# e.g. $ ./pcie_hot_reset.sh 04:00.0
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 -e "\nRemoving $DEV"
CMD="echo 1 | sudo tee /sys/bus/pci/devices/$DEV/remove"
printf "> $CMD\n"
eval $CMD
echo -e "\nPerforming hot reset of port $PORT"
CMD="setpci -s $PORT BRIDGE_CONTROL"
printf "> $CMD\n"
BR_CTRL=$(eval $CMD)
echo "Bridge control: $BR_CTRL"
CMD="sudo setpci -s $PORT BRIDGE_CONTROL=$(printf "%04x" $((0x${BR_CTRL} | 0x40)))"
printf "> $CMD\n"
eval $CMD
sleep 0.01
CMD="sudo setpci -s $PORT BRIDGE_CONTROL=$BR_CTRL"
printf "> $CMD\n"
eval $CMD
sleep 0.5
echo -e "\nRescanning bus"
CMD="echo 1 | sudo tee /sys/bus/pci/devices/$PORT/rescan"
printf "> $CMD\n"
eval $CMD
예제 출력:
$ ./pcie_hot_reset.sh 04:00.0
Removing 0000:04:00.0
> echo 1 | sudo tee /sys/bus/pci/devices/0000:04:00.0/remove
1
Performing hot reset of port 0000:00:03.0
> setpci -s 0000:00:03.0 BRIDGE_CONTROL
Bridge control: 0010
> sudo setpci -s 0000:00:03.0 BRIDGE_CONTROL=0050
> sudo setpci -s 0000:00:03.0 BRIDGE_CONTROL=0010
Rescanning bus
> echo 1 | sudo tee /sys/bus/pci/devices/0000:00:03.0/rescan
1