drivers/vhost/vdpa.c

Source file repositories/reference/linux-study-clean/drivers/vhost/vdpa.c

File Facts

System
Linux kernel
Corpus path
drivers/vhost/vdpa.c
Extension
.c
Size
40185 bytes
Lines
1699
Domain
Driver Families
Bucket
drivers/vhost
Inferred role
Driver Families: operation-table or driver-model contract
Status
pattern 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

static const struct file_operations vhost_vdpa_fops = {
	.owner		= THIS_MODULE,
	.open		= vhost_vdpa_open,
	.release	= vhost_vdpa_release,
	.write_iter	= vhost_vdpa_chr_write_iter,
	.unlocked_ioctl	= vhost_vdpa_unlocked_ioctl,
#ifdef CONFIG_MMU
	.mmap		= vhost_vdpa_mmap,
#endif /* CONFIG_MMU */
	.compat_ioctl	= compat_ptr_ioctl,
};

static void vhost_vdpa_release_dev(struct device *device)
{
	struct vhost_vdpa *v =
	       container_of(device, struct vhost_vdpa, dev);

	ida_free(&vhost_vdpa_ida, v->minor);
	kfree(v->vqs);
	kfree(v);
}

static int vhost_vdpa_probe(struct vdpa_device *vdpa)
{
	const struct vdpa_config_ops *ops = vdpa->config;
	struct vhost_vdpa *v;
	int minor;
	int i, r;

	/* We can't support platform IOMMU device with more than 1
	 * group or as
	 */
	if (!ops->set_map && !ops->dma_map &&
	    (vdpa->ngroups > 1 || vdpa->nas > 1))
		return -EOPNOTSUPP;

	v = kzalloc_obj(*v, GFP_KERNEL | __GFP_RETRY_MAYFAIL);
	if (!v)
		return -ENOMEM;

	minor = ida_alloc_max(&vhost_vdpa_ida, VHOST_VDPA_DEV_MAX - 1,
			      GFP_KERNEL);
	if (minor < 0) {
		kfree(v);
		return minor;
	}

	atomic_set(&v->opened, 0);
	v->minor = minor;
	v->vdpa = vdpa;
	v->nvqs = vdpa->nvqs;
	v->virtio_id = ops->get_device_id(vdpa);

	device_initialize(&v->dev);
	v->dev.release = vhost_vdpa_release_dev;
	v->dev.parent = &vdpa->dev;
	v->dev.devt = MKDEV(MAJOR(vhost_vdpa_major), minor);
	v->vqs = kmalloc_objs(struct vhost_virtqueue, v->nvqs);
	if (!v->vqs) {
		r = -ENOMEM;
		goto err;
	}

	r = dev_set_name(&v->dev, "vhost-vdpa-%u", minor);
	if (r)
		goto err;

	cdev_init(&v->cdev, &vhost_vdpa_fops);
	v->cdev.owner = THIS_MODULE;

	r = cdev_device_add(&v->cdev, &v->dev);
	if (r)
		goto err;

	init_completion(&v->completion);
	vdpa_set_drvdata(vdpa, v);

	for (i = 0; i < VHOST_VDPA_IOTLB_BUCKETS; i++)
		INIT_HLIST_HEAD(&v->as[i]);

	return 0;

err:
	put_device(&v->dev);
	return r;
}

static void vhost_vdpa_remove(struct vdpa_device *vdpa)
{
	struct vhost_vdpa *v = vdpa_get_drvdata(vdpa);

Annotation

Implementation Notes