doom13 0 17 ноября, 2015 Опубликовано 17 ноября, 2015 · Жалоба Приветствую. В системе используется ядро 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, указывающие, какой вектор сработал? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
krux 8 17 ноября, 2015 Опубликовано 17 ноября, 2015 · Жалоба MSI и MSI-X - это пакеты. они должны быть сформированы вашим кодом в плис, и отправлены в axi slave pcie-корки. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
doom13 0 17 ноября, 2015 Опубликовано 17 ноября, 2015 · Жалоба MSI и MSI-X - это пакеты. они должны быть сформированы вашим кодом в плис, и отправлены в axi slave pcie-корки. Вот это я и пытаюсь сделать, но у ядра PCIe есть интерфейс cfg_interrupt_msix, который, как понимаю, и предназначен для этих целей. Сделал, как описано в доке (третий рисунок выше), но оно не сгенерило MSI-X. Вот эту штуку (рисунок) из pg023_v7_pcie_gen3.pdf пытаюсь реализовать, должно сгенерировать MSI-X прерывание. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
doom13 0 18 ноября, 2015 Опубликовано 18 ноября, 2015 · Жалоба Ошибка в том, что IP Integrator генерит ядро AXI Bridge for PCIe с ошибкой (Vivado 2015.2). Данная корка строится на основе ядра Gen3 Integrated Block for PCIe, для которого порт cfg_interrupt_msix_int никуда не подключен. Если есть необходимость пересобрать систему, приходится вручную править файлы ядра AXI Bridge for PCIe :( В версии 2015.3 баг остался. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
doom13 0 20 ноября, 2015 Опубликовано 20 ноября, 2015 · Жалоба Приветствую. На рисунке представлена работа 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, что можно отправлять следующее (допустим, пришло прерыване от другого источника), а система ещё не обработала первое. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
krux 8 20 ноября, 2015 Опубликовано 20 ноября, 2015 · Жалоба sent - это действительно подтверждение отправки. т.е. если нужно отправить прерывание, то int поднимается и удерживается до тех пор пока не поднимется sent. абсолютно идентично как для транзакции широко всеми используемого ready-valid интерфейса. что касается обмена пользовательскими данными и прерываниями между device и host - то стандарта на эту тему нет. каждый строчит кто как хочет. если вам нужно гарантированная обработка каждого прерывания ядром linux - то вы должны предусмотреть и определить этот механизм сами, как вам будет удобнее. или производительнее. или ещё по каким причинам. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
doom13 0 20 ноября, 2015 Опубликовано 20 ноября, 2015 · Жалоба 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 не используется, отправили и забыли :( Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
krux 8 21 ноября, 2015 Опубликовано 21 ноября, 2015 · Жалоба Конечно хочу, чтоб обработчик прерывания в ядре срабатывал на каждое отправляемое девайсом 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 с большим списком указателей но всего одним прерыванием. При этом софт не тратит время на постоянное переключение контекста для обработки большого количества мелких прерываний. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться