drivers/dma/idxd/perfmon.c
Source file repositories/reference/linux-study-clean/drivers/dma/idxd/perfmon.c
File Facts
- System
- Linux kernel
- Corpus path
drivers/dma/idxd/perfmon.c- Extension
.c- Size
- 14368 bytes
- Lines
- 563
- Domain
- Driver Families
- Bucket
- drivers/dma
- 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.
- 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.
- 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/sched/task.hlinux/io-64-nonatomic-lo-hi.hidxd.hperfmon.h
Detected Declarations
function is_idxd_eventfunction perfmon_collect_eventsfunction for_each_sibling_eventfunction perfmon_assign_hw_eventfunction perfmon_assign_eventfunction perfmon_validate_groupfunction perfmon_pmu_event_initfunction perfmon_pmu_read_counterfunction perfmon_pmu_event_updatefunction perfmon_counter_overflowfunction for_each_set_bitfunction perfmon_reset_configfunction perfmon_reset_countersfunction perfmon_resetfunction perfmon_pmu_event_startfunction perfmon_pmu_event_stopfunction perfmon_pmu_event_delfunction perfmon_pmu_event_addfunction enable_perfmon_pmufunction disable_perfmon_pmufunction perfmon_pmu_enablefunction perfmon_pmu_disablefunction skip_filterfunction idxd_pmu_initfunction perfmon_pmu_removefunction perfmon_pmu_init
Annotated Snippet
if (idx < 0) {
ret = idx;
goto out;
}
}
out:
kfree(fake_pmu);
return ret;
}
static int perfmon_pmu_event_init(struct perf_event *event)
{
struct idxd_device *idxd;
int ret = 0;
idxd = event_to_idxd(event);
event->hw.idx = -1;
if (event->attr.type != event->pmu->type)
return -ENOENT;
/* sampling not supported */
if (event->attr.sample_period)
return -EINVAL;
if (event->cpu < 0)
return -EINVAL;
if (event->pmu != &idxd->idxd_pmu->pmu)
return -EINVAL;
event->hw.event_base = ioread64(PERFMON_TABLE_OFFSET(idxd));
event->hw.config = event->attr.config;
if (event->group_leader != event)
/* non-group events have themselves as leader */
ret = perfmon_validate_group(idxd->idxd_pmu, event);
return ret;
}
static inline u64 perfmon_pmu_read_counter(struct perf_event *event)
{
struct hw_perf_event *hwc = &event->hw;
struct idxd_device *idxd;
int cntr = hwc->idx;
idxd = event_to_idxd(event);
return ioread64(CNTRDATA_REG(idxd, cntr));
}
static void perfmon_pmu_event_update(struct perf_event *event)
{
struct idxd_device *idxd = event_to_idxd(event);
u64 prev_raw_count, new_raw_count, delta, p, n;
int shift = 64 - idxd->idxd_pmu->counter_width;
struct hw_perf_event *hwc = &event->hw;
prev_raw_count = local64_read(&hwc->prev_count);
do {
new_raw_count = perfmon_pmu_read_counter(event);
} while (!local64_try_cmpxchg(&hwc->prev_count,
&prev_raw_count, new_raw_count));
n = (new_raw_count << shift);
p = (prev_raw_count << shift);
delta = ((n - p) >> shift);
local64_add(delta, &event->count);
}
void perfmon_counter_overflow(struct idxd_device *idxd)
{
int i, n_counters, max_loop = OVERFLOW_SIZE;
struct perf_event *event;
unsigned long ovfstatus;
n_counters = min(idxd->idxd_pmu->n_counters, OVERFLOW_SIZE);
ovfstatus = ioread32(OVFSTATUS_REG(idxd));
/*
* While updating overflowed counters, other counters behind
* them could overflow and be missed in a given pass.
* Normally this could happen at most n_counters times, but in
* theory a tiny counter width could result in continual
* overflows and endless looping. max_loop provides a
* failsafe in that highly unlikely case.
Annotation
- Immediate include surface: `linux/sched/task.h`, `linux/io-64-nonatomic-lo-hi.h`, `idxd.h`, `perfmon.h`.
- Detected declarations: `function is_idxd_event`, `function perfmon_collect_events`, `function for_each_sibling_event`, `function perfmon_assign_hw_event`, `function perfmon_assign_event`, `function perfmon_validate_group`, `function perfmon_pmu_event_init`, `function perfmon_pmu_read_counter`, `function perfmon_pmu_event_update`, `function perfmon_counter_overflow`.
- Atlas domain: Driver Families / drivers/dma.
- Implementation status: source implementation candidate.
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.