PCI Expressのリセットは少し複雑です。リセットには主に2つのタイプがあります-従来のリセットと機能レベルのリセットです。従来のリセットには、基本リセットと非基本リセットの2種類があります。詳細については、PCI Express仕様を参照してください。
「コールドリセット」は、PCIeデバイスに電源が投入された後に行われる基本的なリセットです。コールドリセットをトリガーする標準的な方法はないようです。システムをオフにしてから再びオンにすることを除きます。私のマシンでは、/sys/bus/pci/slots
ディレクトリは空です。
「ウォームリセット」は、デバイスの電源を切断せずにトリガーされる基本的なリセットです。ウォームリセットをトリガーする標準的な方法はないようです。
「ホットリセット」は、PCIエクスプレスリンクを介してトリガーされる従来のリセットです。ホットリセットは、リンクが強制的に電気的アイドル状態になったとき、またはホットリセットビットが設定されたTS1およびTS2順序セットを送信したときにトリガーされます。ソフトウェアは、デバイスの上流のブリッジポートのPCI構成スペースにあるブリッジ制御レジスタのセカンダリバスリセットビットを設定してクリアすることにより、ホットリセットを開始できます。
「機能レベルリセット」(FLR)は、PCI Expressデバイスの単一の機能にのみ影響するリセットです。PCIeデバイス全体をリセットしないでください。PCIe仕様では、機能レベルのリセットを実装する必要はありません。機能レベルリセットは、PCI構成スペースのPCIエクスプレス機能構造内の機能のデバイス制御レジスタに機能レベルリセット開始ビットを設定することにより開始されます。
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の電源ボタンを押すのに似ています。