@@ -28,6 +28,7 @@
#include <linux/vhost_iotlb.h>
#include <uapi/linux/virtio_config.h>
#include <uapi/linux/virtio_net.h>
+#include <uapi/linux/vdpa.h>
#define DRV_VERSION "0.1"
#define DRV_AUTHOR "Jason Wang <jasowang@redhat.com>"
@@ -42,6 +43,17 @@ static char *macaddr;
module_param(macaddr, charp, 0);
MODULE_PARM_DESC(macaddr, "Ethernet MAC address");
+static struct vdpa_parent_dev parent_dev;
+
+static void vdpasim_parent_release(struct device *dev)
+{
+}
+
+static struct device vdpasim_parent = {
+ .init_name = "vdpasim",
+ .release = vdpasim_parent_release,
+};
+
struct vdpasim_virtqueue {
struct vringh vring;
struct vringh_kiov iov;
@@ -101,8 +113,6 @@ static inline __virtio16 cpu_to_vdpasim16(struct vdpasim *vdpasim, u16 val)
return __cpu_to_virtio16(vdpasim_is_little_endian(vdpasim), val);
}
-static struct vdpasim *vdpasim_dev;
-
static struct vdpasim *vdpa_to_sim(struct vdpa_device *vdpa)
{
return container_of(vdpa, struct vdpasim, vdpa);
@@ -345,7 +355,7 @@ static const struct dma_map_ops vdpasim_dma_ops = {
static const struct vdpa_config_ops vdpasim_net_config_ops;
static const struct vdpa_config_ops vdpasim_net_batch_config_ops;
-static struct vdpasim *vdpasim_create(void)
+static struct vdpasim *vdpasim_create(const char *name)
{
const struct vdpa_config_ops *ops;
struct vdpasim *vdpasim;
@@ -357,7 +367,7 @@ static struct vdpasim *vdpasim_create(void)
else
ops = &vdpasim_net_config_ops;
- vdpasim = vdpa_alloc_device(struct vdpasim, vdpa, NULL, ops, VDPASIM_VQ_NUM, NULL);
+ vdpasim = vdpa_alloc_device(struct vdpasim, vdpa, NULL, ops, VDPASIM_VQ_NUM, name);
if (!vdpasim)
goto err_alloc;
@@ -393,7 +403,8 @@ static struct vdpasim *vdpasim_create(void)
vringh_set_iotlb(&vdpasim->vqs[1].vring, vdpasim->iommu);
vdpasim->vdpa.dma_dev = dev;
- ret = vdpa_register_device(&vdpasim->vdpa);
+ vdpasim->vdpa.pdev = &parent_dev;
+ ret = _vdpa_register_device(&vdpasim->vdpa);
if (ret)
goto err_iommu;
@@ -714,21 +725,67 @@ static const struct vdpa_config_ops vdpasim_net_batch_config_ops = {
.free = vdpasim_free,
};
+static struct vdpa_device *
+vdpa_dev_add(struct vdpa_parent_dev *pdev, const char *name, u32 device_id)
+{
+ struct vdpasim *simdev;
+
+ if (device_id != VIRTIO_ID_NET)
+ return ERR_PTR(-EOPNOTSUPP);
+
+ simdev = vdpasim_create(name);
+ if (IS_ERR(simdev))
+ return (struct vdpa_device *)simdev;
+
+ return &simdev->vdpa;
+}
+
+static void vdpa_dev_del(struct vdpa_parent_dev *pdev, struct vdpa_device *dev)
+{
+ struct vdpasim *simdev = container_of(dev, struct vdpasim, vdpa);
+
+ _vdpa_unregister_device(&simdev->vdpa);
+}
+
+static const struct vdpa_dev_ops vdpa_dev_parent_ops = {
+ .dev_add = vdpa_dev_add,
+ .dev_del = vdpa_dev_del
+};
+
+static struct virtio_device_id id_table[] = {
+ { VIRTIO_ID_NET, VIRTIO_DEV_ANY_ID },
+ { 0 },
+};
+
+static struct vdpa_parent_dev parent_dev = {
+ .device = &vdpasim_parent,
+ .id_table = id_table,
+ .ops = &vdpa_dev_parent_ops,
+};
+
static int __init vdpasim_dev_init(void)
{
- vdpasim_dev = vdpasim_create();
+ int ret;
- if (!IS_ERR(vdpasim_dev))
- return 0;
+ ret = device_register(&vdpasim_parent);
+ if (ret)
+ return ret;
+
+ ret = vdpa_parentdev_register(&parent_dev);
+ if (ret)
+ goto parent_err;
- return PTR_ERR(vdpasim_dev);
+ return 0;
+
+parent_err:
+ device_unregister(&vdpasim_parent);
+ return ret;
}
static void __exit vdpasim_dev_exit(void)
{
- struct vdpa_device *vdpa = &vdpasim_dev->vdpa;
-
- vdpa_unregister_device(vdpa);
+ vdpa_parentdev_unregister(&parent_dev);
+ device_unregister(&vdpasim_parent);
}
module_init(vdpasim_dev_init)