Сброс в PCI Express немного сложен. Существует два основных типа сброса: обычный сброс и сброс на уровне функций. Есть также два типа обычных сбросов: фундаментальные и неосновные. См. Спецификацию PCI Express для всех деталей.
«Холодный сброс» - это фундаментальный сброс, который происходит после подачи питания на устройство PCIe. Похоже, не существует стандартного способа холодного сброса, за исключением выключения и повторного включения системы. На моих машинах /sys/bus/pci/slots
каталог пуст.
«Теплый сброс» - это основной сброс, который запускается без отключения питания устройства. Похоже, не существует стандартного способа запуска «горячего» сброса.
«Горячий сброс» - это обычный сброс, который запускается по каналу PCI Express. Горячий сброс запускается, когда канал принудительно переключается в электрический режим, или путем отправки упорядоченных наборов TS1 и TS2 с установленным битом горячего сброса. Программное обеспечение может инициировать «горячий» сброс, установив, а затем сбросив бит сброса вторичной шины в регистре управления мостом в пространстве конфигурации PCI порта моста перед устройством.
«Сброс на уровне функций» (FLR) - это сброс, который влияет только на одну функцию устройства PCI Express. Он не должен сбрасывать все устройство PCIe. Реализация сброса на уровне функций не требуется в спецификации PCIe. Сброс на уровне функций инициируется установкой бита инициализации сброса на уровне функций в регистре управления устройством функции в структуре возможностей PCI Express в пространстве конфигурации 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
? Это похоже на нажатие кнопки питания процессора.