1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
|
@page page_device_pci_msi PCI MSI and MSI-X
# PCI MSI / MSI-X (`msi/`)
Headers: **`drivers/pci_msi.h`**, **`pci_regs.h`**.
| File | Role |
| --- | --- |
| **`msi/msi.c`** | Capability parse, mask/unmask, message write |
| **`msi/irq.c`** | **`rt_pci_msi_setup_irqs`**, PIC allocation |
| **`msi/device.c`** | Device enable helpers |
Disabled when **`RT_PCI_MSI=n`** — stubs in **`pci.h`**.
---
## Prerequisites
- **`pdev->msi_pic`**: **`struct rt_pic`** with **`irq_alloc_msi`**, **`irq_free_msi`**, **`irq_compose_msi_msg`**
- **`pdev->msi_cap`** / **`pdev->msix_cap`** from **`rt_pci_msi_init`** / **`rt_pci_msix_init`** in setup
---
## Setup flow (`irq.c`)
**`rt_pci_msi_setup_irqs(pdev, nvec, type)`**:
### MSI
1. Read **`multi_msg_use`** (log2 vectors) from first **`rt_pci_msi_desc`**
2. **`irq_alloc_msi`** until **`nvec`** contiguous IRQs obtained
3. Per vector: **`irq_compose_msi_msg`**, **`rt_pci_msi_write_msg`**
### MSI-X
- Per table entry: separate **`irq_alloc_msi`**
- Table must be mapped (BAR assigned before enable)
**`rt_pci_msi_cleanup_irqs`** frees allocations.
---
## Driver API
| API | Use |
| --- | --- |
| **`rt_pci_msi_enable(pdev)`** | Single vector |
| **`rt_pci_msi_enable_range(pdev, min, max)`** | Power-of-two count |
| **`rt_pci_msi_enable_range_affinity(...)`** | With CPU masks |
| **`rt_pci_msix_enable(pdev, entries, count)`** | MSI-X table indices |
| **`rt_pci_msi_disable` / `rt_pci_msix_disable`** | Tear down |
| **`rt_pci_alloc_vector`** | Unified legacy/MSI/MSI-X picker (@ref page_device_pci_irq) |
---
## Masking (`msi.c`)
- **MSI**: config **`mask`** register when **`cap.is_masking`**
- **MSI-X**: per-entry vector control in table
**`rt_pci_msi_mask_irq` / `rt_pci_msi_unmask_irq`** — PIC integration.
---
## Pitfalls
| Issue | Mitigation |
| --- | --- |
| Non-contiguous MSI vectors | Allocator retries; check return |
| MSI-X before BAR map | Enable only after **`rt_pci_setup_device`** |
| INTx still firing | Enable MSI only after masking INTx in core |
| Large MSI-X table | Default affinity storage capped — review for 2k+ entries |
## See also
- @ref page_device_pci
- @ref page_device_pci_irq
- @ref page_device_pci_ofw
- @ref page_device_pic
- `components/drivers/pci/msi/`
|