Commit d4438d23 authored by Xie Yongji's avatar Xie Yongji Committed by Michael S. Tsirkin

vduse: Delay iova domain creation

Delay creating iova domain until the vduse device is
registered to vdpa bus.

This is a preparation for adding sysfs interface to
support specifying bounce buffer size for the iova
domain.
Signed-off-by: default avatarXie Yongji <xieyongji@bytedance.com>
Acked-by: default avatarJason Wang <jasowang@redhat.com>
Message-Id: <20230323053043.35-11-xieyongji@bytedance.com>
Signed-off-by: default avatarMichael S. Tsirkin <mst@redhat.com>
parent e38632dd
...@@ -111,6 +111,8 @@ struct vduse_dev { ...@@ -111,6 +111,8 @@ struct vduse_dev {
u32 vq_align; u32 vq_align;
struct vduse_umem *umem; struct vduse_umem *umem;
struct mutex mem_lock; struct mutex mem_lock;
unsigned int bounce_size;
struct mutex domain_lock;
}; };
struct vduse_dev_msg { struct vduse_dev_msg {
...@@ -425,7 +427,7 @@ static void vduse_dev_reset(struct vduse_dev *dev) ...@@ -425,7 +427,7 @@ static void vduse_dev_reset(struct vduse_dev *dev)
struct vduse_iova_domain *domain = dev->domain; struct vduse_iova_domain *domain = dev->domain;
/* The coherent mappings are handled in vduse_dev_free_coherent() */ /* The coherent mappings are handled in vduse_dev_free_coherent() */
if (domain->bounce_map) if (domain && domain->bounce_map)
vduse_domain_reset_bounce_map(domain); vduse_domain_reset_bounce_map(domain);
down_write(&dev->rwsem); down_write(&dev->rwsem);
...@@ -993,6 +995,9 @@ static int vduse_dev_dereg_umem(struct vduse_dev *dev, ...@@ -993,6 +995,9 @@ static int vduse_dev_dereg_umem(struct vduse_dev *dev,
goto unlock; goto unlock;
ret = -EINVAL; ret = -EINVAL;
if (!dev->domain)
goto unlock;
if (dev->umem->iova != iova || size != dev->domain->bounce_size) if (dev->umem->iova != iova || size != dev->domain->bounce_size)
goto unlock; goto unlock;
...@@ -1019,7 +1024,7 @@ static int vduse_dev_reg_umem(struct vduse_dev *dev, ...@@ -1019,7 +1024,7 @@ static int vduse_dev_reg_umem(struct vduse_dev *dev,
unsigned long npages, lock_limit; unsigned long npages, lock_limit;
int ret; int ret;
if (!dev->domain->bounce_map || if (!dev->domain || !dev->domain->bounce_map ||
size != dev->domain->bounce_size || size != dev->domain->bounce_size ||
iova != 0 || uaddr & ~PAGE_MASK) iova != 0 || uaddr & ~PAGE_MASK)
return -EINVAL; return -EINVAL;
...@@ -1109,7 +1114,6 @@ static long vduse_dev_ioctl(struct file *file, unsigned int cmd, ...@@ -1109,7 +1114,6 @@ static long vduse_dev_ioctl(struct file *file, unsigned int cmd,
struct vduse_iotlb_entry entry; struct vduse_iotlb_entry entry;
struct vhost_iotlb_map *map; struct vhost_iotlb_map *map;
struct vdpa_map_file *map_file; struct vdpa_map_file *map_file;
struct vduse_iova_domain *domain = dev->domain;
struct file *f = NULL; struct file *f = NULL;
ret = -EFAULT; ret = -EFAULT;
...@@ -1120,8 +1124,13 @@ static long vduse_dev_ioctl(struct file *file, unsigned int cmd, ...@@ -1120,8 +1124,13 @@ static long vduse_dev_ioctl(struct file *file, unsigned int cmd,
if (entry.start > entry.last) if (entry.start > entry.last)
break; break;
spin_lock(&domain->iotlb_lock); mutex_lock(&dev->domain_lock);
map = vhost_iotlb_itree_first(domain->iotlb, if (!dev->domain) {
mutex_unlock(&dev->domain_lock);
break;
}
spin_lock(&dev->domain->iotlb_lock);
map = vhost_iotlb_itree_first(dev->domain->iotlb,
entry.start, entry.last); entry.start, entry.last);
if (map) { if (map) {
map_file = (struct vdpa_map_file *)map->opaque; map_file = (struct vdpa_map_file *)map->opaque;
...@@ -1131,7 +1140,8 @@ static long vduse_dev_ioctl(struct file *file, unsigned int cmd, ...@@ -1131,7 +1140,8 @@ static long vduse_dev_ioctl(struct file *file, unsigned int cmd,
entry.last = map->last; entry.last = map->last;
entry.perm = map->perm; entry.perm = map->perm;
} }
spin_unlock(&domain->iotlb_lock); spin_unlock(&dev->domain->iotlb_lock);
mutex_unlock(&dev->domain_lock);
ret = -EINVAL; ret = -EINVAL;
if (!f) if (!f)
break; break;
...@@ -1284,8 +1294,10 @@ static long vduse_dev_ioctl(struct file *file, unsigned int cmd, ...@@ -1284,8 +1294,10 @@ static long vduse_dev_ioctl(struct file *file, unsigned int cmd,
sizeof(umem.reserved))) sizeof(umem.reserved)))
break; break;
mutex_lock(&dev->domain_lock);
ret = vduse_dev_reg_umem(dev, umem.iova, ret = vduse_dev_reg_umem(dev, umem.iova,
umem.uaddr, umem.size); umem.uaddr, umem.size);
mutex_unlock(&dev->domain_lock);
break; break;
} }
case VDUSE_IOTLB_DEREG_UMEM: { case VDUSE_IOTLB_DEREG_UMEM: {
...@@ -1299,15 +1311,15 @@ static long vduse_dev_ioctl(struct file *file, unsigned int cmd, ...@@ -1299,15 +1311,15 @@ static long vduse_dev_ioctl(struct file *file, unsigned int cmd,
if (!is_mem_zero((const char *)umem.reserved, if (!is_mem_zero((const char *)umem.reserved,
sizeof(umem.reserved))) sizeof(umem.reserved)))
break; break;
mutex_lock(&dev->domain_lock);
ret = vduse_dev_dereg_umem(dev, umem.iova, ret = vduse_dev_dereg_umem(dev, umem.iova,
umem.size); umem.size);
mutex_unlock(&dev->domain_lock);
break; break;
} }
case VDUSE_IOTLB_GET_INFO: { case VDUSE_IOTLB_GET_INFO: {
struct vduse_iova_info info; struct vduse_iova_info info;
struct vhost_iotlb_map *map; struct vhost_iotlb_map *map;
struct vduse_iova_domain *domain = dev->domain;
ret = -EFAULT; ret = -EFAULT;
if (copy_from_user(&info, argp, sizeof(info))) if (copy_from_user(&info, argp, sizeof(info)))
...@@ -1321,18 +1333,24 @@ static long vduse_dev_ioctl(struct file *file, unsigned int cmd, ...@@ -1321,18 +1333,24 @@ static long vduse_dev_ioctl(struct file *file, unsigned int cmd,
sizeof(info.reserved))) sizeof(info.reserved)))
break; break;
spin_lock(&domain->iotlb_lock); mutex_lock(&dev->domain_lock);
map = vhost_iotlb_itree_first(domain->iotlb, if (!dev->domain) {
mutex_unlock(&dev->domain_lock);
break;
}
spin_lock(&dev->domain->iotlb_lock);
map = vhost_iotlb_itree_first(dev->domain->iotlb,
info.start, info.last); info.start, info.last);
if (map) { if (map) {
info.start = map->start; info.start = map->start;
info.last = map->last; info.last = map->last;
info.capability = 0; info.capability = 0;
if (domain->bounce_map && map->start == 0 && if (dev->domain->bounce_map && map->start == 0 &&
map->last == domain->bounce_size - 1) map->last == dev->domain->bounce_size - 1)
info.capability |= VDUSE_IOVA_CAP_UMEM; info.capability |= VDUSE_IOVA_CAP_UMEM;
} }
spin_unlock(&domain->iotlb_lock); spin_unlock(&dev->domain->iotlb_lock);
mutex_unlock(&dev->domain_lock);
if (!map) if (!map)
break; break;
...@@ -1355,7 +1373,10 @@ static int vduse_dev_release(struct inode *inode, struct file *file) ...@@ -1355,7 +1373,10 @@ static int vduse_dev_release(struct inode *inode, struct file *file)
{ {
struct vduse_dev *dev = file->private_data; struct vduse_dev *dev = file->private_data;
vduse_dev_dereg_umem(dev, 0, dev->domain->bounce_size); mutex_lock(&dev->domain_lock);
if (dev->domain)
vduse_dev_dereg_umem(dev, 0, dev->domain->bounce_size);
mutex_unlock(&dev->domain_lock);
spin_lock(&dev->msg_lock); spin_lock(&dev->msg_lock);
/* Make sure the inflight messages can processed after reconncection */ /* Make sure the inflight messages can processed after reconncection */
list_splice_init(&dev->recv_list, &dev->send_list); list_splice_init(&dev->recv_list, &dev->send_list);
...@@ -1564,6 +1585,7 @@ static struct vduse_dev *vduse_dev_create(void) ...@@ -1564,6 +1585,7 @@ static struct vduse_dev *vduse_dev_create(void)
mutex_init(&dev->lock); mutex_init(&dev->lock);
mutex_init(&dev->mem_lock); mutex_init(&dev->mem_lock);
mutex_init(&dev->domain_lock);
spin_lock_init(&dev->msg_lock); spin_lock_init(&dev->msg_lock);
INIT_LIST_HEAD(&dev->send_list); INIT_LIST_HEAD(&dev->send_list);
INIT_LIST_HEAD(&dev->recv_list); INIT_LIST_HEAD(&dev->recv_list);
...@@ -1613,7 +1635,8 @@ static int vduse_destroy_dev(char *name) ...@@ -1613,7 +1635,8 @@ static int vduse_destroy_dev(char *name)
idr_remove(&vduse_idr, dev->minor); idr_remove(&vduse_idr, dev->minor);
kvfree(dev->config); kvfree(dev->config);
vduse_dev_deinit_vqs(dev); vduse_dev_deinit_vqs(dev);
vduse_domain_destroy(dev->domain); if (dev->domain)
vduse_domain_destroy(dev->domain);
kfree(dev->name); kfree(dev->name);
vduse_dev_destroy(dev); vduse_dev_destroy(dev);
module_put(THIS_MODULE); module_put(THIS_MODULE);
...@@ -1722,11 +1745,7 @@ static int vduse_create_dev(struct vduse_dev_config *config, ...@@ -1722,11 +1745,7 @@ static int vduse_create_dev(struct vduse_dev_config *config,
if (!dev->name) if (!dev->name)
goto err_str; goto err_str;
dev->domain = vduse_domain_create(VDUSE_IOVA_SIZE - 1, dev->bounce_size = VDUSE_BOUNCE_SIZE;
VDUSE_BOUNCE_SIZE);
if (!dev->domain)
goto err_domain;
dev->config = config_buf; dev->config = config_buf;
dev->config_size = config->config_size; dev->config_size = config->config_size;
...@@ -1756,8 +1775,6 @@ static int vduse_create_dev(struct vduse_dev_config *config, ...@@ -1756,8 +1775,6 @@ static int vduse_create_dev(struct vduse_dev_config *config,
err_dev: err_dev:
idr_remove(&vduse_idr, dev->minor); idr_remove(&vduse_idr, dev->minor);
err_idr: err_idr:
vduse_domain_destroy(dev->domain);
err_domain:
kfree(dev->name); kfree(dev->name);
err_str: err_str:
vduse_dev_destroy(dev); vduse_dev_destroy(dev);
...@@ -1924,9 +1941,23 @@ static int vdpa_dev_add(struct vdpa_mgmt_dev *mdev, const char *name, ...@@ -1924,9 +1941,23 @@ static int vdpa_dev_add(struct vdpa_mgmt_dev *mdev, const char *name,
if (ret) if (ret)
return ret; return ret;
mutex_lock(&dev->domain_lock);
if (!dev->domain)
dev->domain = vduse_domain_create(VDUSE_IOVA_SIZE - 1,
dev->bounce_size);
mutex_unlock(&dev->domain_lock);
if (!dev->domain) {
put_device(&dev->vdev->vdpa.dev);
return -ENOMEM;
}
ret = _vdpa_register_device(&dev->vdev->vdpa, dev->vq_num); ret = _vdpa_register_device(&dev->vdev->vdpa, dev->vq_num);
if (ret) { if (ret) {
put_device(&dev->vdev->vdpa.dev); put_device(&dev->vdev->vdpa.dev);
mutex_lock(&dev->domain_lock);
vduse_domain_destroy(dev->domain);
dev->domain = NULL;
mutex_unlock(&dev->domain_lock);
return ret; return ret;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment