¿Cómo reiniciar / apagar y encender un dispositivo PCIe?

20

Tengo un dispositivo PCIe que solo funciona correctamente cuando la computadora está completamente apagada y luego se vuelve a encender. Emitir un comando rebooto reboot -pcomando simple no parece apagar y encender la tarjeta PCIe, lo que hace que no funcione después del reinicio.

¿Hay alguna forma de, desde el sistema operativo, apagar y encender un dispositivo en una ranura PCIe? Puedo encontrarlo /sys/bus/pci/devices/0000*/, pero no puedo encontrar la manera de restablecer correctamente la placa. El poder de alternancia parece ser la única forma.

Salvo eso, ¿puedo cambiar una configuración en algún lugar que causará un ciclo de energía completo en un rebootcomando?

Estoy ejecutando Ubuntu 12.10 por cierto.

zachd1_618
fuente
¿Lo intentaste reboot -f? Esto es similar a presionar el botón de encendido de la CPU.
ktan
1
Hace dos años, el OP señaló que un soft rebootno funcionaba. Tu reboot -ftodavía es un reinicio suave.
roaima

Respuestas:

16

Método potencial # 1

Creo que puedes hacerlo con estos comandos:

inhabilitar

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

habilitar

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

¿Dónde $NUMBERestá el número de la ranura PCI?

lspci -vvpuede ayudar a identificar el dispositivo. Esto no está muy bien documentado ...

Método potencial # 2

Encontré este hilo en U&L , problema similar: hay algunas respuestas a esa pregunta que dicen que puede restablecer con este comando:

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

Sin embargo, ¡leería las respuestas allí! ¡Hay condiciones para hacerlo de esta manera! ¡Específicamente leería esta respuesta !

Método potencial # 3

Hay un comando Unix setpcique puede proporcionarle un método para restablecer un dispositivo en el bus PCI.

No vi ningún ejemplo específico con este comando, por lo que tendrá que buscar ejemplos en Google y consultar la página de manual . Seguiría este comando ligeramente hasta que esté seguro de su uso. Por lo que he leído al respecto, está manipulando el hardware directamente, por lo que siempre hay riesgos al hacerlo usted mismo en lugar de usar una herramienta que expone este tipo de funcionalidad.

slm
fuente
1
No aparece nada en las ranuras, a pesar de que tengo varias tarjetas conectadas. Tengo un directorio de alimentación /sys/bus/pci/devices/$NUMBER/. Pero nada parece justificar la configuración 0 o 1
zachd1_618
1
Encontré este hilo en U&L , problema similar: hay algunas respuestas a esa Q que dicen que puede restablecer con esto: echo "1"> / sys / bus / pci / devices / $ NUMBER / reset. Sin embargo, lea esa Q, ¡hay condiciones para hacerlo de esa manera!
slm
Gracias por el enlace. Sin embargo, he intentado eso y no parece hacer nada. Específicamente, el dispositivo no enciende y el sistema todavía sabe que está allí. (Cuando la tarjeta está encendida y enchufada, hay dispositivos en / dev que puedo ver). No desaparecen cuando yo echo "1" > ....
zachd1_618
1
¿Está descargando los módulos del kernel para esa tarjeta antes del ciclo de alimentación? Creo que tienes que hacer eso también.
slm
1
Creo que comprobaré el código fuente del núcleo para ver si alternar powerrealmente lo coloca en D3.
bosque
7

removey rescanpermitirá que el kernel alimente por ciclos el dispositivo PCI sin reboot:

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

donde DDDD.BB.DD.F = Dominio: Bus: Device.Function

ciber
fuente
echo "1"> / sys / bus / pci / rescan me funcionó en la ranura mini pci de lenovo g560. Conecté la tarjeta minipci USB 3.0. El sistema es Ubuntu 16.04 x64
kodmanyagha
No funciona para todos los dispositivos. Tengo un adaptador de red Cavium que no se apaga por ese método, ya que todavía puedo acceder a su arranque en U cuando uso una línea en serie.
Eric
7

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/slotsdirectorio 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.

alex.forencich
fuente
Este script funcionó para mi AMD RX480. Contexto: transferencia de PCI a un invitado Win10, luego apagar o reiniciar el invitado. Iniciar el invitado nuevamente (sin usar este script) se bloqueará si la GPU todavía está conectada. Ejecutar este script en el medio solucionó el problema
小 太郎