tools/testing/selftests/vfio/lib/drivers/dsa/dsa.c

Source file repositories/reference/linux-study-clean/tools/testing/selftests/vfio/lib/drivers/dsa/dsa.c

File Facts

System
Linux kernel
Corpus path
tools/testing/selftests/vfio/lib/drivers/dsa/dsa.c
Extension
.c
Size
11648 bytes
Lines
428
Domain
Support Tooling And Documentation
Bucket
tools
Inferred role
Support Tooling And Documentation: implementation source
Status
source implementation candidate

Why This File Exists

Repository support layer: documentation, build tooling, samples, user-space helper tools, generated initramfs support, licenses, and validation utilities.

Dependency Surface

Detected Declarations

Annotated Snippet

struct dsa_state {
	/* Descriptors for copy and batch operations. */
	struct dsa_hw_desc batch[32];
	struct dsa_hw_desc copy[1024];

	/* Completion records for copy and batch operations. */
	struct dsa_completion_record copy_completion;
	struct dsa_completion_record batch_completion;

	/* Cached device registers (and derived data) for easy access */
	union gen_cap_reg gen_cap;
	union wq_cap_reg wq_cap;
	union group_cap_reg group_cap;
	union engine_cap_reg engine_cap;
	union offsets_reg table_offsets;
	void *wqcfg_table;
	void *grpcfg_table;
	u64 max_batches;
	u64 max_copies_per_batch;

	/* The number of ongoing memcpy operations. */
	u64 memcpy_count;

	/* Buffers used by dsa_send_msi() to generate an interrupt */
	u64 send_msi_src;
	u64 send_msi_dst;
};

static inline struct dsa_state *to_dsa_state(struct vfio_pci_device *device)
{
	return device->driver.region.vaddr;
}

static bool dsa_int_handle_request_required(struct vfio_pci_device *device)
{
	void *bar0 = device->bars[0].vaddr;
	union gen_cap_reg gen_cap;
	u32 cmd_cap;

	gen_cap.bits = readq(bar0 + IDXD_GENCAP_OFFSET);
	if (!gen_cap.cmd_cap)
		return false;

	cmd_cap = readl(bar0 + IDXD_CMDCAP_OFFSET);
	return (cmd_cap >> IDXD_CMD_REQUEST_INT_HANDLE) & 1;
}

static int dsa_probe(struct vfio_pci_device *device)
{
	const u16 vendor_id = vfio_pci_config_readw(device, PCI_VENDOR_ID);
	const u16 device_id = vfio_pci_config_readw(device, PCI_DEVICE_ID);

	if (vendor_id != PCI_VENDOR_ID_INTEL)
		return -EINVAL;

	switch (device_id) {
	case PCI_DEVICE_ID_INTEL_DSA_SPR0:
	case PCI_DEVICE_ID_INTEL_DSA_DMR:
	case PCI_DEVICE_ID_INTEL_DSA_GNRD:
		break;
	default:
		return -EINVAL;
	}

	if (dsa_int_handle_request_required(device)) {
		dev_err(device, "Device requires requesting interrupt handles\n");
		return -EINVAL;
	}

	return 0;
}

static void dsa_check_sw_err(struct vfio_pci_device *device)
{
	void *reg = device->bars[0].vaddr + IDXD_SWERR_OFFSET;
	union sw_err_reg err = {};
	int i;

	for (i = 0; i < ARRAY_SIZE(err.bits); i++) {
		err.bits[i] = readq(reg + offsetof(union sw_err_reg, bits[i]));

		/* No errors */
		if (i == 0 && !err.valid)
			return;
	}

	dev_err(device, "SWERR: 0x%016lx 0x%016lx 0x%016lx 0x%016lx\n",
		err.bits[0], err.bits[1], err.bits[2], err.bits[3]);

	dev_err(device, "  valid: 0x%x\n", err.valid);

Annotation

Implementation Notes