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

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

File Facts

System
Linux kernel
Corpus path
tools/testing/selftests/vfio/lib/drivers/ioat/ioat.c
Extension
.c
Size
5973 bytes
Lines
236
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 ioat_state {
	/* Single descriptor used to issue DMA memcpy operations */
	struct ioat_dma_descriptor desc;

	/* Copy buffers used by ioat_send_msi() to generate an interrupt. */
	u64 send_msi_src;
	u64 send_msi_dst;
};

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

static inline void *ioat_channel_registers(struct vfio_pci_device *device)
{
	return device->bars[0].vaddr + IOAT_CHANNEL_MMIO_SIZE;
}

static int ioat_probe(struct vfio_pci_device *device)
{
	u8 version;
	int r;

	if (!vfio_pci_device_match(device, PCI_VENDOR_ID_INTEL,
				   PCI_DEVICE_ID_INTEL_IOAT_SKX))
		return -EINVAL;

	VFIO_ASSERT_NOT_NULL(device->bars[0].vaddr);

	version = readb(device->bars[0].vaddr + IOAT_VER_OFFSET);
	switch (version) {
	case IOAT_VER_3_2:
	case IOAT_VER_3_3:
		r = 0;
		break;
	default:
		dev_err(device, "ioat: Unsupported version: 0x%x\n", version);
		r = -EINVAL;
	}
	return r;
}

static u64 ioat_channel_status(void *bar)
{
	return readq(bar + IOAT_CHANSTS_OFFSET) & IOAT_CHANSTS_STATUS;
}

static void ioat_clear_errors(struct vfio_pci_device *device)
{
	void *registers = ioat_channel_registers(device);
	u32 errors;

	errors = vfio_pci_config_readl(device, IOAT_PCI_CHANERR_INT_OFFSET);
	vfio_pci_config_writel(device, IOAT_PCI_CHANERR_INT_OFFSET, errors);

	errors = vfio_pci_config_readl(device, IOAT_PCI_DMAUNCERRSTS_OFFSET);
	vfio_pci_config_writel(device, IOAT_PCI_CHANERR_INT_OFFSET, errors);

	errors = readl(registers + IOAT_CHANERR_OFFSET);
	writel(errors, registers + IOAT_CHANERR_OFFSET);
}

static void ioat_reset(struct vfio_pci_device *device)
{
	void *registers = ioat_channel_registers(device);
	u32 sleep_ms = 1, attempts = 5000 / sleep_ms;
	u8 chancmd;

	ioat_clear_errors(device);

	writeb(IOAT_CHANCMD_RESET, registers + IOAT2_CHANCMD_OFFSET);

	for (;;) {
		chancmd = readb(registers + IOAT2_CHANCMD_OFFSET);
		if (!(chancmd & IOAT_CHANCMD_RESET))
			break;

		VFIO_ASSERT_GT(--attempts, 0);
		usleep(sleep_ms * 1000);
	}

	VFIO_ASSERT_EQ(ioat_channel_status(registers), IOAT_CHANSTS_HALTED);
}

static void ioat_init(struct vfio_pci_device *device)
{
	struct ioat_state *ioat = to_ioat_state(device);
	u8 intrctrl;

Annotation

Implementation Notes