Comment réinitialiser / éteindre puis rallumer un périphérique PCIe?

20

J'ai un périphérique PCIe qui ne fonctionne correctement que lorsque l'ordinateur est complètement éteint puis rallumé. L'émission d'une commande simple rebootou reboot -pne semble pas couper l'alimentation de la carte PCIe, ce qui l'empêche de fonctionner après le redémarrage.

Existe-t-il un moyen, à partir du système d'exploitation, de redémarrer un périphérique dans un emplacement PCIe? Je peux le trouver /sys/bus/pci/devices/0000*/, mais je ne sais pas comment réinitialiser correctement la carte. Basculer le pouvoir semble être le seul moyen.

Sauf cela, puis-je modifier un paramètre quelque part qui provoquera un cycle d'alimentation complet sur une rebootcommande?

Soit dit en passant, j'utilise Ubuntu 12.10.

zachd1_618
la source
As-tu essayé reboot -f? Cela revient à appuyer sur le bouton d'alimentation du CPU.
ktan
1
Il y a deux ans, le PO a souligné qu'un logiciel rebootne fonctionnait pas. Votre reboot -fest toujours un redémarrage en douceur.
roaima

Réponses:

16

Méthode potentielle n ° 1

Je pense que vous pouvez le faire avec ces commandes:

désactiver

echo 0 > /sys/bus/pci/slots/$NUMBER/power

activer

echo 1 > /sys/bus/pci/slots/$NUMBER/power

$NUMBERest le numéro de l'emplacement PCI.

lspci -vvpeut aider à identifier l'appareil. Ce n'est pas très bien documenté ...

Méthode potentielle n ° 2

Je suis tombé sur ce fil sur U&L , problème similaire: il y a des réponses à cette question qui disent que vous pouvez réinitialiser avec cette commande:

echo "1" > /sys/bus/pci/devices/$NUMBER/reset

Cependant, je lirais les réponses là-bas! Il y a des conditions pour le faire de cette façon! Plus précisément, je voudrais lire cette réponse !

Méthode potentielle n ° 3

Il existe une commande Unix setpci, qui peut vous donner une méthode pour réinitialiser un périphérique dans le bus PCI.

Je n'ai vu aucun exemple spécifique avec cette commande, vous devrez donc rechercher des exemples sur Google et parcourir la page de manuel . Je marcherais légèrement avec cette commande jusqu'à ce que vous ayez confiance en son utilisation. D'après ce que j'ai lu à ce sujet, il s'agit de manipuler le matériel directement et il y a donc toujours des risques à le faire vous-même par rapport à l'utilisation d'un outil qui expose ce type de fonctionnalité!

slm
la source
1
Rien n'apparaît dans les emplacements, même si plusieurs cartes sont branchées. J'ai un répertoire d'alimentation /sys/bus/pci/devices/$NUMBER/. Mais rien ne semble justifier le réglage 0 ou 1
zachd1_618
1
Je suis tombé sur ce fil sur U&L , problème similaire: il y a des réponses à ce Q qui disent que vous pouvez réinitialiser avec ceci: echo "1"> / sys / bus / pci / devices / $ NUMBER / reset. Lisez ce Q cependant, il y a des conditions pour le faire de cette façon!
slm
Merci pour le lien. J'ai essayé cela cependant et cela ne semble rien faire. Plus précisément, l'appareil ne redémarre pas et le système sait toujours qu'il est là. (Lorsque la carte est allumée et branchée, il y a des périphériques dans / dev que je peux regarder). Ils ne disparaissent pas quand je echo "1" > ....
zachd1_618
1
Déchargez-vous les modules du noyau pour cette carte avant le cycle d'alimentation? Je pense que vous devez également le faire.
slm
1
Je pense que je vais vérifier le code source du noyau pour voir si le basculement le powerplace réellement dans D3.
forêt
7

removeet rescanpermettra au noyau d'alimenter cycliquement le périphérique PCI sans reboot:

echo "1" > /sys/bus/pci/devices/DDDD\:BB\:DD.F//remove
sleep 1
echo "1" > /sys/bus/pci/rescan

où DDDD.BB.DD.F = Domaine: Bus: Device.Function

cyber
la source
echo "1"> / sys / bus / pci / rescan est travaillé pour moi dans le slot lenovo g560 mini pci. J'ai branché la carte minipci USB 3.0. Le système est Ubuntu 16.04 x64
kodmanyagha
Cela ne fonctionne pas pour tous les appareils. J'ai une carte réseau Cavium qui n'est pas mise hors tension par cette méthode car je peux toujours accéder à son u-boot lorsque j'utilise une ligne série.
Eric
7

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/slotsré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.

alex.forencich
la source
Ce script a fonctionné pour mon AMD RX480. Contexte: passage PCI à un invité Win10, puis arrêt ou redémarrage de l'invité. Le redémarrage de l'invité (sans utiliser ce script) se bloquerait si le GPU était toujours connecté. L'exécution de ce script entre les deux a résolu le problème
小 太郎