drivers/iommu/iommufd/driver.c
Source file repositories/reference/linux-study-clean/drivers/iommu/iommufd/driver.c
File Facts
- System
- Linux kernel
- Corpus path
drivers/iommu/iommufd/driver.c- Extension
.c- Size
- 8951 bytes
- Lines
- 308
- Domain
- Driver Families
- Bucket
- drivers/iommu
- Inferred role
- Driver Families: exported/initcall integration point
- Status
- integration implementation candidate
Why This File Exists
Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.
- Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.
- 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
iommufd_private.h
Detected Declarations
function _iommufd_object_dependfunction _iommufd_object_undependfunction _iommufd_alloc_mmapfunction _iommufd_destroy_mmapfunction iommufd_viommu_get_vdev_idfunction iommufd_viommu_report_eventfunction iommufd_sw_msi_get_mapfunction list_for_each_entryfunction iommufd_sw_msi_installfunction iommufd_sw_msi
Annotated Snippet
if (iommufd_vdevice_to_device(vdev) == dev) {
*vdev_id = vdev->virt_id;
rc = 0;
break;
}
}
xa_unlock(&viommu->vdevs);
return rc;
}
EXPORT_SYMBOL_NS_GPL(iommufd_viommu_get_vdev_id, "IOMMUFD");
/*
* Typically called in driver's threaded IRQ handler.
* The @type and @event_data must be defined in include/uapi/linux/iommufd.h
*/
int iommufd_viommu_report_event(struct iommufd_viommu *viommu,
enum iommu_veventq_type type, void *event_data,
size_t data_len)
{
struct iommufd_veventq *veventq;
struct iommufd_vevent *vevent;
int rc = 0;
if (WARN_ON_ONCE(!data_len || !event_data))
return -EINVAL;
down_read(&viommu->veventqs_rwsem);
veventq = iommufd_viommu_find_veventq(viommu, type);
if (!veventq) {
rc = -EOPNOTSUPP;
goto out_unlock_veventqs;
}
/* Pre-allocate to avoid GFP_ATOMIC; use GFP_NOWAIT to avoid sleeping */
vevent = kzalloc_flex(*vevent, event_data, data_len, GFP_NOWAIT);
if (!vevent) {
spin_lock(&veventq->common.lock);
vevent = &veventq->lost_events_header;
rc = -ENOMEM;
goto out_set_header;
}
spin_lock(&veventq->common.lock);
if (veventq->num_events == veventq->depth) {
kfree(vevent);
vevent = &veventq->lost_events_header;
goto out_set_header;
}
vevent->data_len = data_len;
memcpy(vevent->event_data, event_data, data_len);
veventq->num_events++;
out_set_header:
iommufd_vevent_handler(veventq, vevent);
spin_unlock(&veventq->common.lock);
out_unlock_veventqs:
up_read(&viommu->veventqs_rwsem);
return rc;
}
EXPORT_SYMBOL_NS_GPL(iommufd_viommu_report_event, "IOMMUFD");
#ifdef CONFIG_IRQ_MSI_IOMMU
/*
* Get a iommufd_sw_msi_map for the msi physical address requested by the irq
* layer. The mapping to IOVA is global to the iommufd file descriptor, every
* domain that is attached to a device using the same MSI parameters will use
* the same IOVA.
*/
static struct iommufd_sw_msi_map *
iommufd_sw_msi_get_map(struct iommufd_ctx *ictx, phys_addr_t msi_addr,
phys_addr_t sw_msi_start)
{
struct iommufd_sw_msi_map *cur;
unsigned int max_pgoff = 0;
lockdep_assert_held(&ictx->sw_msi_lock);
list_for_each_entry(cur, &ictx->sw_msi_list, sw_msi_item) {
if (cur->sw_msi_start != sw_msi_start)
continue;
max_pgoff = max(max_pgoff, cur->pgoff + 1);
if (cur->msi_addr == msi_addr)
return cur;
}
if (ictx->sw_msi_id >=
BITS_PER_BYTE * sizeof_field(struct iommufd_sw_msi_maps, bitmap))
return ERR_PTR(-EOVERFLOW);
Annotation
- Immediate include surface: `iommufd_private.h`.
- Detected declarations: `function _iommufd_object_depend`, `function _iommufd_object_undepend`, `function _iommufd_alloc_mmap`, `function _iommufd_destroy_mmap`, `function iommufd_viommu_get_vdev_id`, `function iommufd_viommu_report_event`, `function iommufd_sw_msi_get_map`, `function list_for_each_entry`, `function iommufd_sw_msi_install`, `function iommufd_sw_msi`.
- Atlas domain: Driver Families / drivers/iommu.
- 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.