diff options
Diffstat (limited to 'drivers/vhost/net.c')
-rw-r--r-- | drivers/vhost/net.c | 67 |
1 files changed, 57 insertions, 10 deletions
diff --git a/drivers/vhost/net.c b/drivers/vhost/net.c index e032ca397371..5dc128a8da83 100644 --- a/drivers/vhost/net.c +++ b/drivers/vhost/net.c | |||
@@ -61,7 +61,8 @@ MODULE_PARM_DESC(experimental_zcopytx, "Enable Zero Copy TX;" | |||
61 | enum { | 61 | enum { |
62 | VHOST_NET_FEATURES = VHOST_FEATURES | | 62 | VHOST_NET_FEATURES = VHOST_FEATURES | |
63 | (1ULL << VHOST_NET_F_VIRTIO_NET_HDR) | | 63 | (1ULL << VHOST_NET_F_VIRTIO_NET_HDR) | |
64 | (1ULL << VIRTIO_NET_F_MRG_RXBUF) | 64 | (1ULL << VIRTIO_NET_F_MRG_RXBUF) | |
65 | (1ULL << VIRTIO_F_IOMMU_PLATFORM) | ||
65 | }; | 66 | }; |
66 | 67 | ||
67 | enum { | 68 | enum { |
@@ -334,7 +335,7 @@ static int vhost_net_tx_get_vq_desc(struct vhost_net *net, | |||
334 | { | 335 | { |
335 | unsigned long uninitialized_var(endtime); | 336 | unsigned long uninitialized_var(endtime); |
336 | int r = vhost_get_vq_desc(vq, vq->iov, ARRAY_SIZE(vq->iov), | 337 | int r = vhost_get_vq_desc(vq, vq->iov, ARRAY_SIZE(vq->iov), |
337 | out_num, in_num, NULL, NULL); | 338 | out_num, in_num, NULL, NULL); |
338 | 339 | ||
339 | if (r == vq->num && vq->busyloop_timeout) { | 340 | if (r == vq->num && vq->busyloop_timeout) { |
340 | preempt_disable(); | 341 | preempt_disable(); |
@@ -344,7 +345,7 @@ static int vhost_net_tx_get_vq_desc(struct vhost_net *net, | |||
344 | cpu_relax_lowlatency(); | 345 | cpu_relax_lowlatency(); |
345 | preempt_enable(); | 346 | preempt_enable(); |
346 | r = vhost_get_vq_desc(vq, vq->iov, ARRAY_SIZE(vq->iov), | 347 | r = vhost_get_vq_desc(vq, vq->iov, ARRAY_SIZE(vq->iov), |
347 | out_num, in_num, NULL, NULL); | 348 | out_num, in_num, NULL, NULL); |
348 | } | 349 | } |
349 | 350 | ||
350 | return r; | 351 | return r; |
@@ -377,6 +378,9 @@ static void handle_tx(struct vhost_net *net) | |||
377 | if (!sock) | 378 | if (!sock) |
378 | goto out; | 379 | goto out; |
379 | 380 | ||
381 | if (!vq_iotlb_prefetch(vq)) | ||
382 | goto out; | ||
383 | |||
380 | vhost_disable_notify(&net->dev, vq); | 384 | vhost_disable_notify(&net->dev, vq); |
381 | 385 | ||
382 | hdr_size = nvq->vhost_hlen; | 386 | hdr_size = nvq->vhost_hlen; |
@@ -652,6 +656,10 @@ static void handle_rx(struct vhost_net *net) | |||
652 | sock = vq->private_data; | 656 | sock = vq->private_data; |
653 | if (!sock) | 657 | if (!sock) |
654 | goto out; | 658 | goto out; |
659 | |||
660 | if (!vq_iotlb_prefetch(vq)) | ||
661 | goto out; | ||
662 | |||
655 | vhost_disable_notify(&net->dev, vq); | 663 | vhost_disable_notify(&net->dev, vq); |
656 | vhost_net_disable_vq(net, vq); | 664 | vhost_net_disable_vq(net, vq); |
657 | 665 | ||
@@ -1052,20 +1060,20 @@ static long vhost_net_reset_owner(struct vhost_net *n) | |||
1052 | struct socket *tx_sock = NULL; | 1060 | struct socket *tx_sock = NULL; |
1053 | struct socket *rx_sock = NULL; | 1061 | struct socket *rx_sock = NULL; |
1054 | long err; | 1062 | long err; |
1055 | struct vhost_memory *memory; | 1063 | struct vhost_umem *umem; |
1056 | 1064 | ||
1057 | mutex_lock(&n->dev.mutex); | 1065 | mutex_lock(&n->dev.mutex); |
1058 | err = vhost_dev_check_owner(&n->dev); | 1066 | err = vhost_dev_check_owner(&n->dev); |
1059 | if (err) | 1067 | if (err) |
1060 | goto done; | 1068 | goto done; |
1061 | memory = vhost_dev_reset_owner_prepare(); | 1069 | umem = vhost_dev_reset_owner_prepare(); |
1062 | if (!memory) { | 1070 | if (!umem) { |
1063 | err = -ENOMEM; | 1071 | err = -ENOMEM; |
1064 | goto done; | 1072 | goto done; |
1065 | } | 1073 | } |
1066 | vhost_net_stop(n, &tx_sock, &rx_sock); | 1074 | vhost_net_stop(n, &tx_sock, &rx_sock); |
1067 | vhost_net_flush(n); | 1075 | vhost_net_flush(n); |
1068 | vhost_dev_reset_owner(&n->dev, memory); | 1076 | vhost_dev_reset_owner(&n->dev, umem); |
1069 | vhost_net_vq_reset(n); | 1077 | vhost_net_vq_reset(n); |
1070 | done: | 1078 | done: |
1071 | mutex_unlock(&n->dev.mutex); | 1079 | mutex_unlock(&n->dev.mutex); |
@@ -1096,10 +1104,14 @@ static int vhost_net_set_features(struct vhost_net *n, u64 features) | |||
1096 | } | 1104 | } |
1097 | mutex_lock(&n->dev.mutex); | 1105 | mutex_lock(&n->dev.mutex); |
1098 | if ((features & (1 << VHOST_F_LOG_ALL)) && | 1106 | if ((features & (1 << VHOST_F_LOG_ALL)) && |
1099 | !vhost_log_access_ok(&n->dev)) { | 1107 | !vhost_log_access_ok(&n->dev)) |
1100 | mutex_unlock(&n->dev.mutex); | 1108 | goto out_unlock; |
1101 | return -EFAULT; | 1109 | |
1110 | if ((features & (1ULL << VIRTIO_F_IOMMU_PLATFORM))) { | ||
1111 | if (vhost_init_device_iotlb(&n->dev, true)) | ||
1112 | goto out_unlock; | ||
1102 | } | 1113 | } |
1114 | |||
1103 | for (i = 0; i < VHOST_NET_VQ_MAX; ++i) { | 1115 | for (i = 0; i < VHOST_NET_VQ_MAX; ++i) { |
1104 | mutex_lock(&n->vqs[i].vq.mutex); | 1116 | mutex_lock(&n->vqs[i].vq.mutex); |
1105 | n->vqs[i].vq.acked_features = features; | 1117 | n->vqs[i].vq.acked_features = features; |
@@ -1109,6 +1121,10 @@ static int vhost_net_set_features(struct vhost_net *n, u64 features) | |||
1109 | } | 1121 | } |
1110 | mutex_unlock(&n->dev.mutex); | 1122 | mutex_unlock(&n->dev.mutex); |
1111 | return 0; | 1123 | return 0; |
1124 | |||
1125 | out_unlock: | ||
1126 | mutex_unlock(&n->dev.mutex); | ||
1127 | return -EFAULT; | ||
1112 | } | 1128 | } |
1113 | 1129 | ||
1114 | static long vhost_net_set_owner(struct vhost_net *n) | 1130 | static long vhost_net_set_owner(struct vhost_net *n) |
@@ -1182,9 +1198,40 @@ static long vhost_net_compat_ioctl(struct file *f, unsigned int ioctl, | |||
1182 | } | 1198 | } |
1183 | #endif | 1199 | #endif |
1184 | 1200 | ||
1201 | static ssize_t vhost_net_chr_read_iter(struct kiocb *iocb, struct iov_iter *to) | ||
1202 | { | ||
1203 | struct file *file = iocb->ki_filp; | ||
1204 | struct vhost_net *n = file->private_data; | ||
1205 | struct vhost_dev *dev = &n->dev; | ||
1206 | int noblock = file->f_flags & O_NONBLOCK; | ||
1207 | |||
1208 | return vhost_chr_read_iter(dev, to, noblock); | ||
1209 | } | ||
1210 | |||
1211 | static ssize_t vhost_net_chr_write_iter(struct kiocb *iocb, | ||
1212 | struct iov_iter *from) | ||
1213 | { | ||
1214 | struct file *file = iocb->ki_filp; | ||
1215 | struct vhost_net *n = file->private_data; | ||
1216 | struct vhost_dev *dev = &n->dev; | ||
1217 | |||
1218 | return vhost_chr_write_iter(dev, from); | ||
1219 | } | ||
1220 | |||
1221 | static unsigned int vhost_net_chr_poll(struct file *file, poll_table *wait) | ||
1222 | { | ||
1223 | struct vhost_net *n = file->private_data; | ||
1224 | struct vhost_dev *dev = &n->dev; | ||
1225 | |||
1226 | return vhost_chr_poll(file, dev, wait); | ||
1227 | } | ||
1228 | |||
1185 | static const struct file_operations vhost_net_fops = { | 1229 | static const struct file_operations vhost_net_fops = { |
1186 | .owner = THIS_MODULE, | 1230 | .owner = THIS_MODULE, |
1187 | .release = vhost_net_release, | 1231 | .release = vhost_net_release, |
1232 | .read_iter = vhost_net_chr_read_iter, | ||
1233 | .write_iter = vhost_net_chr_write_iter, | ||
1234 | .poll = vhost_net_chr_poll, | ||
1188 | .unlocked_ioctl = vhost_net_ioctl, | 1235 | .unlocked_ioctl = vhost_net_ioctl, |
1189 | #ifdef CONFIG_COMPAT | 1236 | #ifdef CONFIG_COMPAT |
1190 | .compat_ioctl = vhost_net_compat_ioctl, | 1237 | .compat_ioctl = vhost_net_compat_ioctl, |