|
|
  |
MSI-X Interrupt |
|
|
|
Nov 17 2015, 19:25
|
Профессионал
    
Группа: Свой
Сообщений: 1 404
Регистрация: 11-03-11
Из: Минск, Беларусь
Пользователь №: 63 539

|
Приветствую. В системе используется ядро AXI Bridge for PCIe. Пытаюсь использовать MSI-X прерывания. Ядро в стандартной конфигурации поддерживает два MSI-X прерывания. В драйвере Linux Kernel используется функция pci_enable_msix_range(pdev, msixentries, 1, 2), которая разрешает два прерывания. lspci -vv для устройства показывает следующее: CODE 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, указывающие, какой вектор сработал?
Эскизы прикрепленных изображений
|
|
|
|
|
Nov 17 2015, 20:52
|
Профессионал
    
Группа: Свой
Сообщений: 1 404
Регистрация: 11-03-11
Из: Минск, Беларусь
Пользователь №: 63 539

|
Цитата(krux @ Nov 17 2015, 23:00)  MSI и MSI-X - это пакеты. они должны быть сформированы вашим кодом в плис, и отправлены в axi slave pcie-корки. Вот это я и пытаюсь сделать, но у ядра PCIe есть интерфейс cfg_interrupt_msix, который, как понимаю, и предназначен для этих целей. Сделал, как описано в доке (третий рисунок выше), но оно не сгенерило MSI-X. Вот эту штуку (рисунок) из pg023_v7_pcie_gen3.pdf пытаюсь реализовать, должно сгенерировать MSI-X прерывание.
Эскизы прикрепленных изображений
|
|
|
|
|
Nov 20 2015, 08:43
|
Профессионал
    
Группа: Свой
Сообщений: 1 404
Регистрация: 11-03-11
Из: Минск, Беларусь
Пользователь №: 63 539

|
Приветствую. На рисунке представлена работа 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, что можно отправлять следующее (допустим, пришло прерыване от другого источника), а система ещё не обработала первое.
Эскизы прикрепленных изображений
|
|
|
|
|
Nov 20 2015, 20:50
|
Профессионал
    
Группа: Свой
Сообщений: 1 404
Регистрация: 11-03-11
Из: Минск, Беларусь
Пользователь №: 63 539

|
Цитата(krux @ Nov 20 2015, 22:48)  sent - это действительно подтверждение отправки. т.е. если нужно отправить прерывание, то int поднимается и удерживается до тех пор пока не поднимется sent. Пока так и сделал, работает, но не соответствует тому, как описано в доке Xilinx (рисунок из доки выше). Пробовал сделать, как в мануале, длительность int один такт - работать не захотело, хочу ещё проверить дительность int 2-3 такта. Цитата(krux @ Nov 20 2015, 22:48)  что касается обмена пользовательскими данными и прерываниями между 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 не используется, отправили и забыли
|
|
|
|
|
Nov 21 2015, 07:51
|
Профессионал
    
Группа: Свой
Сообщений: 1 700
Регистрация: 2-07-12
Из: дефолт-сити
Пользователь №: 72 596

|
Цитата(doom13 @ Nov 20 2015, 23:50)  Конечно хочу, чтоб обработчик прерывания в ядре срабатывал на каждое отправляемое девайсом 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 с большим списком указателей но всего одним прерыванием. При этом софт не тратит время на постоянное переключение контекста для обработки большого количества мелких прерываний.
--------------------
провоцируем неудовлетворенных провокаторов с удовольствием.
|
|
|
|
|
  |
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|