Как сделать ИСТИННОЕ повторное сканирование шины PCIe

У меня есть FPGA (как и большинство людей, задающих этот вопрос), который настраивается после того, как мое ядро ​​Linux выполняет начальное сканирование и перечисление шины PCIe. Как вы можете догадаться, FPGA реализует конечную точку PCIe.

Я хотел бы, чтобы ядро ​​PCIe пересчитывало ВСЮ шину PCIe, чтобы моя ПЛИС отображалась и я мог загрузить свой драйверный модуль. Я также хотел бы иметь возможность поменять местами загрузку ПЛИС для другой конфигурации. Я имею в виду, что хотел бы иметь возможность:

  1. Загрузочный Linux
  2. Настроить ПЛИС
  3. Перечислите конечную точку PCIe и загрузочный модуль
  4. Удалить конечную точку PCIe
  5. Переконфигурировать FPGA
  6. Пересчитать конечную точку PCIe

Все без перезагрузки Linux

Вот решения, которые были предложены в другом месте, но не решают проблему.

echo 1 > /sys/bus/pci/rescan Кажется, это работает (только иногда), и это не работает, если я хочу, чтобы загрузить FPGA после того, как она была впервые перечислена.

Вот довольно инвазивный метод (который я не проверял), который кто-то предлагал и в других местах. https://community.freescale.com/thread/305355

Можно ли использовать Hotplug/ средства управления питанием PCIe для этой работы? Если да, есть ли хорошие ресурсы для использования системы Hotplug с PCIe? (LDD не совсем достаточно подробно освещает это)

2 ответа

Повторное перечисление шины / дерева PCIe через echo 1 > /sys/bus/pci/rescan это правильное решение. Мы используем это так же, как вы описали это.

Мы используем echo 1 > $pcidevice/remove отключить драйвер от устройства и отсоединить устройство от дерева. Драйвер (xillybus) не выгружен, просто отключен.

Лучшим решением является повторное сканирование только узла, к которому подключена ваша FPGA. Это уменьшает общее воздействие на систему.

Этот метод используется в облачной системе RC3E FPGA.

Это действительно зависит от того, что именно изменено в FPGA. Проблема заключается в том, как выполняется перечисление и назначение адресов PCIe, особенно в том, как настроены переключатели PCIe. Распределение ДОЛЖНО выполняться за один раз в качестве поиска в глубину. После этого невозможно вставить дополнительные номера шины или адресное пространство без изменения всех последующих выделений, что потребует перезагрузки всех соответствующих драйверов устройств. По сути, после того, как шина пронумерована и адреса назначены, вы не можете изменить общие распределения без повторного перечисления всей шины, что требует перезагрузки. Предварительное выделение ресурсов на конкретный порт PCIe может решить эту проблему и требуется для горячего подключения PCIe.

Если конфигурация PCIe BAR не изменилась, то обычно достаточно выполнить удаление / горячий сброс/ повторное сканирование и перезагрузка не требуется.

Если конфигурация BAR изменилась, то это отдельная история. Если новые БАРЫ меньше, то проблем быть не должно. Но если новые полосы BAR больше или имеется больше полос, если для порта коммутатора, к которому подключено устройство, выделено недостаточно адресного пространства, то эти полосы не могут быть выделены адресным пространством, и устройство не сможет выполнить перечисление. В этом случае требуется перезагрузка, чтобы можно было переназначить ресурсы. Не забывайте, что есть также 32-битные BAR и 64-битные BAR, и эти BAR назначаются из двух разных пулов адресного пространства, поэтому изменение типов BAR также может потребовать перезагрузки для повторного перечисления.

Если вы переходите с одного устройства на другое (например, с пустой ПЛИС на настроенную ПЛИС), то, возможно, потребуется переназначить номера шин, что потребует перезагрузки.

От доктора

Вот как сбросить Vegas до того же, как сброс в Windows. Это основано на ID поставщика.

lspci -n | grep 1002: | egrep -v ".1"| awk '{print "find /sys | grep ""$1"/rescan" -| tac -;"}' | sh - | sed s/^/echo\ 1\ >\ "&/g | sed s/$/"/g

Вывод этого положить в ваш /etc/rc.local сбросить ваш Vegas после загрузки аналогично сценарию перезапуска devcon.

echo 1 > "/sys/devices/pci0000:00/0000:00:01.0/0000:01:00.0/rescan"
echo 1 > "/sys/devices/pci0000:00/0000:00:1c.5/0000:03:00.0/rescan"
echo 1 > "/sys/devices/pci0000:00/0000:00:1d.0/0000:06:00.0/rescan"
echo 1 > "/sys/devices/pci0000:00/0000:00:1d.1/0000:07:00.0/rescan"
Другие вопросы по тегам