drivers/iommu/intel/perf.c

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

File Facts

System
Linux kernel
Corpus path
drivers/iommu/intel/perf.c
Extension
.c
Size
4006 bytes
Lines
165
Domain
Driver Families
Bucket
drivers/iommu
Inferred role
Driver Families: implementation source
Status
source 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

if (!iommu->perf_statistic) {
			ret = -ENOMEM;
			goto unlock_out;
		}
	}

	lstat = iommu->perf_statistic;

	if (!lstat[type].enabled) {
		lstat[type].enabled = true;
		lstat[type].counter[COUNTS_MIN] = UINT_MAX;
		ret = 0;
	}
unlock_out:
	spin_unlock_irqrestore(&latency_lock, flags);

	return ret;
}

void dmar_latency_disable(struct intel_iommu *iommu, enum latency_type type)
{
	struct latency_statistic *lstat = iommu->perf_statistic;
	unsigned long flags;

	if (!dmar_latency_enabled(iommu, type))
		return;

	spin_lock_irqsave(&latency_lock, flags);
	memset(&lstat[type], 0, sizeof(*lstat) * DMAR_LATENCY_NUM);
	spin_unlock_irqrestore(&latency_lock, flags);
}

void dmar_latency_update(struct intel_iommu *iommu, enum latency_type type, u64 latency)
{
	struct latency_statistic *lstat = iommu->perf_statistic;
	unsigned long flags;
	u64 min, max;

	if (!dmar_latency_enabled(iommu, type))
		return;

	spin_lock_irqsave(&latency_lock, flags);
	if (latency < 100)
		lstat[type].counter[COUNTS_10e2]++;
	else if (latency < 1000)
		lstat[type].counter[COUNTS_10e3]++;
	else if (latency < 10000)
		lstat[type].counter[COUNTS_10e4]++;
	else if (latency < 100000)
		lstat[type].counter[COUNTS_10e5]++;
	else if (latency < 1000000)
		lstat[type].counter[COUNTS_10e6]++;
	else if (latency < 10000000)
		lstat[type].counter[COUNTS_10e7]++;
	else
		lstat[type].counter[COUNTS_10e8_plus]++;

	min = lstat[type].counter[COUNTS_MIN];
	max = lstat[type].counter[COUNTS_MAX];
	lstat[type].counter[COUNTS_MIN] = min_t(u64, min, latency);
	lstat[type].counter[COUNTS_MAX] = max_t(u64, max, latency);
	lstat[type].counter[COUNTS_SUM] += latency;
	lstat[type].samples++;
	spin_unlock_irqrestore(&latency_lock, flags);
}

static char *latency_counter_names[] = {
	"                  <0.1us",
	"   0.1us-1us", "    1us-10us", "  10us-100us",
	"   100us-1ms", "    1ms-10ms", "      >=10ms",
	"     min(us)", "     max(us)", " average(us)"
};

static char *latency_type_names[] = {
	"   inv_iotlb", "  inv_devtlb", "     inv_iec",
	"     svm_prq"
};

void dmar_latency_snapshot(struct intel_iommu *iommu, char *str, size_t size)
{
	struct latency_statistic *lstat = iommu->perf_statistic;
	unsigned long flags;
	int bytes = 0, i, j;

	memset(str, 0, size);

	for (i = 0; i < COUNTS_NUM; i++)
		bytes += scnprintf(str + bytes, size - bytes,
				  "%s", latency_counter_names[i]);

Annotation

Implementation Notes