Перейти к содержанию
    

MSI-X Interrupt

Приветствую.

В системе используется ядро AXI Bridge for PCIe. Пытаюсь использовать MSI-X прерывания. Ядро в стандартной конфигурации поддерживает два MSI-X прерывания. В драйвере Linux Kernel используется функция pci_enable_msix_range(pdev, msixentries, 1, 2), которая разрешает два прерывания.

lspci -vv для устройства показывает следующее:

01:00.0 Multimedia controller: Xilinx Corporation Device 7024
       Subsystem: Xilinx Corporation Device 0007
       Control: I/O+ Mem+ BusMaster+ SpecCycle- MemWINV- VGASnoop- ParErr- Stepping- SERR- FastB2B- DisINTx+
       Status: Cap+ 66MHz- UDF- FastB2B- ParErr- DEVSEL=fast >TAbort- <TAbort- <MAbort- >SERR- <PERR- INTx+
       Latency: 0, Cache Line Size: 64 bytes
       Interrupt: pin A routed to IRQ 16
       Region 0: Memory at f7e20000 (64-bit, non-prefetchable) [size=4K]
       Region 2: Memory at f7e00000 (64-bit, non-prefetchable) [size=128K]
       Capabilities: [80] Power Management version 3
               Flags: PMEClk- DSI- D1- D2- AuxCurrent=0mA PME(D0-,D1-,D2-,D3hot-,D3cold-)
               Status: D0 NoSoftRst+ PME-Enable- DSel=0 DScale=0 PME-
       Capabilities: [b0] MSI-X: Enable+ Count=2 Masked-
               Vector table: BAR=0 offset=00000200
               PBA: BAR=0 offset=00000280
       Capabilities: [c0] Express (v2) Endpoint, MSI 00
               DevCap:	MaxPayload 512 bytes, PhantFunc 0, Latency L0s <64ns, L1 <1us
                       ExtTag- AttnBtn- AttnInd- PwrInd- RBE+ FLReset-
               DevCtl:	Report errors: Correctable- Non-Fatal- Fatal- Unsupported-
                       RlxdOrd- ExtTag- PhantFunc- AuxPwr- NoSnoop+
                       MaxPayload 256 bytes, MaxReadReq 512 bytes
               DevSta:	CorrErr+ UncorrErr- FatalErr- UnsuppReq+ AuxPwr- TransPend-
               LnkCap:	Port #0, Speed 5GT/s, Width x4, ASPM not supported, Exit Latency L0s unlimited, L1 unlimited
                       ClockPM- Surprise- LLActRep- BwNot-
               LnkCtl:	ASPM Disabled; RCB 64 bytes Disabled- CommClk+
                       ExtSynch- ClockPM- AutWidDis- BWInt- AutBWInt-
               LnkSta:	Speed 5GT/s, Width x4, TrErr- Train- SlotClk+ DLActive- BWMgmt- ABWMgmt-
               DevCap2: Completion Timeout: Range B, TimeoutDis+, LTR-, OBFF Not Supported
               DevCtl2: Completion Timeout: 50us to 50ms, TimeoutDis-, LTR-, OBFF Disabled
               LnkCtl2: Target Link Speed: 5GT/s, EnterCompliance- SpeedDis-
                        Transmit Margin: Normal Operating Range, EnterModifiedCompliance- ComplianceSOS-
                        Compliance De-emphasis: -6dB
               LnkSta2: Current De-emphasis Level: -3.5dB, EqualizationComplete-, EqualizationPhase1-
                        EqualizationPhase2-, EqualizationPhase3-, LinkEqualizationRequest-
       Capabilities: [100 v2] Advanced Error Reporting
               UESta:	DLP- SDES- TLP- FCP- CmpltTO- CmpltAbrt- UnxCmplt- RxOF- MalfTLP- ECRC- UnsupReq- ACSViol-
               UEMsk:	DLP- SDES- TLP- FCP- CmpltTO- CmpltAbrt- UnxCmplt- RxOF- MalfTLP- ECRC- UnsupReq- ACSViol-
               UESvrt:	DLP+ SDES+ TLP- FCP+ CmpltTO- CmpltAbrt- UnxCmplt- RxOF+ MalfTLP+ ECRC- UnsupReq- ACSViol-
               CESta:	RxErr- BadTLP- BadDLLP- Rollover- Timeout- NonFatalErr+
               CEMsk:	RxErr- BadTLP- BadDLLP- Rollover- Timeout- NonFatalErr+
               AERCap:	First Error Pointer: 00, GenCap- CGenEn- ChkCap- ChkEn-
       Kernel driver in use: htg_v7_g3

В драйвере реализованы два обработчика прерывания, которые вешаются на выделенные pci_enable_msix_range() MSI-X вектора. После инициализации драйвера заполняется таблица векторов MSI-X (Рисунок 1).

Реализовано два BAR-a: BAR0 - таблица векторов MSI-X, BAR2 - регистры устройств.

Ядро AXI Bridge for PCIe имеет интерфейс cfg_interrupt_msix (Рисунок 2), к нему подключается MSI-X Interrupt controller. На MSI-X Interrupt controller заводится сигнал от PIO (пока, тестовый режим), по высокому уровню от PIO MSI-X Interrupt controller генерит прерывание MSI-X (Рисунок 3), но система на него никак не реагирует (обработчик не срабатывает).

Что тут сделано неправильно? Кто должен выставлять биты PBA, указывающие, какой вектор сработал?

post-63539-1447787881_thumb.png

post-63539-1447787892_thumb.png

post-63539-1447787899_thumb.png

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

MSI и MSI-X - это пакеты. они должны быть сформированы вашим кодом в плис, и отправлены в axi slave pcie-корки.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

MSI и MSI-X - это пакеты. они должны быть сформированы вашим кодом в плис, и отправлены в axi slave pcie-корки.

Вот это я и пытаюсь сделать, но у ядра PCIe есть интерфейс cfg_interrupt_msix, который, как понимаю, и предназначен для этих целей. Сделал, как описано в доке (третий рисунок выше), но оно не сгенерило MSI-X.

 

 

Вот эту штуку (рисунок) из pg023_v7_pcie_gen3.pdf пытаюсь реализовать, должно сгенерировать MSI-X прерывание.

post-63539-1447793571_thumb.jpg

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Ошибка в том, что IP Integrator генерит ядро AXI Bridge for PCIe с ошибкой (Vivado 2015.2). Данная корка строится на основе ядра Gen3 Integrated Block for PCIe, для которого порт cfg_interrupt_msix_int никуда не подключен. Если есть необходимость пересобрать систему, приходится вручную править файлы ядра AXI Bridge for PCIe :(

 

В версии 2015.3 баг остался.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Приветствую.

На рисунке представлена работа MSI-X контроллера прерываний. Пока всё работает в тестовом режиме, прерывание срабатывает от порта GPIO. Портом PIO управляет MicroBlaze. Использую подряд две функции

XGpio_DiscreteWrite(&gpio_1, 1, 1);
XGpio_DiscreteWrite(&gpio_1, 1, 0);

Как видно из рисунка, пока MicroBlaze меняет данные порта GPIO1, контроллер MSI-X прерываний успевает сгенерировать 8 прерываний. Ядро AXI Bridge for PCIe выставляет сигнал cfg_interrupt_msix_sent, что означает (я так понял) разрешено отправлять следующее прерывание. При этом обработчик прерывания в Linux Kernel срабатывает 2-3 раза (а не 8!!!). Получается cfg_interrupt_msix_sent - это сигнал от ядра PCIe, что прерывание отправлено, но он не даёт гарантии, что оно обработано системой. Вопрос, как разрулить эту ситуацию? Как определить, что ядро Linux обработало прерывание и когда можно генерировать следующее?

 

Пока добавляю в контроллер MSI-X прерываний детектор фронта прерывания, чтоб исключить ситуацию многократной отправки MSI-X на одно прерывание от одного источника. Но это не решает проблему, когда ядро ответило сигналом cfg_interrupt_msix_sent, что можно отправлять следующее (допустим, пришло прерыване от другого источника), а система ещё не обработала первое.

post-63539-1448009016_thumb.png

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

sent - это действительно подтверждение отправки.

т.е. если нужно отправить прерывание, то int поднимается и удерживается до тех пор пока не поднимется sent.

абсолютно идентично как для транзакции широко всеми используемого ready-valid интерфейса.

 

что касается обмена пользовательскими данными и прерываниями между device и host - то стандарта на эту тему нет.

каждый строчит кто как хочет.

если вам нужно гарантированная обработка каждого прерывания ядром linux - то вы должны предусмотреть и определить этот механизм сами, как вам будет удобнее. или производительнее. или ещё по каким причинам.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

sent - это действительно подтверждение отправки.

т.е. если нужно отправить прерывание, то int поднимается и удерживается до тех пор пока не поднимется sent.

Пока так и сделал, работает, но не соответствует тому, как описано в доке Xilinx (рисунок из доки выше). Пробовал сделать, как в мануале, длительность int один такт - работать не захотело, хочу ещё проверить дительность int 2-3 такта.

 

что касается обмена пользовательскими данными и прерываниями между device и host - то стандарта на эту тему нет.

каждый строчит кто как хочет.

если вам нужно гарантированная обработка каждого прерывания ядром linux - то вы должны предусмотреть и определить этот механизм сами, как вам будет удобнее. или производительнее. или ещё по каким причинам.

Конечно хочу, чтоб обработчик прерывания в ядре срабатывал на каждое отправляемое девайсом MSI-X, но не понимаю, как это реализуется.

MSI-X Capability Structure содержит указатели на MSI-X Table Structure и MSI-X PBA (Pending Bit Array) Structure. С MSI-X Table Structure вроде как всё понятно, а вот как используется и для чего необходима MSI-X PBA Structure?

 

 

Посмотрел пример реализации PCIe DMA для Virtex 7 с opencores.org (там как раз используются MSI-X), но в примере для контроллера прерываний даже сигнал sent не используется, отправили и забыли :(

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Конечно хочу, чтоб обработчик прерывания в ядре срабатывал на каждое отправляемое девайсом MSI-X, но не понимаю, как это реализуется.

MSI-X Capability Structure содержит указатели на MSI-X Table Structure и MSI-X PBA (Pending Bit Array) Structure. С MSI-X Table Structure вроде как всё понятно, а вот как используется и для чего необходима MSI-X PBA Structure?

ключевое слово Pending - ожидающие.

т.е. вы отправляя 8 прерываний на каждом из них записываете с PBA очередной бит.

софт, получив всего 2-3 прерывания, определяет сколько же на самом деле событий произошло, читая PBA и сбрасывая биты, соответствующие обработанным данным.

 

 

если данных, которые нужно перегнать у вас очень много, и прерывания у вас идут буквально одно за другим, то стоит рассмотреть вариант NAPI - т.е. прерывания используются, но не для передачи данных, а для перезарядки указателей. При этом софт работает в Polling-режиме, т.е. принудительно каждые N-мсек опрашивает устройство, а данные затем сливаются SGDMA с большим списком указателей но всего одним прерыванием. При этом софт не тратит время на постоянное переключение контекста для обработки большого количества мелких прерываний.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...