Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

virtio: add context flag to find vqs

Allows maintaining extra context per vq. For ease of use, passing in
NULL is legal and disables the feature for all vqs.

Includes fixes by Christian for s390, acked by Cornelia.

Signed-off-by: Christian Borntraeger <borntraeger@de.ibm.com>
Acked-by: Cornelia Huck <cornelia.huck@de.ibm.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>

+74 -33
+6 -3
drivers/misc/mic/vop/vop_main.c
··· 278 278 static struct virtqueue *vop_find_vq(struct virtio_device *dev, 279 279 unsigned index, 280 280 void (*callback)(struct virtqueue *vq), 281 - const char *name) 281 + const char *name, bool ctx) 282 282 { 283 283 struct _vop_vdev *vdev = to_vopvdev(dev); 284 284 struct vop_device *vpdev = vdev->vpdev; ··· 314 314 le16_to_cpu(config.num), MIC_VIRTIO_RING_ALIGN, 315 315 dev, 316 316 false, 317 + ctx, 317 318 (void __force *)va, vop_notify, callback, name); 318 319 if (!vq) { 319 320 err = -ENOMEM; ··· 375 374 static int vop_find_vqs(struct virtio_device *dev, unsigned nvqs, 376 375 struct virtqueue *vqs[], 377 376 vq_callback_t *callbacks[], 378 - const char * const names[], struct irq_affinity *desc) 377 + const char * const names[], const bool *ctx, 378 + struct irq_affinity *desc) 379 379 { 380 380 struct _vop_vdev *vdev = to_vopvdev(dev); 381 381 struct vop_device *vpdev = vdev->vpdev; ··· 390 388 for (i = 0; i < nvqs; ++i) { 391 389 dev_dbg(_vop_dev(vdev), "%s: %d: %s\n", 392 390 __func__, i, names[i]); 393 - vqs[i] = vop_find_vq(dev, i, callbacks[i], names[i]); 391 + vqs[i] = vop_find_vq(dev, i, callbacks[i], names[i], 392 + ctx ? ctx[i] : false); 394 393 if (IS_ERR(vqs[i])) { 395 394 err = PTR_ERR(vqs[i]); 396 395 goto error;
+6 -4
drivers/remoteproc/remoteproc_virtio.c
··· 71 71 static struct virtqueue *rp_find_vq(struct virtio_device *vdev, 72 72 unsigned int id, 73 73 void (*callback)(struct virtqueue *vq), 74 - const char *name) 74 + const char *name, bool ctx) 75 75 { 76 76 struct rproc_vdev *rvdev = vdev_to_rvdev(vdev); 77 77 struct rproc *rproc = vdev_to_rproc(vdev); ··· 103 103 * Create the new vq, and tell virtio we're not interested in 104 104 * the 'weak' smp barriers, since we're talking with a real device. 105 105 */ 106 - vq = vring_new_virtqueue(id, len, rvring->align, vdev, false, addr, 107 - rproc_virtio_notify, callback, name); 106 + vq = vring_new_virtqueue(id, len, rvring->align, vdev, false, ctx, 107 + addr, rproc_virtio_notify, callback, name); 108 108 if (!vq) { 109 109 dev_err(dev, "vring_new_virtqueue %s failed\n", name); 110 110 rproc_free_vring(rvring); ··· 138 138 struct virtqueue *vqs[], 139 139 vq_callback_t *callbacks[], 140 140 const char * const names[], 141 + const bool * ctx, 141 142 struct irq_affinity *desc) 142 143 { 143 144 int i, ret; 144 145 145 146 for (i = 0; i < nvqs; ++i) { 146 - vqs[i] = rp_find_vq(vdev, i, callbacks[i], names[i]); 147 + vqs[i] = rp_find_vq(vdev, i, callbacks[i], names[i], 148 + ctx ? ctx[i] : false); 147 149 if (IS_ERR(vqs[i])) { 148 150 ret = PTR_ERR(vqs[i]); 149 151 goto error;
+5 -3
drivers/s390/virtio/kvm_virtio.c
··· 189 189 static struct virtqueue *kvm_find_vq(struct virtio_device *vdev, 190 190 unsigned index, 191 191 void (*callback)(struct virtqueue *vq), 192 - const char *name) 192 + const char *name, bool ctx) 193 193 { 194 194 struct kvm_device *kdev = to_kvmdev(vdev); 195 195 struct kvm_vqconfig *config; ··· 211 211 goto out; 212 212 213 213 vq = vring_new_virtqueue(index, config->num, KVM_S390_VIRTIO_RING_ALIGN, 214 - vdev, true, (void *) config->address, 214 + vdev, true, ctx, (void *) config->address, 215 215 kvm_notify, callback, name); 216 216 if (!vq) { 217 217 err = -ENOMEM; ··· 256 256 struct virtqueue *vqs[], 257 257 vq_callback_t *callbacks[], 258 258 const char * const names[], 259 + const bool *ctx, 259 260 struct irq_affinity *desc) 260 261 { 261 262 struct kvm_device *kdev = to_kvmdev(vdev); ··· 267 266 return -ENOENT; 268 267 269 268 for (i = 0; i < nvqs; ++i) { 270 - vqs[i] = kvm_find_vq(vdev, i, callbacks[i], names[i]); 269 + vqs[i] = kvm_find_vq(vdev, i, callbacks[i], names[i], 270 + ctx ? ctx[i] : false); 271 271 if (IS_ERR(vqs[i])) 272 272 goto error; 273 273 }
+4 -3
drivers/s390/virtio/virtio_ccw.c
··· 484 484 485 485 static struct virtqueue *virtio_ccw_setup_vq(struct virtio_device *vdev, 486 486 int i, vq_callback_t *callback, 487 - const char *name, 487 + const char *name, bool ctx, 488 488 struct ccw1 *ccw) 489 489 { 490 490 struct virtio_ccw_device *vcdev = to_vc_device(vdev); ··· 522 522 } 523 523 524 524 vq = vring_new_virtqueue(i, info->num, KVM_VIRTIO_CCW_RING_ALIGN, vdev, 525 - true, info->queue, virtio_ccw_kvm_notify, 525 + true, ctx, info->queue, virtio_ccw_kvm_notify, 526 526 callback, name); 527 527 if (!vq) { 528 528 /* For now, we fail if we can't get the requested size. */ ··· 629 629 struct virtqueue *vqs[], 630 630 vq_callback_t *callbacks[], 631 631 const char * const names[], 632 + const bool *ctx, 632 633 struct irq_affinity *desc) 633 634 { 634 635 struct virtio_ccw_device *vcdev = to_vc_device(vdev); ··· 643 642 644 643 for (i = 0; i < nvqs; ++i) { 645 644 vqs[i] = virtio_ccw_setup_vq(vdev, i, callbacks[i], names[i], 646 - ccw); 645 + ctx ? ctx[i] : false, ccw); 647 646 if (IS_ERR(vqs[i])) { 648 647 ret = PTR_ERR(vqs[i]); 649 648 vqs[i] = NULL;
+5 -3
drivers/virtio/virtio_mmio.c
··· 351 351 352 352 static struct virtqueue *vm_setup_vq(struct virtio_device *vdev, unsigned index, 353 353 void (*callback)(struct virtqueue *vq), 354 - const char *name) 354 + const char *name, bool ctx) 355 355 { 356 356 struct virtio_mmio_device *vm_dev = to_virtio_mmio_device(vdev); 357 357 struct virtio_mmio_vq_info *info; ··· 388 388 389 389 /* Create the vring */ 390 390 vq = vring_create_virtqueue(index, num, VIRTIO_MMIO_VRING_ALIGN, vdev, 391 - true, true, vm_notify, callback, name); 391 + true, true, ctx, vm_notify, callback, name); 392 392 if (!vq) { 393 393 err = -ENOMEM; 394 394 goto error_new_virtqueue; ··· 447 447 struct virtqueue *vqs[], 448 448 vq_callback_t *callbacks[], 449 449 const char * const names[], 450 + const bool *ctx, 450 451 struct irq_affinity *desc) 451 452 { 452 453 struct virtio_mmio_device *vm_dev = to_virtio_mmio_device(vdev); ··· 460 459 return err; 461 460 462 461 for (i = 0; i < nvqs; ++i) { 463 - vqs[i] = vm_setup_vq(vdev, i, callbacks[i], names[i]); 462 + vqs[i] = vm_setup_vq(vdev, i, callbacks[i], names[i], 463 + ctx ? ctx[i] : false); 464 464 if (IS_ERR(vqs[i])) { 465 465 vm_del_vqs(vdev); 466 466 return PTR_ERR(vqs[i]);
+11 -6
drivers/virtio/virtio_pci_common.c
··· 172 172 static struct virtqueue *vp_setup_vq(struct virtio_device *vdev, unsigned index, 173 173 void (*callback)(struct virtqueue *vq), 174 174 const char *name, 175 + bool ctx, 175 176 u16 msix_vec) 176 177 { 177 178 struct virtio_pci_device *vp_dev = to_vp_device(vdev); ··· 184 183 if (!info) 185 184 return ERR_PTR(-ENOMEM); 186 185 187 - vq = vp_dev->setup_vq(vp_dev, info, index, callback, name, 186 + vq = vp_dev->setup_vq(vp_dev, info, index, callback, name, ctx, 188 187 msix_vec); 189 188 if (IS_ERR(vq)) 190 189 goto out_info; ··· 275 274 static int vp_find_vqs_msix(struct virtio_device *vdev, unsigned nvqs, 276 275 struct virtqueue *vqs[], vq_callback_t *callbacks[], 277 276 const char * const names[], bool per_vq_vectors, 277 + const bool *ctx, 278 278 struct irq_affinity *desc) 279 279 { 280 280 struct virtio_pci_device *vp_dev = to_vp_device(vdev); ··· 317 315 else 318 316 msix_vec = VP_MSIX_VQ_VECTOR; 319 317 vqs[i] = vp_setup_vq(vdev, i, callbacks[i], names[i], 318 + ctx ? ctx[i] : false, 320 319 msix_vec); 321 320 if (IS_ERR(vqs[i])) { 322 321 err = PTR_ERR(vqs[i]); ··· 348 345 349 346 static int vp_find_vqs_intx(struct virtio_device *vdev, unsigned nvqs, 350 347 struct virtqueue *vqs[], vq_callback_t *callbacks[], 351 - const char * const names[]) 348 + const char * const names[], const bool *ctx) 352 349 { 353 350 struct virtio_pci_device *vp_dev = to_vp_device(vdev); 354 351 int i, err; ··· 370 367 continue; 371 368 } 372 369 vqs[i] = vp_setup_vq(vdev, i, callbacks[i], names[i], 370 + ctx ? ctx[i] : false, 373 371 VIRTIO_MSI_NO_VECTOR); 374 372 if (IS_ERR(vqs[i])) { 375 373 err = PTR_ERR(vqs[i]); ··· 387 383 /* the config->find_vqs() implementation */ 388 384 int vp_find_vqs(struct virtio_device *vdev, unsigned nvqs, 389 385 struct virtqueue *vqs[], vq_callback_t *callbacks[], 390 - const char * const names[], struct irq_affinity *desc) 386 + const char * const names[], const bool *ctx, 387 + struct irq_affinity *desc) 391 388 { 392 389 int err; 393 390 394 391 /* Try MSI-X with one vector per queue. */ 395 - err = vp_find_vqs_msix(vdev, nvqs, vqs, callbacks, names, true, desc); 392 + err = vp_find_vqs_msix(vdev, nvqs, vqs, callbacks, names, true, ctx, desc); 396 393 if (!err) 397 394 return 0; 398 395 /* Fallback: MSI-X with one vector for config, one shared for queues. */ 399 - err = vp_find_vqs_msix(vdev, nvqs, vqs, callbacks, names, false, desc); 396 + err = vp_find_vqs_msix(vdev, nvqs, vqs, callbacks, names, false, ctx, desc); 400 397 if (!err) 401 398 return 0; 402 399 /* Finally fall back to regular interrupts. */ 403 - return vp_find_vqs_intx(vdev, nvqs, vqs, callbacks, names); 400 + return vp_find_vqs_intx(vdev, nvqs, vqs, callbacks, names, ctx); 404 401 } 405 402 406 403 const char *vp_bus_name(struct virtio_device *vdev)
+3 -1
drivers/virtio/virtio_pci_common.h
··· 102 102 unsigned idx, 103 103 void (*callback)(struct virtqueue *vq), 104 104 const char *name, 105 + bool ctx, 105 106 u16 msix_vec); 106 107 void (*del_vq)(struct virtio_pci_vq_info *info); 107 108 ··· 132 131 /* the config->find_vqs() implementation */ 133 132 int vp_find_vqs(struct virtio_device *vdev, unsigned nvqs, 134 133 struct virtqueue *vqs[], vq_callback_t *callbacks[], 135 - const char * const names[], struct irq_affinity *desc); 134 + const char * const names[], const bool *ctx, 135 + struct irq_affinity *desc); 136 136 const char *vp_bus_name(struct virtio_device *vdev); 137 137 138 138 /* Setup the affinity for a virtqueue:
+3 -1
drivers/virtio/virtio_pci_legacy.c
··· 116 116 unsigned index, 117 117 void (*callback)(struct virtqueue *vq), 118 118 const char *name, 119 + bool ctx, 119 120 u16 msix_vec) 120 121 { 121 122 struct virtqueue *vq; ··· 136 135 /* create the vring */ 137 136 vq = vring_create_virtqueue(index, num, 138 137 VIRTIO_PCI_VRING_ALIGN, &vp_dev->vdev, 139 - true, false, vp_notify, callback, name); 138 + true, false, ctx, 139 + vp_notify, callback, name); 140 140 if (!vq) 141 141 return ERR_PTR(-ENOMEM); 142 142
+8 -4
drivers/virtio/virtio_pci_modern.c
··· 297 297 unsigned index, 298 298 void (*callback)(struct virtqueue *vq), 299 299 const char *name, 300 + bool ctx, 300 301 u16 msix_vec) 301 302 { 302 303 struct virtio_pci_common_cfg __iomem *cfg = vp_dev->common; ··· 329 328 /* create the vring */ 330 329 vq = vring_create_virtqueue(index, num, 331 330 SMP_CACHE_BYTES, &vp_dev->vdev, 332 - true, true, vp_notify, callback, name); 331 + true, true, ctx, 332 + vp_notify, callback, name); 333 333 if (!vq) 334 334 return ERR_PTR(-ENOMEM); 335 335 ··· 389 387 } 390 388 391 389 static int vp_modern_find_vqs(struct virtio_device *vdev, unsigned nvqs, 392 - struct virtqueue *vqs[], vq_callback_t *callbacks[], 393 - const char * const names[], struct irq_affinity *desc) 390 + struct virtqueue *vqs[], 391 + vq_callback_t *callbacks[], 392 + const char * const names[], const bool *ctx, 393 + struct irq_affinity *desc) 394 394 { 395 395 struct virtio_pci_device *vp_dev = to_vp_device(vdev); 396 396 struct virtqueue *vq; 397 - int rc = vp_find_vqs(vdev, nvqs, vqs, callbacks, names, desc); 397 + int rc = vp_find_vqs(vdev, nvqs, vqs, callbacks, names, ctx, desc); 398 398 399 399 if (rc) 400 400 return rc;
+5 -2
drivers/virtio/virtio_ring.c
··· 916 916 struct vring vring, 917 917 struct virtio_device *vdev, 918 918 bool weak_barriers, 919 + bool context, 919 920 bool (*notify)(struct virtqueue *), 920 921 void (*callback)(struct virtqueue *), 921 922 const char *name) ··· 1020 1019 struct virtio_device *vdev, 1021 1020 bool weak_barriers, 1022 1021 bool may_reduce_num, 1022 + bool context, 1023 1023 bool (*notify)(struct virtqueue *), 1024 1024 void (*callback)(struct virtqueue *), 1025 1025 const char *name) ··· 1060 1058 queue_size_in_bytes = vring_size(num, vring_align); 1061 1059 vring_init(&vring, num, queue, vring_align); 1062 1060 1063 - vq = __vring_new_virtqueue(index, vring, vdev, weak_barriers, 1061 + vq = __vring_new_virtqueue(index, vring, vdev, weak_barriers, context, 1064 1062 notify, callback, name); 1065 1063 if (!vq) { 1066 1064 vring_free_queue(vdev, queue_size_in_bytes, queue, ··· 1081 1079 unsigned int vring_align, 1082 1080 struct virtio_device *vdev, 1083 1081 bool weak_barriers, 1082 + bool context, 1084 1083 void *pages, 1085 1084 bool (*notify)(struct virtqueue *vq), 1086 1085 void (*callback)(struct virtqueue *vq), ··· 1089 1086 { 1090 1087 struct vring vring; 1091 1088 vring_init(&vring, num, pages, vring_align); 1092 - return __vring_new_virtqueue(index, vring, vdev, weak_barriers, 1089 + return __vring_new_virtqueue(index, vring, vdev, weak_barriers, context, 1093 1090 notify, callback, name); 1094 1091 } 1095 1092 EXPORT_SYMBOL_GPL(vring_new_virtqueue);
+15 -3
include/linux/virtio_config.h
··· 72 72 void (*reset)(struct virtio_device *vdev); 73 73 int (*find_vqs)(struct virtio_device *, unsigned nvqs, 74 74 struct virtqueue *vqs[], vq_callback_t *callbacks[], 75 - const char * const names[], struct irq_affinity *desc); 75 + const char * const names[], const bool *ctx, 76 + struct irq_affinity *desc); 76 77 void (*del_vqs)(struct virtio_device *); 77 78 u64 (*get_features)(struct virtio_device *vdev); 78 79 int (*finalize_features)(struct virtio_device *vdev); ··· 174 173 vq_callback_t *callbacks[] = { c }; 175 174 const char *names[] = { n }; 176 175 struct virtqueue *vq; 177 - int err = vdev->config->find_vqs(vdev, 1, &vq, callbacks, names, NULL); 176 + int err = vdev->config->find_vqs(vdev, 1, &vq, callbacks, names, NULL, 177 + NULL); 178 178 if (err < 0) 179 179 return ERR_PTR(err); 180 180 return vq; ··· 187 185 const char * const names[], 188 186 struct irq_affinity *desc) 189 187 { 190 - return vdev->config->find_vqs(vdev, nvqs, vqs, callbacks, names, desc); 188 + return vdev->config->find_vqs(vdev, nvqs, vqs, callbacks, names, NULL, desc); 189 + } 190 + 191 + static inline 192 + int virtio_find_vqs_ctx(struct virtio_device *vdev, unsigned nvqs, 193 + struct virtqueue *vqs[], vq_callback_t *callbacks[], 194 + const char * const names[], const bool *ctx, 195 + struct irq_affinity *desc) 196 + { 197 + return vdev->config->find_vqs(vdev, nvqs, vqs, callbacks, names, ctx, 198 + desc); 191 199 } 192 200 193 201 /**
+3
include/linux/virtio_ring.h
··· 71 71 struct virtio_device *vdev, 72 72 bool weak_barriers, 73 73 bool may_reduce_num, 74 + bool ctx, 74 75 bool (*notify)(struct virtqueue *vq), 75 76 void (*callback)(struct virtqueue *vq), 76 77 const char *name); ··· 81 80 struct vring vring, 82 81 struct virtio_device *vdev, 83 82 bool weak_barriers, 83 + bool ctx, 84 84 bool (*notify)(struct virtqueue *), 85 85 void (*callback)(struct virtqueue *), 86 86 const char *name); ··· 95 93 unsigned int vring_align, 96 94 struct virtio_device *vdev, 97 95 bool weak_barriers, 96 + bool ctx, 98 97 void *pages, 99 98 bool (*notify)(struct virtqueue *vq), 100 99 void (*callback)(struct virtqueue *vq),