drivers/vfio/cdx/main.c

Source file repositories/reference/linux-study-clean/drivers/vfio/cdx/main.c

File Facts

System
Linux kernel
Corpus path
drivers/vfio/cdx/main.c
Extension
.c
Size
9352 bytes
Lines
363
Domain
Driver Families
Bucket
drivers/vfio
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

// SPDX-License-Identifier: GPL-2.0
/*
 * Copyright (C) 2022-2023, Advanced Micro Devices, Inc.
 */

#include <linux/vfio.h>
#include <linux/cdx/cdx_bus.h>

#include "private.h"

static int vfio_cdx_init_dev(struct vfio_device *core_vdev)
{
	struct vfio_cdx_device *vdev =
		container_of(core_vdev, struct vfio_cdx_device, vdev);

	mutex_init(&vdev->cdx_irqs_lock);
	return 0;
}

static void vfio_cdx_release_dev(struct vfio_device *core_vdev)
{
	struct vfio_cdx_device *vdev =
		container_of(core_vdev, struct vfio_cdx_device, vdev);

	mutex_destroy(&vdev->cdx_irqs_lock);
}

static int vfio_cdx_open_device(struct vfio_device *core_vdev)
{
	struct vfio_cdx_device *vdev =
		container_of(core_vdev, struct vfio_cdx_device, vdev);
	struct cdx_device *cdx_dev = to_cdx_device(core_vdev->dev);
	int count = cdx_dev->res_count;
	int i, ret;

	vdev->regions = kzalloc_objs(struct vfio_cdx_region, count,
				     GFP_KERNEL_ACCOUNT);
	if (!vdev->regions)
		return -ENOMEM;

	for (i = 0; i < count; i++) {
		struct resource *res = &cdx_dev->res[i];

		vdev->regions[i].addr = res->start;
		vdev->regions[i].size = resource_size(res);
		vdev->regions[i].type = res->flags;
		/*
		 * Only regions addressed with PAGE granularity may be
		 * MMAP'ed securely.
		 */
		if (!(vdev->regions[i].addr & ~PAGE_MASK) &&
		    !(vdev->regions[i].size & ~PAGE_MASK))
			vdev->regions[i].flags |=
					VFIO_REGION_INFO_FLAG_MMAP;
		vdev->regions[i].flags |= VFIO_REGION_INFO_FLAG_READ;
		if (!(cdx_dev->res[i].flags & IORESOURCE_READONLY))
			vdev->regions[i].flags |= VFIO_REGION_INFO_FLAG_WRITE;
	}
	ret = cdx_dev_reset(core_vdev->dev);
	if (ret) {
		kfree(vdev->regions);
		vdev->regions = NULL;
		return ret;
	}
	ret = cdx_clear_master(cdx_dev);
	if (ret)
		vdev->flags &= ~BME_SUPPORT;
	else
		vdev->flags |= BME_SUPPORT;

	return 0;
}

static void vfio_cdx_close_device(struct vfio_device *core_vdev)
{
	struct vfio_cdx_device *vdev =
		container_of(core_vdev, struct vfio_cdx_device, vdev);

	kfree(vdev->regions);
	cdx_dev_reset(core_vdev->dev);
	vfio_cdx_irqs_cleanup(vdev);
}

static int vfio_cdx_bm_ctrl(struct vfio_device *core_vdev, u32 flags,
			    void __user *arg, size_t argsz)
{
	size_t minsz =
		offsetofend(struct vfio_device_feature_bus_master, op);
	struct vfio_cdx_device *vdev =
		container_of(core_vdev, struct vfio_cdx_device, vdev);

Annotation

Implementation Notes