Примените прерывание msi что это
Архитектура ЭВМ
Компоненты ПК
Интерфейсы
Мини блог
Самое читаемое
Заказать каркасно-тентовые сооружения в Иркутске от производителя. Большой выбор приточно вытяжных вентиляционных систем тут.
PCI и PCI-X
Прерывания сообщениями — MSI
На шине PCI имеется прогрессивный механизм оповещения об асинхронных событиях, основанный на передаче сообщений MSI (Message Signaled Interrupts). Здесь для сигнализации запроса прерывания устройство запрашивает управление шиной и, получив его, посылает сообщение. Сообщение выглядит как обычная запись двойного слова в ячейку памяти, адрес (32-битный или 64-битный) и шаблон сообщения на этапе конфигурирования устройств записываются в конфигурационные регистры устройства (точнее, функции). В сообщении старшие 16 бит всегда нулевые, а младшие 16 бит несут информацию об источнике прерывания. Устройство (функция) могут нуждаться в сигнализации нескольких типов запросов; в соответствии с его потребностями и своими возможностями система указывает устройству (функции), сколько различных типов запросов оно может вырабатывать.
Возможность использования MSI описывается в конфигурационном пространстве структурой MSI Capability (CAP_ID = 05h), которая должна присутствовать в пространстве каждой функции, поддерживающей MSI. В структуре имеется 3 или 4 регистра (см. рисунок ниже):
По аппаратному сбросу MSI запрещен; его можно разрешить программно установкой бита MSI Enable (после программирования адреса и шаблона сообщения), и тогда генерация прерываний по линиям INTx# запрещается. Самая «богатая» прерываниями функция (для которой Multiple Message Enable = 101) при записи сообщения идентифицирует конкретное условие прерывания (одно из 32 возможных) по линиям AD[4:0].
Отметим, что быстрая посылка подряд двух и более одинаковых сообщений может быть воспринята системой как одно прерывание (из-за низкой реактивности). Если требуется обработка каждого из них, обработчик должен обеспечивать уведомление устройства, а оно не должно посылать следующее сообщение до получения уведомления, чтобы прерывания не терялись. Различающиеся сообщения друг другу не мешают.
Прерывания через MSI позволяют избежать бед разделяемости, обусловленной дефицитом линий запросов прерывания в PC. Кроме того, они решают проблему целостности данных: все данные, записываемые устройством до посылки MSI, дойдут до получателя гарантированно раньше начала обработки MSI. Прерывания через MSI от одних устройств в одной системе могут использоваться наряду с обычными INTx# от других устройств. Но каждое устройство (функция), использующее MSI, не должно использовать прерывания через линии INTx#.
Механизм MSI может использоваться на системных платах, имеющих «продвинутый» контроллер прерываний APIC. Правда, конкретная реализация поддержки MSI может потенциальные возможности облегчения идентификации большого числа запросов прерывания свести лишь к увеличению числа доступных запросов прерываний (и используемых ими векторов). Так, например, для системных плат на чипсетах с хабом ICH2 и ICH3 фирмы Intel поддержка MSI сводится к организации альтернативных путей подачи запросов IRQ[1:23] на входы APIC (запросы IRQ с номерами 0, 2, 8 и 13 через MSI не передаются). Всем устройствам PCI назначается один и тот же адрес сообщений (Message Address = FEC00020h), по которому в APIC находится регистр IRQ Pin assertion. В сообщении используются лишь младшие 5 бит, в которых указывается номер взводимого запроса прерывания в диапазоне 1–23 (исключая 2, 8 и 13). Линии запросов, используемые в MSI, программируются на чувствительность к перепаду (сообщения имитируют только фронт сигнала). По этой причине прерывания с номерами, используемыми в MSI, не могут использоваться совместно (разделяемо) с прерываниями, полученными другими способами (по линиям запросов от устройств PCI и от других устройств системной платы). Возможно, что в других платформах прерывания через MSI используются более эффективно.
Прерывания от внешних устройств в системе x86. Часть 2. Опции загрузки ядра Linux
В предыдущей части мы рассмотрели эволюцию доставки прерываний от устройств в x86 системах (PIC → APIC → MSI), общую теорию и все необходимые термины.
В этой практической части мы рассмотрим как откатиться к использованию устаревших методов доставки прерываний в Linux, а именно рассмотрим опции загрузки ядра:
Загрузка без дополнительных опций
Смотреть прерывания в данной статье мы будем на кастомной плате с Intel Haswell i7 с чипсетом lynxPoint-LP на которой запущен coreboot.
Информацию о прерываниях мы будем выводить через команду
Вывод при загрузке без дополнительных опций:
Файл /proc/interrupts предоставляет таблицу о количестве прерываний на каждом из процессоров в следующем виде:
Упрощённо схему роутинга прерываний можно нарисовать так (красным помечены активные пути, чёрным неиспользуемые).
Поддержка MSI/MSI-X устройством должна быть обозначена как соответствующая Capability в его конфигурационном пространстве PCI.
В подтверждении приведём небольшой фрагмент вывода lspci для устройств, для которых обозначено, что они используют MSI/MSI-X. В нашем случае это SATA контроллер (прерывание ahci), 2 ethernet контроллера (прерывания eth58* и eth59*), графический контроллер (i915) и 2 контроллера HD Audio (snd_hda_intel).
Как мы видим, у этих устройств присутствует строка либо «MSI: Enable+», либо «MSI-X: Enable+»
Начнём деградировать систему. Для начала загрузимся с опцией pci=nomsi.
pci=nomsi
Благодаря этой опции MSI прерывания станут IO-APIC/XT-PIC в зависимости от используемого контроллера прерываний
В данном случае у нас всё ещё приоритетный контроллер прерываний APIC, так что картина будет такая:
Все прерывания MSI/MSI-X ожидаемо исчезли. Вместо них устройства теперь используют прерывания вида IO-APIC-fasteoi.
Обратим внимание на то, что раньше до включения этой опции у eth58 и eth59 было по 9 прерываний! А сейчас только по одному. Ведь как мы помним, без MSI одной функции PCI доступно только одно прерывание!
Немного информации из dmesg по инициализации ethernet контроллеров:
— загрузка без опции pci=nomsi:
— загрузка с опцией pci=nomsi
Из-за уменьшения количества прерываний на устройство, включение данной опции может приводить к существенному ограничению производительности работы драйвера (это без учёта того, что согласно исследованию Intel Reducing Interrupt Latency Through the Use of Message Signaled Interrupts прерывания через MSI в 3 раза быстрее чем через IO-APIC и в 5 раз быстрее чем через PIC).
noapic
Данная опция отключает I/O APIC. MSI прерывания всё ещё могут идти на все CPU, но прерывания от устройств смогут идти только на CPU0, так как PIC связан только с CPU0. Но LAPIC работает и другие CPU могут работать и обрабатывать прерывания.
Как видим, все прерывания IO-APIC-* превратились в XT-PIC-XT-PIC, причём эти прерывания роутятся только на CPU0. Прерывания MSI остались без изменений и идут на все CPU0-3.
nolapic
Отключает LAPIC. MSI прерывания не могут работать без LAPIC, I/O APIC не может работать без LAPIC. Поэтому все прерывания от устройств будут идти на PIC, а он работает только с CPU0. И без LAPIC остальные CPU даже работать в системе не будут.
Комбинации:
На самом деле всего одна для нового варианта: «noapic pci=nomsi». Все прерывания от устройств смогут идти только на CPU0 через PIC. Но LAPIC работает и другие CPU могут работать и обрабатывать прерывания.
Одна, потому что с «nolapic» можно ничего не комбинировать, т.к. эта опция и так сделает недоступным I/O APIC и MSI. Так что если вы когда-то прописывали опции загрузки «noapic nolapic» (или самый распространённый вариант «acpi=off noapic nolapic»), то судя по всему вы набирали лишние буквы.
Итак, что будет от опций «noapic pci=nomsi»:
Таблицы роутинга прерываний и опции «acpi=noirq», «pci=noacpi», «acpi=off»
Как операционная система получает информацию о роутинге прерываний от устройств? BIOS подготавливает информацию для ОС в виде:
Таблицы в списке выше обозначены в порядке приоритета. Рассмотрим это подробней.
Допустим BIOS предоставил все эти данные и мы грузимся без каких-либо дополнительных опций:
Суммируем всё вышеизложенное следующей картинкой:
Следует помнить, что не каждый BIOS предоставляет все 3 таблицы (ACPI/MPtable/$PIR), так что если вы передали опцию загрузчику отказаться от использования ACPI или ACPI и MPtable для роутинга прерываний, далеко не факт, что ваша система загрузится.
Замечание 1: в случае если мы попытаемся загрузиться в режиме APIC с опцией acpi=noirq и без наличия MPtable, то картина прерываний будет как и в случае обычной загрузки с единственной опцией noapic. Операционная система сама перейдёт в режим PIC прерываний.
В случае если мы попытаемся загрузиться вообще без таблиц ACPI (acpi=off) и не предоставив MPtable, то картина будет такая:
Это проиcходит из-за того, что без ACPI таблицы MADT (Multiple APIC Description Table) и необходимой информации из MPtable, операционная система не знает APIC идентификаторы (APIC ID) для других процессоров и не может с ними работать, но LAPIC основного процессора работает, так как мы это не запрещали, и MSI прерывания могут на него приходить. То есть будет так:
Немного странно, что так происходит, но в документации ядра вроде говорится, что это нормально.
Заключение:
В заключении ещё раз обозначим разобранные опции.
Опции выбора контроллера прерываний:
Содержание
Обзор
Распространенное заблуждение относительно MSI заключается в том, что он позволяет устройству отправлять данные процессору как часть прерывания. Данные, которые отправляются как часть транзакции записи в память, используются набором микросхем, чтобы определить, какое прерывание запускать на каком процессоре; эти данные недоступны устройству для передачи дополнительной информации обработчику прерывания.
Например, PCI Express вообще не имеет отдельных контактов прерывания; вместо этого он использует специальные внутриполосные сообщения, позволяющие имитировать подтверждение вывода или отмену подтверждения. Некоторые архитектуры без PCI также используют MSI; в качестве другого примера, устройства HP GSC не имеют контактов прерывания и могут генерировать прерывания только путем записи непосредственно в регистр прерывания процессора в пространстве памяти. Протокол HyperTransport также поддерживает MSI.
Преимущества
Хотя более сложные для реализации в устройстве прерывания, сигнализируемые сообщением, имеют некоторые существенные преимущества перед внеполосной сигнализацией прерываний на основе выводов. С механической стороны меньшее количество контактов делает разъем более простым, дешевым и надежным. Хотя это не является преимуществом для стандартного разъема PCI, PCI Express использует эту экономию.
MSI увеличивает количество возможных прерываний. В то время как обычный PCI был ограничен четырьмя прерываниями на карту (и, поскольку они были разделены между всеми картами, большинство из них используют только одну), прерывания с сигнализацией сообщений допускают десятки прерываний на карту, когда это полезно.
Также есть небольшое преимущество в производительности. В программном обеспечении прерывание на основе вывода могло конкурировать с опубликованной записью в память. То есть устройство PCI записывает данные в память, а затем отправляет прерывание, чтобы указать, что запись DMA завершена. Однако мост PCI или контроллер памяти могут буферизовать запись, чтобы не мешать другому использованию памяти. Прерывание могло появиться до завершения записи DMA, и процессор мог прочитать устаревшие данные из памяти. Чтобы предотвратить эту гонку, обработчики прерываний должны были читать с устройства, чтобы гарантировать, что запись DMA завершена. Это чтение имело умеренное снижение производительности. Запись MSI не может пройти запись DMA, поэтому гонка устраняется.
Типы MSI
PCI определяет два дополнительных расширения для поддержки прерываний, сигнализируемых сообщением, MSI и MSI-X. PCI Express определяет свой собственный механизм на основе сообщений для эмуляции устаревших прерываний PCI.
MSI (впервые определенная в PCI 2.2) позволяет устройству выделять 1, 2, 4, 8, 16 или 32 прерывания. Устройство запрограммировано с адресом для записи (обычно это регистр управления в контроллере прерываний ) и 16-битным словом данных для его идентификации. Номер прерывания добавляется к слову данных для идентификации прерывания. Некоторые платформы, такие как Windows, не используют все 32 прерывания, а используют только до 16 прерываний.
MSI-X (впервые определенный в PCI 3.0) позволяет устройству выделять до 2048 прерываний. Единый адрес, используемый исходным MSI, оказался ограничивающим для некоторых архитектур. В частности, это затрудняло нацеливание отдельных прерываний на разные процессоры, что полезно в некоторых высокоскоростных сетевых приложениях. MSI-X допускает большее количество прерываний и дает каждому из них отдельный целевой адрес и слово данных. Устройства с MSI-X не обязательно поддерживают 2048 прерываний.
Дополнительные функции MSI (64-битная адресация и маскирование прерываний) также являются обязательными для MSI-X.
Эмуляция устаревших прерываний PCI Express
PCI Express позволяет устройствам использовать эти устаревшие сообщения о прерываниях, сохраняя программную совместимость с драйверами PCI, но они также должны поддерживать MSI или MSI-X на уровне PCI.
системы x86
Поддержка операционной системы
В версии Solaris Express 6/05 добавлена поддержка MSI и MSI-X как часть их новой инфраструктуры обработки прерываний интерфейса драйверов устройств (DDI).
FreeBSD 6.3 и 7.0 добавили поддержку MSI и MSI-X.
В OpenBSD 5.0 добавлена поддержка MSI. 6.0 добавлена поддержка MSI-X.
Linux получил поддержку MSI и MSI-X примерно в 2003 году. Известно, что версии ядра Linux до 2.6.20 имеют серьезные ошибки и ограничения в реализации MSI / MSI-X.
Компания Haiku получила поддержку MSI примерно в 2010 году. Поддержка MSI-X была добавлена позже, в 2013 году.
В NetBSD 8.0 добавлена поддержка MSI и MSI-X.
Примените прерывание msi что это
Отключение таймера HPET
‼️ Ни в коем случае не отключайте данный таймер в BIOS – там он должен быть включён для корректной работы системы в целом. В новых версиях BIOS подобная настройка включена по-умолчанию и зачастую её изменение не возможно. Подробную информацию как изменить параметры в BIOS можно найти в руководстве к материнской плате или в интернете.
Пример правильного отключения таймера HPET в Windows:
Пример не настроенного таймера в Intelligent Standby List Cleaner :
Для правильной настройки необходимо установить следующие параметры:
⚠️ Во избежание дополнительных микрофризов при очищении кэша памяти, если у вас её мало или же её очень активно используют программы, данную настройку лучше протестировать с разными параметрами и найти оптимальную для вашего сценария использования.
После настройки надо нажать Start и проверить зафиксирован ли таймер – значение Current timer resolution должно быть строго равно 0.5ms и не изменяться. Значение может обновится с задержкой!
Пример правильной настройки Intelligent Standby List Cleaner :
Включение MSI mode
Пример настройки MSI с помощью MSI Util v2 :
‼️ Нельзя устанавливать использование MSI mode для всех ваших устройств, иначе устройства могут работать не корректно.
⚠️ Данная настройка сбрасывается на дефолтное значение после обновления драйвера nVidia!
💡 Для дальнейшей настройки необходимо ознакомиться c Работа с реестром.
Следующим шагом после настройки приоритетов IRQL [?] необходимо указать приоритет для каких сервисов (в нашем случае драйверов) необходимо выполнять прерывания в первую очередь. Когда происходит прерывание, Windows, используя IRQL для определения приоритета прерывания, проверяет может ли прерывание обслуживаться в данный момент или нет, если условие выполняется, то приоритет потока начинает его выполнение. Всё что ниже по приоритету – ставиться в очередь. Таким образом мы зафиксируем критически важные сервисы, прерывания от которых необходимо обрабатывать в первую очередь.
Распараллеливание драйверов по ядрам
Самое сложное осталось позади и теперь мы будет освобождать первое ядро, куда Windows зачем-то добавляет почти все драйверы. Этим мы с одной стороны разгрузим ядро, а с другой так же уменьшим задержки.
✨ При использовании утилиты будут периодически появляться сообщения об ошибке – их можно спокойно игнорировать, т.к. программа давно не обновлялась и на работу программы они никак не влияют.
Пример списка устройств в утилите Interrupt Affinity Policy Tool :
В этом списке надо найти свою видеокарту и USB Host Controller (название может не соответствовать, поэтому искать лучше по полю Location Info ), нажать Set Mask и выбрать ядро на которое будет назначен драйвер. Выбирать надо на любое ядро отличное от первого.
⚠️ Данная настройка сбрасывается на дефолтное значение после обновления драйвера nVidia!
Message Signaled Interrupts
1. Об этом руководстве
В этом руководстве описаны основы Message Signaled Interrupts (MSIs), преимущества использования MSI, по сравнению с традиционным механизмом прерываний, как изменить Ваш драйвер, что бы он использовал MSI или MSI-X и некоторые методы диагностики, для определения причины, почему устройство не поддерживает MSI.
Возможности MSI впервые были определены в стандарте PCI 2.2 и, позднее, были доработаны в PCI 3.0 для того, что бы можно было индивидуально маскировать каждое MSI прерывание. Возможности MSI-X так же были добавлены в версии 3.0. Каждое устройство теперь может иметь большее число прерываний по сравнению с PCI и позволяет независимо настраивать каждое прерывание.
Устройство может поддерживать как MSI, так и MSI-X, но в любой момент времени может быть доступен только один из этих режимов.
Использование MSI может дать три преимущества, по сравнению с использованием традиционной технологии линий прерывания.
Линии прерывания зачастую разделяются между несколькими устройствами. Для того, что бы обеспечить обработку разделяемых прерываний, ядро вынуждено вызывать поочерёдно все обработчики прерываний, связанный с этим прерыванием, что приводит к снижению производительности системы в целом. MSI никогда не разделяются, так что эта проблема не возникает.
Когда устройство завершает запись данных в память, возникшее прерывание может достигнуть процессора раньше, чем все данные реально достигнут памяти (если устройство расположено за PCI мостом, то вероятность этого возрастает). Для того, что бы удостоверится. что все данные реально записаны в память, обработчик прерываний должен прочитать любой регистр на устройстве, которое послало прерывание. Правила выполнения транзакций на PCI требуют, что бы все данные достигли памяти до того, как можно читать регистры. Использование MSI позволяет избежать этой проблемы, так как запись в память, генерирующая прерывание, не может обогнать запись данных, поэтому, когда возникло прерывание, драйвер точно знает, что запись данных уже завершена.
Во время аппаратной инициализации, PCI устройства настраиваются на использование классических прерываний. Переключить устройство на использование MSI или MSI-X должен драйвер устройства. Не все архитектуры поддерживают MSI и на таких машинах, вызов API функций, описанных ниже, завершится ошибкой и устройство продолжит работать в классическом режиме линий прерывания.
4.1 Включаем поддержку ядра для MSI
Для того, что бы ядро Linux поддерживало MSI, необходимо собрать его с включённой опцией CONFIG_PCI_MSI. Эта опция доступна не на всех архитектурах и она может зависеть от некоторых других опций, которые тоже должны быть установлены. Например, для х86 необходимо включить опцию X86_UP_APIC или SMP для того, что бы сделать доступной опцию CONFIG_PCI_MSI.
4.2 Используем MSI
Самая тяжёлая часть работы для драйвера делается PCI-уровнем ядра. Он должен просто запросить PCI-уровень ядра установить поддержку возможностей MSI для данного устройства.
4.2.1 pci_enable_msi
Успешный вызов этой функции выделит ОДНО прерывание устройству, независимо от того, как много MSI способно обслуживать устройство. Устройство при этом будет переключено в режим MSI. Поле dev->irq, хранящее номер прерывания, будет изменено на новый номер, который будет предоставлен MSI. Эта функция должна быт вызвана до того, как драйвер вызовет request_irq() так как включение MSI запрещает линии IRQ и драйвер не получит прерываний от старых прерываний.
4.2.2 pci_enable_msi_block
Этот вариант вызова, описанного выше, позволяет драйверу устройства запросить множество MSI. Спецификация MSI позволяет выделять прерывания в количестве, равном степени двойки, до 2^5 = 32.
Если эта функция вернула отрицательное число, то это указывает на ошибку и драйвер не должен пытаться запрашивать дополнительные MSI прерывания для данного устройства. Если функция вернула положительное значение, то это значение будет меньше, чем count и оно указывает реальное количество прерываний, которые были выделены устройству. В любом случае, значение irq не изменится, а само устройство не будет переключено в режим MSI.
Драйвер устройства должен решить, что делать, в случае, если pci_enable_msi_block() вернула значение, меньшее, чем запрошенный count. Некоторые устройства могут использовать меньше прерываний, чем тот максимум, который они запросили; в этом случае драйвер должен вновь вызвать pci_enable_msi_block(). Следует отметить, что успех не гарантируется, даже если значение count уменьшено до значения. которое вернул предыдущий вызов pci_enable_msi_block(). Это возможно потому, что существует множество ограничений на количество векторов прерываний, которое может выделить система; pci_enable_msi_block() будет возвращать такое значение до тех пор, пока некоторые ограничения не позволяют успешно завершить вызов.
4.2.3 pci_disable_msi
Эта функция используется для отмены действия pci_enable_msi() или pci_enable_msi_block(). Её вызов восстанавливает значение dev->irq записывая туда номер IRQ и освобождает ранее выделенные MSI. В дальнейшем эти прерывания могут быть назначены другому устройству, поэтому драйвер не должен запоминать это эти значения.
Драйвер устройства обязательно должен вызывать free_irq() для тех прерываний, для которых он вызывал request_irq() ДО вызова этой функции. При неудаче устройство останется в режиме MSI и его вектора будут потеряны. Будет выполнен отладочный вызов BUG_ON().
4.3 Использование MSI-X
MCI-X предоставляет намного более гибкие возможности, чем MSI. Она поддерживает до 2048 прерываний, каждое из которых может управляться независимо от других. Для поддержания такой гибкости, драйвер должен использовать массив структур struct msix_entry :
Это позволяет драйверу использовать разряженные номера прерываний. Например, он может использовать номера 3 и 1027 и выделить место всего под двухэлементный массив. Предполагается, что драйвер заполнит поля entry каждого элемента массива, значениями указывающими, какие номера прерываний он желает что бы ядро выделило для устройства. Ошибкой будет указание двух одинаковых значений поля entry в разных элементах массива.
4.3.1 pci_enable_msix
Вызов этой функции запрашивает у PCI-подсистемы ядра выделить nvec MSI прерываний. Аргумент entries указывает на массив структур типа msix_entry который должен имет размер не менее nvec. При успешном завершении функция вернет 0 и устройство будет переключено в режим MSI-X прерываний. В каждом элементе массива структур, поле vector получит соответствующий номер прерывания. После этого драйвер должен вызвать request_irq() для каждого значения vector, которое он собирается использовать.
Если эта функция вернула отрицательное значение, то это указывает на ошибку и драйвер не должен больше пытаться выделять MSI-X прерывания для данного устройства. Если он вернул положительное число, то оно указывает на максимальный номер вектора прерывания, который был выделен системой. См. пример ниже.
В противоположность pci_enable_msi() эта функция НЕ настраивает dev->irq. Устройство перестанет генерировать прерывания по этому номеру прерывания, при включении режима MSI-X. Драйвер устройства отвечает за отслеживание прерываний, назначенных MSI-X векторам для того, что бы он мог, в последствии, освободить их позднее.
Во время фазы инициализации, драйвер устройства должен вызвать эту функцию однократно для каждого устройства.
Идеально будет, если драйвер способен работать с разными номерами MSI-X прерываний, так есть много причин, по которым разные платформы окажутся не в состоянии выделить именно те номера, которые запросил драйвер.
Цикл запроса прерываний, решающий эту задачу, может выглядеть следующим образом:
4.3.2 pci_disable_msix
Эта функция API должна использоваться для отмены результатов действия pci_enable_msix(). Она осовбождает ранее выделенные MSI прерывания. В последствии, эти прерывания могут быть назначены другому устройству, поэтому драйвер не должен хранить и использовать значения поля vector после вызова pci_disable_msix().
Драйвер устройства обязательно должен вызывать free_irq() для всех прерываний, для которых он делал вызов request_irq(), перед вызовом этой функции. Иначе возникнет ошибка, результатом которой будет отладочная печать в BUG_ON(), устройство выйдет из режима MSI и вектор будет потерян.
4.3.3 Таблица MSI-X
В элементе MSI-X capability указывается BAR и смещение для указания на таблицу MSI-X. Этот адрес устанавливается PCI подсистемой ядра и не должен использоваться напрямую драйвером устройства. Если драйвер намеревается маскировать / размаскировать некотрое прерывание, то он должен делать это вызывая disable_irq() / enable_irq().
4.4 Управление устройствами, в которых реализовано как MSI так и MSI-X
4.5.1 Выбор между MSI-X и MSI
Если Ваше устройство поддерживает и MSI и MSI-X, предпочтительно, что бы Вы использовали возможности MSI-X. Как упоминалось выше, MSI-X поддерживает любое количество номеров прерываний от 1 до 2048. В то время, как MSI ограничен 32 прерываниями. Кроме того, так как вектора прерываний MSI должны быть расположены последовательно, система, возможно, окажется не в состоянии выделить так много векторов MSI, как для MSI-X. На некоторых платформах, все MSI прерывания передаются на один набор процессоров, тогда как все прерывания MSI-X могут быть нацелены на различные ЦП.
4.5.2 Spinlocks
Большинство драйверов устройств имеют спинлоки, связанные с каждым устройством, которые захватываются обработчиком прерываний. При работе с линиями прерывания или единственным прерыванием MSI, нет необходимости запрещать прерывания (ядро Linux гарантирует, что одно и тоже прерывание не будет повторно входимым). Если же устройство работает с множеством прерываний, то драйвер должен запретить прерывания пока сохраняется блокировка. Если устройство пошлет другое прерывание, драйвер войдет в клинч, пытаясь рекурсивно получить спинлок.
Есть два решения. Первое заключается в использовании вызовов функций API spin_lock_irqsave() или spin_lock_irq() (Смотри Documentation/DocBook/kernel-locking). Второе заключается в использовании флага IRQF_DISABLED при вызове request_irq(), так что ядро будет запускать обработчик прерываний при запрещённых прерываниях.
Если Ваш обработчик MSI прерываний не захватывает блокировку на все время, пока он работает, первое решение является более предпочтительным. Второе решение обычно предпочитается тогда, когда нужно избежать двух переходов из состояния запрета прерывания в состояние разрешения и обратно.
5.Проблемы MSI
Некоторые чипсеты PCI или устройства, как известно, не поддерживают MSI. Стек PCI предоставляет три метода для запрета MSI :
5.1. Глобальный запрет MSI
Некоторые чипсеты не поддерживают совсем или поддерживают MSI неправильно. Если Вам повезет, то производитель, знающий об этом, отметит это в таблице ACPI FADT. В этом случае, ядро Linux автоматически запретит MSI. Некоторые платы не включают эту информацию в таблицу и тогда мы должны определять это самостоятельно. Наиболее полный список таких плат можно найти рядом с функцией quirk_disable_all_msi() в файле drivers/pci/quirks.c.
5.2. Запрет MSI ниже моста
Некоторые мосты не способны правильно направлять MSI между ветвями. В этом случае необходимо запретить MSI для всех устройств за этим мостом.
Для запрета MSI выдайте команду echo 0 вместо 1. Выполнять такие действия необходимо с осторожностью, так как они могут нарушить обработку прерываний у всех устройств, расположенных ниже моста.
Повторяю, пожалуйста, сообщите о всех мостах, которым требуется специальное управление, по адресу linux-pci@vger.kernel.org.
5.3. Запрет MSI на одном устройстве
Известно, что на некоторых устройствах MSI реализован с ошибками. Обычно, такие устройства управляются индивидуальными драйверами, но иногда необходимо управлять ими с помощью различных уловок. Некоторые драйверы имеют опцию для запрета MSI. Хотя это является простейшим выходом для разработчика драйвера, нельзя признать это хорошей идеей и не следует подражать такому решению.
5.4. Определение причины запрета MSI на устройстве
Из трёх предыдущих разделов Вы могли увидеть, что есть множество причин, по которым MSI отключен на данном устройстве. Вашим первым шагом должна быть внимательная проверка файла dmesg для выяснения того, включены ли MSI на Вашей машине. Кроме того, Вам необходимо проверить файл .config и убедится, что опция CONFIG_PCI_MSI включена.
Полезно так же проверить сам драйвер, что бы выяснить, поддерживает ли он MSI. Такой драйвер должен содержать вызовы функций pci_enable_msi(), pci_enable_msix() or pci_enable_msi_block().