コンピュータが完全にオフになってから再びオンになったときにのみ機能する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でリセットするのは少し複雑です。リセットには、主に一般リセットと機能レベルリセットの2種類があります。一般リセットには、基本リセットと非基本リセットの2種類があります。詳細については、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で動作するにはいくつかの変更が必要でした。部分的にはrootとして実行されていないからです。このバージョンは、実行中のコマンドを示しています。
#!/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