drivers/iommu/dma-iommu.c

Source file repositories/reference/linux-study-clean/drivers/iommu/dma-iommu.c

File Facts

System
Linux kernel
Corpus path
drivers/iommu/dma-iommu.c
Extension
.c
Size
63115 bytes
Lines
2266
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.

Dependency Surface

Detected Declarations

Annotated Snippet

struct iommu_dma_msi_page {
	struct list_head	list;
	dma_addr_t		iova;
	phys_addr_t		phys;
};

enum iommu_dma_queue_type {
	IOMMU_DMA_OPTS_PER_CPU_QUEUE,
	IOMMU_DMA_OPTS_SINGLE_QUEUE,
};

struct iommu_dma_options {
	enum iommu_dma_queue_type qt;
	size_t		fq_size;
	unsigned int	fq_timeout;
};

struct iommu_dma_cookie {
	struct iova_domain iovad;
	struct list_head msi_page_list;
	/* Flush queue */
	union {
		struct iova_fq *single_fq;
		struct iova_fq __percpu *percpu_fq;
	};
	/* Number of TLB flushes that have been started */
	atomic64_t fq_flush_start_cnt;
	/* Number of TLB flushes that have been finished */
	atomic64_t fq_flush_finish_cnt;
	/* Timer to regularily empty the flush queues */
	struct timer_list fq_timer;
	/* 1 when timer is active, 0 when not */
	atomic_t fq_timer_on;
	/* Domain for flush queue callback; NULL if flush queue not in use */
	struct iommu_domain *fq_domain;
	/* Options for dma-iommu use */
	struct iommu_dma_options options;
};

struct iommu_dma_msi_cookie {
	dma_addr_t msi_iova;
	struct list_head msi_page_list;
};

static DEFINE_STATIC_KEY_FALSE(iommu_deferred_attach_enabled);
bool iommu_dma_forcedac __read_mostly;

static int __init iommu_dma_forcedac_setup(char *str)
{
	int ret = kstrtobool(str, &iommu_dma_forcedac);

	if (!ret && iommu_dma_forcedac)
		pr_info("Forcing DAC for PCI devices\n");
	return ret;
}
early_param("iommu.forcedac", iommu_dma_forcedac_setup);

/* Number of entries per flush queue */
#define IOVA_DEFAULT_FQ_SIZE	256
#define IOVA_SINGLE_FQ_SIZE	32768

/* Timeout (in ms) after which entries are flushed from the queue */
#define IOVA_DEFAULT_FQ_TIMEOUT	10
#define IOVA_SINGLE_FQ_TIMEOUT	1000

/* Flush queue entry for deferred flushing */
struct iova_fq_entry {
	unsigned long iova_pfn;
	unsigned long pages;
	struct iommu_pages_list freelist;
	u64 counter; /* Flush counter when this entry was added */
};

/* Per-CPU flush queue structure */
struct iova_fq {
	spinlock_t lock;
	unsigned int head, tail;
	unsigned int mod_mask;
	struct iova_fq_entry entries[];
};

#define fq_ring_for_each(i, fq) \
	for ((i) = (fq)->head; (i) != (fq)->tail; (i) = ((i) + 1) & (fq)->mod_mask)

static inline bool fq_full(struct iova_fq *fq)
{
	assert_spin_locked(&fq->lock);
	return (((fq->tail + 1) & fq->mod_mask) == fq->head);
}

Annotation

Implementation Notes