kernel/irq/msi.c
Source file repositories/reference/linux-study-clean/kernel/irq/msi.c
File Facts
- System
- Linux kernel
- Corpus path
kernel/irq/msi.c- Extension
.c- Size
- 51862 bytes
- Lines
- 1778
- Domain
- Core OS
- Bucket
- Scheduler, Processes, Timers, Sync, And Syscalls
- Inferred role
- Core OS: exported/initcall integration point
- Status
- integration implementation candidate
Why This File Exists
Core operating-system implementation surface: boot, tasks, memory, VFS, syscall-facing interfaces, synchronization, credentials, and isolation.
- Core operating-system implementation surface: boot, tasks, memory, VFS, syscall-facing interfaces, synchronization, credentials, and isolation.
- Exports symbols or registers init work; inspect boot/module ordering and who consumes the exported contract.
- Uses kernel synchronization; read lock ordering, sleepability, and interrupt context assumptions before translating.
- Touches IRQ or DMA behavior; this matters for the representative real-device path.
- Allocates kernel memory; connect allocation flags and lifetime to context constraints.
- Defines or uses C structs; map object ownership, embedded links, reference counts, and lock ownership.
Dependency Surface
linux/device.hlinux/irq.hlinux/irqdomain.hlinux/msi.hlinux/mutex.hlinux/pci.hlinux/slab.hlinux/seq_file.hlinux/sysfs.hlinux/types.hlinux/xarray.hinternals.h
Detected Declarations
struct msi_device_datastruct msi_ctrlfunction msi_free_descfunction msi_insert_descfunction msi_domain_insert_msi_descfunction msi_desc_matchfunction msi_ctrl_validfunction msi_domain_free_descsfunction msi_domain_free_msi_descs_rangefunction msi_domain_add_simple_msi_descsfunction __get_cached_msi_msgfunction get_cached_msi_msgfunction msi_device_data_releasefunction msi_setup_device_datafunction guardfunction guardfunction xa_for_each_startfunction msi_next_descfunction msi_domain_get_virqfunction msi_sysfs_create_groupfunction msi_mode_showfunction msi_sysfs_remove_descfunction msi_sysfs_populate_descfunction msi_device_populate_sysfsfunction msi_for_each_descfunction msi_device_destroy_sysfsfunction msi_sysfs_create_groupfunction msi_sysfs_populate_descfunction msi_sysfs_remove_descfunction msi_domain_get_hwsizefunction irq_chip_write_msi_msgfunction msi_check_levelfunction msi_domain_set_affinityfunction msi_domain_activatefunction msi_domain_deactivatefunction msi_domain_allocfunction msi_domain_freefunction msi_domain_translatefunction msi_domain_debug_showfunction msi_domain_ops_get_hwirqfunction msi_domain_ops_preparefunction msi_domain_ops_teardownfunction msi_domain_ops_initfunction msi_domain_update_dom_opsfunction msi_domain_update_chip_opsfunction msi_parent_init_dev_msi_infofunction msi_create_device_irq_domainfunction msi_remove_device_irq_domain
Annotated Snippet
struct msi_device_data {
unsigned long properties;
struct mutex mutex;
struct msi_dev_domain __domains[MSI_MAX_DEVICE_IRQDOMAINS];
unsigned long __iter_idx;
};
/**
* struct msi_ctrl - MSI internal management control structure
* @domid: ID of the domain on which management operations should be done
* @first: First (hardware) slot index to operate on
* @last: Last (hardware) slot index to operate on
* @nirqs: The number of Linux interrupts to allocate. Can be larger
* than the range due to PCI/multi-MSI.
*/
struct msi_ctrl {
unsigned int domid;
unsigned int first;
unsigned int last;
unsigned int nirqs;
};
/* Invalid Xarray index which is outside of any searchable range */
#define MSI_XA_MAX_INDEX (ULONG_MAX - 1)
/* The maximum domain size */
#define MSI_XA_DOMAIN_SIZE (MSI_MAX_INDEX + 1)
static void msi_domain_free_locked(struct device *dev, struct msi_ctrl *ctrl);
static unsigned int msi_domain_get_hwsize(struct device *dev, unsigned int domid);
static inline int msi_sysfs_create_group(struct device *dev);
static int msi_domain_prepare_irqs(struct irq_domain *domain, struct device *dev,
int nvec, msi_alloc_info_t *arg);
/**
* msi_alloc_desc - Allocate an initialized msi_desc
* @dev: Pointer to the device for which this is allocated
* @nvec: The number of vectors used in this entry
* @affinity: Optional pointer to an affinity mask array size of @nvec
*
* If @affinity is not %NULL then an affinity array[@nvec] is allocated
* and the affinity masks and flags from @affinity are copied.
*
* Return: pointer to allocated &msi_desc on success or %NULL on failure
*/
static struct msi_desc *msi_alloc_desc(struct device *dev, int nvec,
const struct irq_affinity_desc *affinity)
{
struct msi_desc *desc = kzalloc_obj(*desc);
if (!desc)
return NULL;
desc->dev = dev;
desc->nvec_used = nvec;
if (affinity) {
desc->affinity = kmemdup_array(affinity, nvec, sizeof(*desc->affinity), GFP_KERNEL);
if (!desc->affinity) {
kfree(desc);
return NULL;
}
}
return desc;
}
static void msi_free_desc(struct msi_desc *desc)
{
kfree(desc->affinity);
kfree(desc);
}
static int msi_insert_desc(struct device *dev, struct msi_desc *desc,
unsigned int domid, unsigned int index)
{
struct msi_device_data *md = dev->msi.data;
struct xarray *xa = &md->__domains[domid].store;
unsigned int hwsize;
int ret;
hwsize = msi_domain_get_hwsize(dev, domid);
if (index == MSI_ANY_INDEX) {
struct xa_limit limit = { .min = 0, .max = hwsize - 1 };
unsigned int index;
/* Let the xarray allocate a free index within the limit */
ret = xa_alloc(xa, &index, desc, limit, GFP_KERNEL);
if (ret)
goto fail;
desc->msi_index = index;
Annotation
- Immediate include surface: `linux/device.h`, `linux/irq.h`, `linux/irqdomain.h`, `linux/msi.h`, `linux/mutex.h`, `linux/pci.h`, `linux/slab.h`, `linux/seq_file.h`.
- Detected declarations: `struct msi_device_data`, `struct msi_ctrl`, `function msi_free_desc`, `function msi_insert_desc`, `function msi_domain_insert_msi_desc`, `function msi_desc_match`, `function msi_ctrl_valid`, `function msi_domain_free_descs`, `function msi_domain_free_msi_descs_range`, `function msi_domain_add_simple_msi_descs`.
- Atlas domain: Core OS / Scheduler, Processes, Timers, Sync, And Syscalls.
- Implementation status: integration implementation candidate.
- Synchronization appears in or near this file; preserve lock ordering, sleepability, and interrupt-context constraints.
- IRQ or DMA behavior appears here, which is relevant to the selected PCIe/NVMe device path.
Implementation Notes
- This generated page is the file-by-file coverage layer; curated subsystem chapters should link here when they synthesize a multi-file control flow.
- Core OS pages should be promoted from atlas-only to deep-reviewed when they explain data structures, invariants, locking, lifecycle, and C implementation snippets.
- Driver-family pages are intentionally pattern-oriented unless they are part of the selected PCIe/NVMe representative device path.