On Thu, Jan 16, 2020 at 08:42:31PM +0800, Jason Wang wrote:
This patch implements a software vDPA networking device. The datapathThis is very gross, creating a class just to get a create/remove and
is implemented through vringh and workqueue. The device has an on-chip
IOMMU which translates IOVA to PA. For kernel virtio drivers, vDPA
simulator driver provides dma_ops. For vhost driers, set_map() methods
of vdpa_config_ops is implemented to accept mappings from vhost.
A sysfs based management interface is implemented, devices are
created and removed through:
/sys/devices/virtual/vdpa_simulator/netdev/{create|remove}
then not using the class for anything else? Yuk.
Netlink based lifecycle management could be implemented for vDPAThis is just begging for a netlink based approach.
simulator as well.
Certainly netlink driven removal should be an agreeable standard for
all devices, I think.
+struct vdpasim_virtqueue {Is not using static here intentional?
+ struct vringh vring;
+ struct vringh_kiov iov;
+ unsigned short head;
+ bool ready;
+ u64 desc_addr;
+ u64 device_addr;
+ u64 driver_addr;
+ u32 num;
+ void *private;
+ irqreturn_t (*cb)(void *data);
+};
+
+#define VDPASIM_QUEUE_ALIGN PAGE_SIZE
+#define VDPASIM_QUEUE_MAX 256
+#define VDPASIM_DEVICE_ID 0x1
+#define VDPASIM_VENDOR_ID 0
+#define VDPASIM_VQ_NUM 0x2
+#define VDPASIM_CLASS_NAME "vdpa_simulator"
+#define VDPASIM_NAME "netdev"
+
+u64 vdpasim_features = (1ULL << VIRTIO_F_ANY_LAYOUT) |
+ (1ULL << VIRTIO_F_VERSION_1) |
+ (1ULL << VIRTIO_F_IOMMU_PLATFORM);
+static void vdpasim_release_dev(struct device *_d)It is again a bit weird to see a realease function in a driver. This
+{
+ struct vdpa_device *vdpa = dev_to_vdpa(_d);
+ struct vdpasim *vdpasim = vdpa_to_sim(vdpa);
+
+ sysfs_remove_link(vdpasim_dev->devices_kobj, vdpasim->name);
+
+ mutex_lock(&vsim_list_lock);
+ list_del(&vdpasim->next);
+ mutex_unlock(&vsim_list_lock);
+
+ kfree(vdpasim->buffer);
+ kfree(vdpasim);
+}
stuff is usually in the remove remove function.
+static int vdpasim_create(const guid_t *uuid)The goto err_link does the wrong unwind, once register is completed
+{
+ struct vdpasim *vdpasim, *tmp;
+ struct virtio_net_config *config;
+ struct vdpa_device *vdpa;
+ struct device *dev;
+ int ret = -ENOMEM;
+
+ mutex_lock(&vsim_list_lock);
+ list_for_each_entry(tmp, &vsim_devices_list, next) {
+ if (guid_equal(&tmp->uuid, uuid)) {
+ mutex_unlock(&vsim_list_lock);
+ return -EEXIST;
+ }
+ }
+
+ vdpasim = kzalloc(sizeof(*vdpasim), GFP_KERNEL);
+ if (!vdpasim)
+ goto err_vdpa_alloc;
+
+ vdpasim->buffer = kmalloc(PAGE_SIZE, GFP_KERNEL);
+ if (!vdpasim->buffer)
+ goto err_buffer_alloc;
+
+ vdpasim->iommu = vhost_iotlb_alloc(2048, 0);
+ if (!vdpasim->iommu)
+ goto err_iotlb;
+
+ config = &vdpasim->config;
+ config->mtu = 1500;
+ config->status = VIRTIO_NET_S_LINK_UP;
+ eth_random_addr(config->mac);
+
+ INIT_WORK(&vdpasim->work, vdpasim_work);
+ spin_lock_init(&vdpasim->lock);
+
+ guid_copy(&vdpasim->uuid, uuid);
+
+ list_add(&vdpasim->next, &vsim_devices_list);
+ vdpa = &vdpasim->vdpa;
+
+ mutex_unlock(&vsim_list_lock);
+
+ vdpa = &vdpasim->vdpa;
+ vdpa->config = &vdpasim_net_config_ops;
+ vdpa_set_parent(vdpa, &vdpasim_dev->dev);
+ vdpa->dev.release = vdpasim_release_dev;
+
+ vringh_set_iotlb(&vdpasim->vqs[0].vring, vdpasim->iommu);
+ vringh_set_iotlb(&vdpasim->vqs[1].vring, vdpasim->iommu);
+
+ dev = &vdpa->dev;
+ dev->coherent_dma_mask = DMA_BIT_MASK(64);
+ set_dma_ops(dev, &vdpasim_dma_ops);
+
+ ret = register_vdpa_device(vdpa);
+ if (ret)
+ goto err_register;
+
+ sprintf(vdpasim->name, "%pU", uuid);
+
+ ret = sysfs_create_link(vdpasim_dev->devices_kobj, &vdpa->dev.kobj,
+ vdpasim->name);
+ if (ret)
+ goto err_link;
the error unwind is unregister & put_device, not kfree. This is why I
recommend to always initalize the device early, and always using
put_device during error unwinds.
This whole guid thing seems unncessary when the device is immediately
assigned a vdpa index from the ida.
If you were not using syfs you'd
just return that index from the creation netlink.
Jason