As redefinições no PCI express são um pouco complexas. Existem dois tipos principais de reinicialização - reconfiguração convencional e redefinição no nível de função. Existem também dois tipos de reconfigurações convencionais, reconfigurações fundamentais e reconfigurações não fundamentais. Veja a especificação do PCI Express para todos os detalhes.
Uma 'reinicialização a frio' é uma redefinição fundamental que ocorre depois que a energia é aplicada a um dispositivo PCIe. Parece não haver nenhuma maneira padrão de acionar uma reinicialização a frio, exceto por desligar o sistema e ligá-lo novamente. Em minhas máquinas, o diretório /sys/bus/pci/slots
está vazio.
Um 'warm reset' é um reset fundamental que é disparado sem desconectar a energia do dispositivo. Parece não haver uma maneira padrão de acionar uma reinicialização a quente.
Um 'hot reset' é um reset convencional que é acionado através de um link expresso PCI. Uma reinicialização a quente é acionada quando um link é forçado para a inatividade elétrica ou pelo envio de conjuntos ordenados TS1 e TS2 com o conjunto de bits de reinicialização a quente. O software pode iniciar uma reinicialização a quente definindo e, em seguida, limpando o bit de reinicialização do barramento secundário no registro de controle da ponte na porta da ponte a montante do dispositivo no espaço de configuração da PCI.
Uma 'redefinição de nível de função' (FLR) é uma redefinição que afeta apenas uma única função de um dispositivo expresso PCI. Não deve redefinir todo o dispositivo PCIe. A implementação de redefinições no nível da função não é exigida pela especificação PCIe. Uma redefinição de nível de função é iniciada configurando o bit de redefinição de nível de função inicial no registro de controle de dispositivo da função na estrutura de capacidade expressa PCI no espaço de configuração PCI.
O Linux expõe a funcionalidade de redefinição do nível de função na forma de /sys/bus/pci/devices/$dev/reset
. Escrevendo um 1 para este arquivo irá iniciar uma redefinição de nível de função na função correspondente. Observe que isso afeta apenas essa função específica do dispositivo, não o dispositivo inteiro, e os dispositivos não precisam implementar redefinições no nível da função conforme a especificação PCIe.
Não estou ciente de nenhum método 'legal' para acionar uma reinicialização a quente. No entanto, é possível usar o setpci para fazer isso:
#!/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"
Certifique-se de que todos os drivers conectados estejam descarregados antes de executar este script. Este script tentará remover o dispositivo PCIe, em seguida, comandará a porta do switch upstream para emitir uma reinicialização a quente e, em seguida, tentar verificar novamente o barramento PCIe. Esse script também foi testado apenas em dispositivos com uma única função, portanto, pode ser necessário algum retrabalho para dispositivos com várias funções.