drivers/vfio/fsl-mc/vfio_fsl_mc.c

Source file repositories/reference/linux-study-clean/drivers/vfio/fsl-mc/vfio_fsl_mc.c

File Facts

System
Linux kernel
Corpus path
drivers/vfio/fsl-mc/vfio_fsl_mc.c
Extension
.c
Size
15726 bytes
Lines
605
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

if (ret) {
			fsl_mc_obj_close(mc_dev->mc_io, 0, token);
			goto out;
		}
		ret = fsl_mc_obj_close(mc_dev->mc_io, 0, token);
	}
out:
	return ret;
}

static void vfio_fsl_mc_close_device(struct vfio_device *core_vdev)
{
	struct vfio_fsl_mc_device *vdev =
		container_of(core_vdev, struct vfio_fsl_mc_device, vdev);
	struct fsl_mc_device *mc_dev = vdev->mc_dev;
	struct device *cont_dev = fsl_mc_cont_dev(&mc_dev->dev);
	struct fsl_mc_device *mc_cont = to_fsl_mc_device(cont_dev);
	int ret;

	vfio_fsl_mc_regions_cleanup(vdev);

	/* reset the device before cleaning up the interrupts */
	ret = vfio_fsl_mc_reset_device(vdev);

	if (ret)
		dev_warn(&mc_cont->dev,
			 "VFIO_FSL_MC: reset device has failed (%d)\n", ret);

	vfio_fsl_mc_irqs_cleanup(vdev);

	fsl_mc_cleanup_irq_pool(mc_cont);
}

static int vfio_fsl_mc_ioctl_get_region_info(struct vfio_device *core_vdev,
					     struct vfio_region_info *info,
					     struct vfio_info_cap *caps)
{
	struct vfio_fsl_mc_device *vdev =
		container_of(core_vdev, struct vfio_fsl_mc_device, vdev);
	struct fsl_mc_device *mc_dev = vdev->mc_dev;

	if (info->index >= mc_dev->obj_desc.region_count)
		return -EINVAL;

	/* map offset to the physical address  */
	info->offset = VFIO_FSL_MC_INDEX_TO_OFFSET(info->index);
	info->size = vdev->regions[info->index].size;
	info->flags = vdev->regions[info->index].flags;
	return 0;
}

static long vfio_fsl_mc_ioctl(struct vfio_device *core_vdev,
			      unsigned int cmd, unsigned long arg)
{
	unsigned long minsz;
	struct vfio_fsl_mc_device *vdev =
		container_of(core_vdev, struct vfio_fsl_mc_device, vdev);
	struct fsl_mc_device *mc_dev = vdev->mc_dev;

	switch (cmd) {
	case VFIO_DEVICE_GET_INFO:
	{
		struct vfio_device_info info;

		minsz = offsetofend(struct vfio_device_info, num_irqs);

		if (copy_from_user(&info, (void __user *)arg, minsz))
			return -EFAULT;

		if (info.argsz < minsz)
			return -EINVAL;

		info.flags = VFIO_DEVICE_FLAGS_FSL_MC;

		if (is_fsl_mc_bus_dprc(mc_dev))
			info.flags |= VFIO_DEVICE_FLAGS_RESET;

		info.num_regions = mc_dev->obj_desc.region_count;
		info.num_irqs = mc_dev->obj_desc.irq_count;

		return copy_to_user((void __user *)arg, &info, minsz) ?
			-EFAULT : 0;
	}
	case VFIO_DEVICE_GET_IRQ_INFO:
	{
		struct vfio_irq_info info;

		minsz = offsetofend(struct vfio_irq_info, count);
		if (copy_from_user(&info, (void __user *)arg, minsz))
			return -EFAULT;

Annotation

Implementation Notes