drivers/fpga/dfl-fme-perf.c

Source file repositories/reference/linux-study-clean/drivers/fpga/dfl-fme-perf.c

File Facts

System
Linux kernel
Corpus path
drivers/fpga/dfl-fme-perf.c
Extension
.c
Size
30226 bytes
Lines
1023
Domain
Driver Families
Bucket
drivers/fpga
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

struct fme_perf_priv {
	struct device *dev;
	void __iomem *ioaddr;
	struct pmu pmu;
	u16 id;

	u32 fab_users;
	u32 fab_port_id;
	spinlock_t fab_lock;

	unsigned int cpu;
	struct hlist_node node;
	enum cpuhp_state cpuhp_state;
};

/**
 * struct fme_perf_event_ops - callbacks for fme perf events
 *
 * @event_init: callback invoked during event init.
 * @event_destroy: callback invoked during event destroy.
 * @read_counter: callback to read hardware counters.
 */
struct fme_perf_event_ops {
	int (*event_init)(struct fme_perf_priv *priv, u32 event, u32 portid);
	void (*event_destroy)(struct fme_perf_priv *priv, u32 event,
			      u32 portid);
	u64 (*read_counter)(struct fme_perf_priv *priv, u32 event, u32 portid);
};

#define to_fme_perf_priv(_pmu)	container_of(_pmu, struct fme_perf_priv, pmu)

static ssize_t cpumask_show(struct device *dev,
			    struct device_attribute *attr, char *buf)
{
	struct pmu *pmu = dev_get_drvdata(dev);
	struct fme_perf_priv *priv;

	priv = to_fme_perf_priv(pmu);

	return cpumap_print_to_pagebuf(true, buf, cpumask_of(priv->cpu));
}
static DEVICE_ATTR_RO(cpumask);

static struct attribute *fme_perf_cpumask_attrs[] = {
	&dev_attr_cpumask.attr,
	NULL,
};

static const struct attribute_group fme_perf_cpumask_group = {
	.attrs = fme_perf_cpumask_attrs,
};

#define FME_EVENT_MASK		GENMASK_ULL(11, 0)
#define FME_EVENT_SHIFT		0
#define FME_EVTYPE_MASK		GENMASK_ULL(15, 12)
#define FME_EVTYPE_SHIFT	12
#define FME_EVTYPE_BASIC	0
#define FME_EVTYPE_CACHE	1
#define FME_EVTYPE_FABRIC	2
#define FME_EVTYPE_VTD		3
#define FME_EVTYPE_VTD_SIP	4
#define FME_EVTYPE_MAX		FME_EVTYPE_VTD_SIP
#define FME_PORTID_MASK		GENMASK_ULL(23, 16)
#define FME_PORTID_SHIFT	16
#define FME_PORTID_ROOT		(0xffU)

#define get_event(_config)	FIELD_GET(FME_EVENT_MASK, _config)
#define get_evtype(_config)	FIELD_GET(FME_EVTYPE_MASK, _config)
#define get_portid(_config)	FIELD_GET(FME_PORTID_MASK, _config)

PMU_FORMAT_ATTR(event,		"config:0-11");
PMU_FORMAT_ATTR(evtype,		"config:12-15");
PMU_FORMAT_ATTR(portid,		"config:16-23");

static struct attribute *fme_perf_format_attrs[] = {
	&format_attr_event.attr,
	&format_attr_evtype.attr,
	&format_attr_portid.attr,
	NULL,
};

static const struct attribute_group fme_perf_format_group = {
	.name = "format",
	.attrs = fme_perf_format_attrs,
};

/*
 * There are no default events, but we need to create
 * "events" group (with empty attrs) before updating
 * it with detected events (using pmu->attr_update).

Annotation

Implementation Notes