Les réinitialisations dans PCI express sont un peu complexes. Il existe deux principaux types de réinitialisation: la réinitialisation conventionnelle et la réinitialisation au niveau de la fonction. Il existe également deux types de réinitialisations conventionnelles, les réinitialisations fondamentales et les réinitialisations non fondamentales. Voir la spécification PCI express pour tous les détails.
Une «réinitialisation à froid» est une réinitialisation fondamentale qui a lieu après la mise sous tension d'un périphérique PCIe. Il ne semble pas y avoir de moyen standard de déclencher une réinitialisation à froid, sauf pour éteindre et rallumer le système. Sur mes machines, le /sys/bus/pci/slots
répertoire est vide.
Une «réinitialisation à chaud» est une réinitialisation fondamentale qui se déclenche sans couper l'alimentation de l'appareil. Il ne semble y avoir aucun moyen standard de déclencher une réinitialisation à chaud.
Une «réinitialisation à chaud» est une réinitialisation conventionnelle qui est déclenchée sur une liaison PCI express. Une réinitialisation à chaud est déclenchée soit lorsqu'une liaison est forcée au repos électrique, soit en envoyant des ensembles ordonnés TS1 et TS2 avec le bit de réinitialisation à chaud défini. Le logiciel peut lancer une réinitialisation à chaud en définissant puis en effaçant le bit de réinitialisation du bus secondaire dans le registre de contrôle de pont dans l'espace de configuration PCI du port de pont en amont de l'appareil.
Une «réinitialisation au niveau de la fonction» (FLR) est une réinitialisation qui affecte uniquement une seule fonction d'un périphérique PCI express. Il ne doit pas réinitialiser l'ensemble du périphérique PCIe. L'implémentation de réinitialisations au niveau des fonctions n'est pas requise par la spécification PCIe. Une réinitialisation au niveau de la fonction est lancée en définissant le bit de réinitialisation au niveau de la fonction de lancement dans le registre de commande de périphérique de la fonction dans la structure de capacité PCI express dans l'espace de configuration PCI.
Linux expose la fonctionnalité de réinitialisation au niveau de la fonction sous la forme de /sys/bus/pci/devices/$dev/reset
. L'écriture d'un 1 dans ce fichier lancera une réinitialisation au niveau de la fonction sur la fonction correspondante. Notez que cela n'affecte que cette fonction spécifique du périphérique, pas l'ensemble du périphérique, et les périphériques ne sont pas nécessaires pour implémenter des réinitialisations au niveau des fonctions selon la spécification PCIe.
Je ne connais aucune méthode «sympa» pour déclencher une réinitialisation à chaud (il n'y a pas d'entrée sysfs pour cela). Cependant, il est possible d'utiliser setpci pour ce faire:
#!/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"
Assurez-vous que tous les pilotes connectés sont déchargés avant d'exécuter ce script. Ce script tentera de supprimer le périphérique PCIe, puis commandera au port du commutateur en amont d'émettre une réinitialisation à chaud, puis tentera de réanalyser le bus PCIe. Ce script a également été testé uniquement sur des appareils avec une seule fonction, il peut donc avoir besoin d'être retravaillé pour les appareils avec plusieurs fonctions.
reboot -f
? Cela revient à appuyer sur le bouton d'alimentation du CPU.