Reset di PCI express agak rumit. Ada dua jenis utama pengaturan ulang - reset konvensional, dan reset level fungsi. Ada juga dua jenis pengaturan ulang konvensional, pengaturan dasar dan pengaturan non-fundamental. Lihat spesifikasi PCI express untuk semua detailnya.
'Cold reset' adalah reset mendasar yang terjadi setelah daya diterapkan ke perangkat PCIe. Tampaknya tidak ada cara standar untuk memicu reset dingin, kecuali mematikan sistem dan menyalakan kembali. Di komputer saya, /sys/bus/pci/slots
direktori kosong.
'Warm reset' adalah reset mendasar yang dipicu tanpa memutus daya dari perangkat. Tampaknya tidak ada cara standar untuk memicu reset hangat.
'Hot reset' adalah pengaturan ulang konvensional yang dipicu pada tautan PCI express. Reset panas dipicu baik ketika tautan dipaksa ke idle listrik atau dengan mengirim set memerintahkan TS1 dan TS2 dengan set bit reset panas. Perangkat lunak dapat memulai reset panas dengan mengatur dan kemudian membersihkan bit reset bus sekunder di register kontrol jembatan di ruang konfigurasi PCI port jembatan hulu perangkat.
'Reset tingkat fungsi' (FLR) adalah pengaturan ulang yang hanya memengaruhi satu fungsi perangkat PCI express. Itu tidak boleh mereset seluruh perangkat PCIe. Menerapkan pengaturan tingkat fungsi tidak diperlukan oleh spesifikasi PCIe. Reset level fungsi dimulai dengan mengatur bit reset level fungsi mulai pada register kontrol perangkat fungsi dalam struktur kemampuan PCI express di ruang konfigurasi PCI.
Linux memperlihatkan fungsi reset level fungsi dalam bentuk /sys/bus/pci/devices/$dev/reset
. Menulis 1 ke file ini akan memulai reset tingkat fungsi pada fungsi yang sesuai. Perhatikan bahwa ini hanya memengaruhi fungsi spesifik perangkat tersebut, bukan keseluruhan perangkat, dan perangkat tidak diharuskan untuk mengimplementasikan pengaturan level fungsi sesuai dengan spesifikasi PCIe.
Saya tidak mengetahui adanya metode 'bagus' untuk memicu reset panas (tidak ada entri sysfs untuk itu). Namun, dimungkinkan untuk menggunakan setpci untuk melakukannya:
#!/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"
Pastikan semua driver yang terpasang diturunkan sebelum menjalankan skrip ini. Script ini akan mencoba untuk menghapus perangkat PCIe, kemudian memerintahkan port switch hulu untuk mengeluarkan reset panas, kemudian mencoba untuk memindai ulang bus PCIe. Skrip ini juga hanya diuji pada perangkat dengan fungsi tunggal, sehingga mungkin perlu pengerjaan ulang untuk perangkat dengan banyak fungsi.
reboot -f
? Ini mirip dengan menekan tombol daya CPU.