Los reinicios en PCI express son un poco complejos. Hay dos tipos principales de restablecimientos: restablecimiento convencional y restablecimiento a nivel de función. También hay dos tipos de restablecimientos convencionales, restablecimientos fundamentales y restablecimientos no fundamentales. Consulte la especificación PCI express para todos los detalles.
Un 'restablecimiento en frío' es un restablecimiento fundamental que se realiza después de que se aplica alimentación a un dispositivo PCIe. Parece que no hay una forma estándar de activar un reinicio en frío, salvo para apagar y volver a encender el sistema. En mis máquinas, el /sys/bus/pci/slots
directorio está vacío.
Un 'reinicio en caliente' es un reinicio fundamental que se activa sin desconectar la alimentación del dispositivo. Parece que no hay una forma estándar de activar un reinicio en caliente.
Un 'restablecimiento en caliente' es un restablecimiento convencional que se activa a través de un enlace PCI express. Se activa un restablecimiento en caliente cuando un enlace se fuerza a inactividad eléctrica o al enviar conjuntos ordenados TS1 y TS2 con el conjunto de bits de restablecimiento en caliente. El software puede iniciar un restablecimiento en caliente configurando y luego borrando el bit de restablecimiento del bus secundario en el registro de control del puente en el espacio de configuración PCI del puerto del puente aguas arriba del dispositivo.
Un 'restablecimiento de nivel de función' (FLR) es un restablecimiento que afecta solo una función de un dispositivo PCI express. No debe restablecer todo el dispositivo PCIe. La implementación de restablecimientos a nivel de función no es requerida por la especificación PCIe. Un restablecimiento de nivel de función se inicia configurando el bit de restablecimiento de nivel de función de inicio en el registro de control de dispositivo de la función en la estructura de capacidad PCI express en el espacio de configuración de PCI.
Linux expone la funcionalidad de restablecimiento a nivel de función en forma de /sys/bus/pci/devices/$dev/reset
. Escribir un 1 en este archivo iniciará un restablecimiento de nivel de función en la función correspondiente. Tenga en cuenta que esto solo afecta esa función específica del dispositivo, no todo el dispositivo, y no se requiere que los dispositivos implementen restablecimientos de nivel de función según la especificación PCIe.
No conozco ningún método 'agradable' para activar un reinicio en caliente (no hay entrada de sysfs para eso). Sin embargo, es posible usar setpci para hacerlo:
#!/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"
Asegúrese de que todos los controladores conectados estén descargados antes de ejecutar este script. Este script intentará eliminar el dispositivo PCIe, luego ordenará al puerto del interruptor ascendente que emita un restablecimiento en caliente, luego intentará volver a escanear el bus PCIe. Este script también se ha probado solo en dispositivos con una sola función, por lo que puede necesitar un poco de reelaboración para dispositivos con múltiples funciones.
reboot -f
? Esto es similar a presionar el botón de encendido de la CPU.