Как сбросить / отключить питание устройства PCIe?

20

У меня есть устройство PCIe, которое работает правильно только тогда, когда компьютер полностью выключен, а затем снова включен. Появление простой команды rebootили reboot -pкоманды не приводит к отключению питания карты PCIe, что приводит к тому, что она не работает после перезагрузки.

Есть ли способ из операционной системы отключить питание устройства в слоте PCIe? Я могу найти это в /sys/bus/pci/devices/0000*/, но я не могу понять, как правильно сбросить плату. Похоже, что переключающая сила - единственный путь.

За исключением этого, могу ли я изменить настройку где-нибудь, что вызовет полный цикл питания для rebootкоманды?

Кстати, я использую Ubuntu 12.10.

zachd1_618
источник
Ты пробовал reboot -f? Это похоже на нажатие кнопки питания процессора.
ktan
1
Два года назад ОП указывал, что софт rebootне работает. Ваша reboot -fвсе еще мягкая перезагрузка.
Роайма

Ответы:

16

Потенциальный метод № 1

Я думаю, что вы можете сделать это с помощью этих команд:

отключить

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

включить

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

Где $NUMBERномер слота PCI.

lspci -vvможет помочь идентифицировать устройство. Это не очень хорошо задокументировано ...

Потенциальный метод № 2

Я сталкивался с этой веткой на U & L , похожая проблема: есть некоторые ответы на этот вопрос, которые говорят, что вы можете сбросить с помощью этой команды:

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

Однако я бы прочитал ответы там! Есть условия, чтобы делать это таким образом! Конкретно я бы прочитал этот ответ !

Потенциальный метод № 3

Существует команда Unix setpci, которая может дать вам способ сброса устройства на шине PCI.

Я не видел никаких конкретных примеров с этой командой, поэтому вам придется поискать примеры в Google и просмотреть страницу руководства . Я бы слегка пошагнул с этой командой, пока вы не будете уверены в ее использовании. Из того, что я читал об этом, он напрямую манипулирует оборудованием, поэтому всегда есть риск сделать это самостоятельно, а не использовать инструмент, который демонстрирует этот тип функциональности!

SLM
источник
1
В слотах ничего не отображается, даже если у меня подключено несколько карт. У меня есть каталог питания /sys/bus/pci/devices/$NUMBER/. Но, кажется, ничто не гарантирует установки 0 или 1
zachd1_618
1
Я сталкивался с этой веткой о U & L , похожая проблема: есть некоторые ответы на этот вопрос, которые говорят, что вы можете сбросить с помощью этого: echo "1"> / sys / bus / pci / devices / $ NUMBER / reset. Прочитайте, что Q, хотя, есть условия вокруг, делающие это таким образом!
СЛМ
Спасибо за ссылку. Я пробовал это однако, и это, кажется, ничего не делает. В частности, устройство не выключается и система все еще знает, что оно есть. (Когда карта включена и подключена, в / dev есть устройства, которые я могу наблюдать). Они не исчезают, когда я echo "1" > ....
zachd1_618
1
Вы выгружаете модули ядра для этой карты до выключения питания? Я думаю, что ты должен сделать это также.
SLM
1
Я думаю, что проверю исходный код ядра, чтобы увидеть, powerдействительно ли переключение помещает его в D3.
лес
7

removeи rescanпозволит ядру циклически запитывать устройство PCI без reboot:

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

где DDDD.BB.DD.F = Домен: Шина: Device.Function

кибер
источник
echo "1"> / sys / bus / pci / rescan у меня работает в слоте lenovo g560 mini pci. Я подключил карту USB 3.0 minipci. Система Ubuntu 16.04 x64
кодманьяга
Это не работает для всех устройств. У меня есть сетевой адаптер Cavium, который не отключается этим способом, поскольку я все еще могу получить доступ к его загрузке при использовании последовательной линии.
Эрик
7

Сброс в PCI Express немного сложен. Существует два основных типа сброса: обычный сброс и сброс на уровне функций. Есть также два типа обычных сбросов: фундаментальные и неосновные. См. Спецификацию PCI Express для всех деталей.

«Холодный сброс» - это фундаментальный сброс, который происходит после подачи питания на устройство PCIe. Похоже, не существует стандартного способа холодного сброса, за исключением выключения и повторного включения системы. На моих машинах /sys/bus/pci/slotsкаталог пуст.

«Теплый сброс» - это основной сброс, который запускается без отключения питания устройства. Похоже, не существует стандартного способа запуска «горячего» сброса.

«Горячий сброс» - это обычный сброс, который запускается по каналу PCI Express. Горячий сброс запускается, когда канал принудительно переключается в электрический режим, или путем отправки упорядоченных наборов TS1 и TS2 с установленным битом горячего сброса. Программное обеспечение может инициировать «горячий» сброс, установив, а затем сбросив бит сброса вторичной шины в регистре управления мостом в пространстве конфигурации PCI порта моста перед устройством.

«Сброс на уровне функций» (FLR) - это сброс, который влияет только на одну функцию устройства PCI Express. Он не должен сбрасывать все устройство PCIe. Реализация сброса на уровне функций не требуется в спецификации PCIe. Сброс на уровне функций инициируется установкой бита инициализации сброса на уровне функций в регистре управления устройством функции в структуре возможностей PCI Express в пространстве конфигурации PCI.

Linux предоставляет функциональность сброса на уровне функций в форме /sys/bus/pci/devices/$dev/reset. Запись 1 в этот файл инициирует сброс уровня функции для соответствующей функции. Обратите внимание, что это влияет только на эту конкретную функцию устройства, а не на все устройство, и устройства не обязаны выполнять сброс на уровне функций согласно спецификации PCIe.

Я не знаю ни одного «хорошего» метода для запуска «горячего» сброса (для этого нет записи sysfs). Однако для этого можно использовать setpci:

#!/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"

Убедитесь, что все подключенные драйверы выгружены перед запуском этого скрипта. Этот сценарий попытается удалить устройство PCIe, затем подать команду на порт вышестоящего коммутатора для выполнения горячего сброса, а затем попытаться выполнить повторное сканирование шины PCIe. Этот сценарий также был протестирован только на устройствах с одной функцией, поэтому может потребоваться доработка для устройств с несколькими функциями.

alex.forencich
источник
Этот скрипт работал для моего AMD RX480. Контекст: прохождение PCI к гостю Win10, затем выключение или перезагрузка гостя. При повторном запуске гостя (без использования этого сценария) графический процессор все еще будет подключен. Выполнение этого скрипта в промежутке исправило проблему
小 太郎