Pull virtio updates from Michael Tsirkin: "vhost,virtio,vdpa: features, fixes, cleanups. vdpa/mlx5: - VHOST_BACKEND_F_ENABLE_AFTER_DRIVER_OK - new maintainer vdpa: - support for vq descriptor mappings - decouple reset of iotlb mapping from device reset and fixes, cleanups all over the place" * tag 'for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mst/vhost: (34 commits) vdpa_sim: implement .reset_map support vdpa/mlx5: implement .reset_map driver op vhost-vdpa: clean iotlb map during reset for older userspace vdpa: introduce .compat_reset operation callback vhost-vdpa: introduce IOTLB_PERSIST backend feature bit vhost-vdpa: reset vendor specific mapping to initial state in .release vdpa: introduce .reset_map operation callback virtio_pci: add check for common cfg size virtio-blk: fix implicit overflow on virtio_max_dma_size virtio_pci: add build offset check for the new common cfg items virtio: add definition of VIRTIO_F_NOTIF_CONFIG_DATA feature bit vduse: make vduse_class constant vhost-scsi: Spelling s/preceeding/preceding/g virtio: kdoc for struct virtio_pci_modern_device vdpa: Update sysfs ABI documentation MAINTAINERS: Add myself as mlx5_vdpa driver virtio-balloon: correct the comment of virtballoon_migratepage() mlx5_vdpa: offer VHOST_BACKEND_F_ENABLE_AFTER_DRIVER_OK vdpa/mlx5: Update cvq iotlb mapping on ASID change vdpa/mlx5: Make iotlb helper functions more generic ...
Unified · Split
| @@ -1,4 +1,4 @@ | ||
| 1 | −What: /sys/bus/vdpa/driver_autoprobe | |
| 1 | +What: /sys/bus/vdpa/drivers_autoprobe | |
| 2 | 2 | Date: March 2020 |
| 3 | 3 | Contact: virtualization@lists.linux-foundation.org |
| 4 | 4 | Description: |
| @@ -17,7 +17,7 @@ Description: · 12 unmodified lines | ||
| 17 | 17 | Writing a device name to this file will cause the kernel binds |
| 18 | 18 | devices to a compatible driver. |
| 19 | 19 | |
| 20 | − This can be useful when /sys/bus/vdpa/driver_autoprobe is | |
| 20 | + This can be useful when /sys/bus/vdpa/drivers_autoprobe is | |
| 21 | 21 | disabled. |
| 22 | 22 | |
| 23 | 23 | What: /sys/bus/vdpa/drivers/.../bind |
| @@ -13790,6 +13790,12 @@ F: drivers/infiniband/hw/mlx5/ · 13789 unmodified lines | ||
| 13790 | 13790 | F: include/linux/mlx5/ |
| 13791 | 13791 | F: include/uapi/rdma/mlx5-abi.h |
| 13792 | 13792 | |
| 13793 | +MELLANOX MLX5 VDPA DRIVER | |
| 13794 | +M: Dragos Tatulea <dtatulea@nvidia.com> | |
| 13795 | +L: virtualization@lists.linux-foundation.org | |
| 13796 | +S: Supported | |
| 13797 | +F: drivers/vdpa/mlx5/ | |
| 13798 | + | |
| 13793 | 13799 | MELLANOX MLXCPLD I2C AND MUX DRIVER |
| 13794 | 13800 | M: Vadim Pasternak <vadimp@nvidia.com> |
| 13795 | 13801 | M: Michael Shych <michaelsh@nvidia.com> |
| @@ -1311,6 +1311,7 @@ static int virtblk_probe(struct virtio_device *vdev) · 1310 unmodified lines | ||
| 1311 | 1311 | u16 min_io_size; |
| 1312 | 1312 | u8 physical_block_exp, alignment_offset; |
| 1313 | 1313 | unsigned int queue_depth; |
| 1314 | + size_t max_dma_size; | |
| 1314 | 1315 | |
| 1315 | 1316 | if (!vdev->config->get) { |
| 1316 | 1317 | dev_err(&vdev->dev, "%s failure: config access disabled\n", |
| @@ -1409,7 +1410,8 @@ static int virtblk_probe(struct virtio_device *vdev) · 92 unmodified lines | ||
| 1409 | 1410 | /* No real sector limit. */ |
| 1410 | 1411 | blk_queue_max_hw_sectors(q, UINT_MAX); |
| 1411 | 1412 | |
| 1412 | − max_size = virtio_max_dma_size(vdev); | |
| 1413 | + max_dma_size = virtio_max_dma_size(vdev); | |
| 1414 | + max_size = max_dma_size > U32_MAX ? U32_MAX : max_dma_size; | |
| 1413 | 1415 | |
| 1414 | 1416 | /* Host can optionally specify maximum segment size and number of |
| 1415 | 1417 | * segments. */ |
| @@ -31,11 +31,9 @@ struct mlx5_vdpa_mr { · 30 unmodified lines | ||
| 31 | 31 | struct list_head head; |
| 32 | 32 | unsigned long num_directs; |
| 33 | 33 | unsigned long num_klms; |
| 34 | − /* state of dvq mr */ | |
| 35 | − bool initialized; | |
| 36 | 34 | |
| 37 | − /* serialize mkey creation and destruction */ | |
| 38 | − struct mutex mkey_mtx; | |
| 35 | + struct vhost_iotlb *iotlb; | |
| 36 | + | |
| 39 | 37 | bool user_mr; |
| 40 | 38 | }; |
| 41 | 39 | |
| @@ -74,11 +72,12 @@ struct mlx5_vdpa_wq_ent { · 32 unmodified lines | ||
| 74 | 72 | enum { |
| 75 | 73 | MLX5_VDPA_DATAVQ_GROUP, |
| 76 | 74 | MLX5_VDPA_CVQ_GROUP, |
| 75 | + MLX5_VDPA_DATAVQ_DESC_GROUP, | |
| 77 | 76 | MLX5_VDPA_NUMVQ_GROUPS |
| 78 | 77 | }; |
| 79 | 78 | |
| 80 | 79 | enum { |
| 81 | − MLX5_VDPA_NUM_AS = MLX5_VDPA_NUMVQ_GROUPS | |
| 80 | + MLX5_VDPA_NUM_AS = 2 | |
| 82 | 81 | }; |
| 83 | 82 | |
| 84 | 83 | struct mlx5_vdpa_dev { |
| @@ -93,7 +92,9 @@ struct mlx5_vdpa_dev { · 8 unmodified lines | ||
| 93 | 92 | u16 max_idx; |
| 94 | 93 | u32 generation; |
| 95 | 94 | |
| 96 | − struct mlx5_vdpa_mr mr; | |
| 95 | + struct mlx5_vdpa_mr *mr[MLX5_VDPA_NUM_AS]; | |
| 96 | + /* serialize mr access */ | |
| 97 | + struct mutex mr_mtx; | |
| 97 | 98 | struct mlx5_control_vq cvq; |
| 98 | 99 | struct workqueue_struct *wq; |
| 99 | 100 | unsigned int group2asid[MLX5_VDPA_NUMVQ_GROUPS]; |
| @@ -114,12 +115,19 @@ void mlx5_vdpa_free_resources(struct mlx5_vdpa_dev *mvdev); · 14 unmodified lines | ||
| 114 | 115 | int mlx5_vdpa_create_mkey(struct mlx5_vdpa_dev *mvdev, u32 *mkey, u32 *in, |
| 115 | 116 | int inlen); |
| 116 | 117 | int mlx5_vdpa_destroy_mkey(struct mlx5_vdpa_dev *mvdev, u32 mkey); |
| 117 | −int mlx5_vdpa_handle_set_map(struct mlx5_vdpa_dev *mvdev, struct vhost_iotlb *iotlb, | |
| 118 | − bool *change_map, unsigned int asid); | |
| 119 | −int mlx5_vdpa_create_mr(struct mlx5_vdpa_dev *mvdev, struct vhost_iotlb *iotlb, | |
| 120 | − unsigned int asid); | |
| 121 | −void mlx5_vdpa_destroy_mr(struct mlx5_vdpa_dev *mvdev); | |
| 122 | −void mlx5_vdpa_destroy_mr_asid(struct mlx5_vdpa_dev *mvdev, unsigned int asid); | |
| 118 | +struct mlx5_vdpa_mr *mlx5_vdpa_create_mr(struct mlx5_vdpa_dev *mvdev, | |
| 119 | + struct vhost_iotlb *iotlb); | |
| 120 | +void mlx5_vdpa_destroy_mr_resources(struct mlx5_vdpa_dev *mvdev); | |
| 121 | +void mlx5_vdpa_destroy_mr(struct mlx5_vdpa_dev *mvdev, | |
| 122 | + struct mlx5_vdpa_mr *mr); | |
| 123 | +void mlx5_vdpa_update_mr(struct mlx5_vdpa_dev *mvdev, | |
| 124 | + struct mlx5_vdpa_mr *mr, | |
| 125 | + unsigned int asid); | |
| 126 | +int mlx5_vdpa_update_cvq_iotlb(struct mlx5_vdpa_dev *mvdev, | |
| 127 | + struct vhost_iotlb *iotlb, | |
| 128 | + unsigned int asid); | |
| 129 | +int mlx5_vdpa_create_dma_mr(struct mlx5_vdpa_dev *mvdev); | |
| 130 | +int mlx5_vdpa_reset_mr(struct mlx5_vdpa_dev *mvdev, unsigned int asid); | |
| 123 | 131 | |
| 124 | 132 | #define mlx5_vdpa_warn(__dev, format, ...) \ |
| 125 | 133 | dev_warn((__dev)->mdev->device, "%s:%d:(pid %d) warning: " format, __func__, __LINE__, \ |
| @@ -301,10 +301,13 @@ static void unmap_direct_mr(struct mlx5_vdpa_dev *mvdev, struct mlx5_vdpa_direct · 300 unmodified lines | ||
| 301 | 301 | sg_free_table(&mr->sg_head); |
| 302 | 302 | } |
| 303 | 303 | |
| 304 | −static int add_direct_chain(struct mlx5_vdpa_dev *mvdev, u64 start, u64 size, u8 perm, | |
| 304 | +static int add_direct_chain(struct mlx5_vdpa_dev *mvdev, | |
| 305 | + struct mlx5_vdpa_mr *mr, | |
| 306 | + u64 start, | |
| 307 | + u64 size, | |
| 308 | + u8 perm, | |
| 305 | 309 | struct vhost_iotlb *iotlb) |
| 306 | 310 | { |
| 307 | − struct mlx5_vdpa_mr *mr = &mvdev->mr; | |
| 308 | 311 | struct mlx5_vdpa_direct_mr *dmr; |
| 309 | 312 | struct mlx5_vdpa_direct_mr *n; |
| 310 | 313 | LIST_HEAD(tmp); |
| @@ -354,9 +357,10 @@ err_alloc: · 43 unmodified lines | ||
| 354 | 357 | * indirect memory key that provides access to the enitre address space given |
| 355 | 358 | * by iotlb. |
| 356 | 359 | */ |
| 357 | −static int create_user_mr(struct mlx5_vdpa_dev *mvdev, struct vhost_iotlb *iotlb) | |
| 360 | +static int create_user_mr(struct mlx5_vdpa_dev *mvdev, | |
| 361 | + struct mlx5_vdpa_mr *mr, | |
| 362 | + struct vhost_iotlb *iotlb) | |
| 358 | 363 | { |
| 359 | − struct mlx5_vdpa_mr *mr = &mvdev->mr; | |
| 360 | 364 | struct mlx5_vdpa_direct_mr *dmr; |
| 361 | 365 | struct mlx5_vdpa_direct_mr *n; |
| 362 | 366 | struct vhost_iotlb_map *map; |
| @@ -384,7 +388,7 @@ static int create_user_mr(struct mlx5_vdpa_dev *mvdev, struct vhost_iotlb *iotlb · 21 unmodified lines | ||
| 384 | 388 | LOG_MAX_KLM_SIZE); |
| 385 | 389 | mr->num_klms += nnuls; |
| 386 | 390 | } |
| 387 | − err = add_direct_chain(mvdev, ps, pe - ps, pperm, iotlb); | |
| 391 | + err = add_direct_chain(mvdev, mr, ps, pe - ps, pperm, iotlb); | |
| 388 | 392 | if (err) |
| 389 | 393 | goto err_chain; |
| 390 | 394 | } |
| @@ -393,7 +397,7 @@ static int create_user_mr(struct mlx5_vdpa_dev *mvdev, struct vhost_iotlb *iotlb · 2 unmodified lines | ||
| 393 | 397 | pperm = map->perm; |
| 394 | 398 | } |
| 395 | 399 | } |
| 396 | − err = add_direct_chain(mvdev, ps, pe - ps, pperm, iotlb); | |
| 400 | + err = add_direct_chain(mvdev, mr, ps, pe - ps, pperm, iotlb); | |
| 397 | 401 | if (err) |
| 398 | 402 | goto err_chain; |
| 399 | 403 | |
| @@ -450,20 +454,23 @@ static void destroy_dma_mr(struct mlx5_vdpa_dev *mvdev, struct mlx5_vdpa_mr *mr) · 50 unmodified lines | ||
| 450 | 454 | mlx5_vdpa_destroy_mkey(mvdev, mr->mkey); |
| 451 | 455 | } |
| 452 | 456 | |
| 453 | −static int dup_iotlb(struct mlx5_vdpa_dev *mvdev, struct vhost_iotlb *src) | |
| 457 | +static int dup_iotlb(struct vhost_iotlb *dst, struct vhost_iotlb *src) | |
| 454 | 458 | { |
| 455 | 459 | struct vhost_iotlb_map *map; |
| 456 | 460 | u64 start = 0, last = ULLONG_MAX; |
| 457 | 461 | int err; |
| 458 | 462 | |
| 463 | + if (dst == src) | |
| 464 | + return -EINVAL; | |
| 465 | + | |
| 459 | 466 | if (!src) { |
| 460 | − err = vhost_iotlb_add_range(mvdev->cvq.iotlb, start, last, start, VHOST_ACCESS_RW); | |
| 467 | + err = vhost_iotlb_add_range(dst, start, last, start, VHOST_ACCESS_RW); | |
| 461 | 468 | return err; |
| 462 | 469 | } |
| 463 | 470 | |
| 464 | 471 | for (map = vhost_iotlb_itree_first(src, start, last); map; |
| 465 | 472 | map = vhost_iotlb_itree_next(map, start, last)) { |
| 466 | − err = vhost_iotlb_add_range(mvdev->cvq.iotlb, map->start, map->last, | |
| 473 | + err = vhost_iotlb_add_range(dst, map->start, map->last, | |
| 467 | 474 | map->addr, map->perm); |
| 468 | 475 | if (err) |
| 469 | 476 | return err; |
| @@ -471,9 +478,9 @@ static int dup_iotlb(struct mlx5_vdpa_dev *mvdev, struct vhost_iotlb *src) · 1 unmodified line | ||
| 471 | 478 | return 0; |
| 472 | 479 | } |
| 473 | 480 | |
| 474 | −static void prune_iotlb(struct mlx5_vdpa_dev *mvdev) | |
| 481 | +static void prune_iotlb(struct vhost_iotlb *iotlb) | |
| 475 | 482 | { |
| 476 | − vhost_iotlb_del_range(mvdev->cvq.iotlb, 0, ULLONG_MAX); | |
| 483 | + vhost_iotlb_del_range(iotlb, 0, ULLONG_MAX); | |
| 477 | 484 | } |
| 478 | 485 | |
| 479 | 486 | static void destroy_user_mr(struct mlx5_vdpa_dev *mvdev, struct mlx5_vdpa_mr *mr) |
| @@ -489,133 +496,169 @@ static void destroy_user_mr(struct mlx5_vdpa_dev *mvdev, struct mlx5_vdpa_mr *mr · 9 unmodified lines | ||
| 489 | 496 | } |
| 490 | 497 | } |
| 491 | 498 | |
| 492 | −static void _mlx5_vdpa_destroy_cvq_mr(struct mlx5_vdpa_dev *mvdev, unsigned int asid) | |
| 499 | +static void _mlx5_vdpa_destroy_mr(struct mlx5_vdpa_dev *mvdev, struct mlx5_vdpa_mr *mr) | |
| 493 | 500 | { |
| 494 | − if (mvdev->group2asid[MLX5_VDPA_CVQ_GROUP] != asid) | |
| 495 | − return; | |
| 501 | + if (mr->user_mr) | |
| 502 | + destroy_user_mr(mvdev, mr); | |
| 503 | + else | |
| 504 | + destroy_dma_mr(mvdev, mr); | |
| 496 | 505 | |
| 497 | − prune_iotlb(mvdev); | |
| 506 | + vhost_iotlb_free(mr->iotlb); | |
| 498 | 507 | } |
| 499 | 508 | |
| 500 | −static void _mlx5_vdpa_destroy_dvq_mr(struct mlx5_vdpa_dev *mvdev, unsigned int asid) | |
| 509 | +void mlx5_vdpa_destroy_mr(struct mlx5_vdpa_dev *mvdev, | |
| 510 | + struct mlx5_vdpa_mr *mr) | |
| 501 | 511 | { |
| 502 | − struct mlx5_vdpa_mr *mr = &mvdev->mr; | |
| 503 | − | |
| 504 | − if (mvdev->group2asid[MLX5_VDPA_DATAVQ_GROUP] != asid) | |
| 512 | + if (!mr) | |
| 505 | 513 | return; |
| 506 | 514 | |
| 507 | − if (!mr->initialized) | |
| 508 | − return; | |
| 515 | + mutex_lock(&mvdev->mr_mtx); | |
| 509 | 516 | |
| 510 | − if (mr->user_mr) | |
| 511 | − destroy_user_mr(mvdev, mr); | |
| 512 | − else | |
| 513 | − destroy_dma_mr(mvdev, mr); | |
| 517 | + _mlx5_vdpa_destroy_mr(mvdev, mr); | |
| 518 | + | |
| 519 | + for (int i = 0; i < MLX5_VDPA_NUM_AS; i++) { | |
| 520 | + if (mvdev->mr[i] == mr) | |
| 521 | + mvdev->mr[i] = NULL; | |
| 522 | + } | |
| 514 | 523 | |
| 515 | − mr->initialized = false; | |
| 524 | + mutex_unlock(&mvdev->mr_mtx); | |
| 525 | + | |
| 526 | + kfree(mr); | |
| 516 | 527 | } |
| 517 | 528 | |
| 518 | −void mlx5_vdpa_destroy_mr_asid(struct mlx5_vdpa_dev *mvdev, unsigned int asid) | |
| 529 | +void mlx5_vdpa_update_mr(struct mlx5_vdpa_dev *mvdev, | |
| 530 | + struct mlx5_vdpa_mr *new_mr, | |
| 531 | + unsigned int asid) | |
| 519 | 532 | { |
| 520 | − struct mlx5_vdpa_mr *mr = &mvdev->mr; | |
| 533 | + struct mlx5_vdpa_mr *old_mr = mvdev->mr[asid]; | |
| 521 | 534 | |
| 522 | − mutex_lock(&mr->mkey_mtx); | |
| 535 | + mutex_lock(&mvdev->mr_mtx); | |
| 523 | 536 | |
| 524 | − _mlx5_vdpa_destroy_dvq_mr(mvdev, asid); | |
| 525 | − _mlx5_vdpa_destroy_cvq_mr(mvdev, asid); | |
| 537 | + mvdev->mr[asid] = new_mr; | |
| 538 | + if (old_mr) { | |
| 539 | + _mlx5_vdpa_destroy_mr(mvdev, old_mr); | |
| 540 | + kfree(old_mr); | |
| 541 | + } | |
| 526 | 542 | |
| 527 | − mutex_unlock(&mr->mkey_mtx); | |
| 528 | −} | |
| 543 | + mutex_unlock(&mvdev->mr_mtx); | |
| 529 | 544 | |
| 530 | −void mlx5_vdpa_destroy_mr(struct mlx5_vdpa_dev *mvdev) | |
| 531 | −{ | |
| 532 | − mlx5_vdpa_destroy_mr_asid(mvdev, mvdev->group2asid[MLX5_VDPA_CVQ_GROUP]); | |
| 533 | − mlx5_vdpa_destroy_mr_asid(mvdev, mvdev->group2asid[MLX5_VDPA_DATAVQ_GROUP]); | |
| 534 | 545 | } |
| 535 | 546 | |
| 536 | −static int _mlx5_vdpa_create_cvq_mr(struct mlx5_vdpa_dev *mvdev, | |
| 537 | − struct vhost_iotlb *iotlb, | |
| 538 | − unsigned int asid) | |
| 547 | +void mlx5_vdpa_destroy_mr_resources(struct mlx5_vdpa_dev *mvdev) | |
| 539 | 548 | { |
| 540 | − if (mvdev->group2asid[MLX5_VDPA_CVQ_GROUP] != asid) | |
| 541 | − return 0; | |
| 549 | + for (int i = 0; i < MLX5_VDPA_NUM_AS; i++) | |
| 550 | + mlx5_vdpa_destroy_mr(mvdev, mvdev->mr[i]); | |
| 542 | 551 | |
| 543 | − return dup_iotlb(mvdev, iotlb); | |
| 552 | + prune_iotlb(mvdev->cvq.iotlb); | |
| 544 | 553 | } |
| 545 | 554 | |
| 546 | −static int _mlx5_vdpa_create_dvq_mr(struct mlx5_vdpa_dev *mvdev, | |
| 547 | − struct vhost_iotlb *iotlb, | |
| 548 | − unsigned int asid) | |
| 555 | +static int _mlx5_vdpa_create_mr(struct mlx5_vdpa_dev *mvdev, | |
| 556 | + struct mlx5_vdpa_mr *mr, | |
| 557 | + struct vhost_iotlb *iotlb) | |
| 549 | 558 | { |
| 550 | − struct mlx5_vdpa_mr *mr = &mvdev->mr; | |
| 551 | 559 | int err; |
| 552 | 560 | |
| 553 | − if (mvdev->group2asid[MLX5_VDPA_DATAVQ_GROUP] != asid) | |
| 554 | − return 0; | |
| 555 | − | |
| 556 | − if (mr->initialized) | |
| 557 | − return 0; | |
| 558 | − | |
| 559 | 561 | if (iotlb) |
| 560 | − err = create_user_mr(mvdev, iotlb); | |
| 562 | + err = create_user_mr(mvdev, mr, iotlb); | |
| 561 | 563 | else |
| 562 | 564 | err = create_dma_mr(mvdev, mr); |
| 563 | 565 | |
| 564 | 566 | if (err) |
| 565 | 567 | return err; |
| 566 | 568 | |
| 567 | − mr->initialized = true; | |
| 569 | + mr->iotlb = vhost_iotlb_alloc(0, 0); | |
| 570 | + if (!mr->iotlb) { | |
| 571 | + err = -ENOMEM; | |
| 572 | + goto err_mr; | |
| 573 | + } | |
| 574 | + | |
| 575 | + err = dup_iotlb(mr->iotlb, iotlb); | |
| 576 | + if (err) | |
| 577 | + goto err_iotlb; | |
| 568 | 578 | |
| 569 | 579 | return 0; |
| 580 | + | |
| 581 | +err_iotlb: | |
| 582 | + vhost_iotlb_free(mr->iotlb); | |
| 583 | + | |
| 584 | +err_mr: | |
| 585 | + if (iotlb) | |
| 586 | + destroy_user_mr(mvdev, mr); | |
| 587 | + else | |
| 588 | + destroy_dma_mr(mvdev, mr); | |
| 589 | + | |
| 590 | + return err; | |
| 570 | 591 | } |
| 571 | 592 | |
| 572 | −static int _mlx5_vdpa_create_mr(struct mlx5_vdpa_dev *mvdev, | |
| 573 | − struct vhost_iotlb *iotlb, unsigned int asid) | |
| 593 | +struct mlx5_vdpa_mr *mlx5_vdpa_create_mr(struct mlx5_vdpa_dev *mvdev, | |
| 594 | + struct vhost_iotlb *iotlb) | |
| 574 | 595 | { |
| 596 | + struct mlx5_vdpa_mr *mr; | |
| 575 | 597 | int err; |
| 576 | 598 | |
| 577 | − err = _mlx5_vdpa_create_dvq_mr(mvdev, iotlb, asid); | |
| 578 | − if (err) | |
| 579 | − return err; | |
| 599 | + mr = kzalloc(sizeof(*mr), GFP_KERNEL); | |
| 600 | + if (!mr) | |
| 601 | + return ERR_PTR(-ENOMEM); | |
| 602 | + | |
| 603 | + mutex_lock(&mvdev->mr_mtx); | |
| 604 | + err = _mlx5_vdpa_create_mr(mvdev, mr, iotlb); | |
| 605 | + mutex_unlock(&mvdev->mr_mtx); | |
| 580 | 606 | |
| 581 | − err = _mlx5_vdpa_create_cvq_mr(mvdev, iotlb, asid); | |
| 582 | 607 | if (err) |
| 583 | 608 | goto out_err; |
| 584 | 609 | |
| 585 | − return 0; | |
| 610 | + return mr; | |
| 586 | 611 | |
| 587 | 612 | out_err: |
| 588 | − _mlx5_vdpa_destroy_dvq_mr(mvdev, asid); | |
| 589 | − | |
| 590 | − return err; | |
| 613 | + kfree(mr); | |
| 614 | + return ERR_PTR(err); | |
| 591 | 615 | } |
| 592 | 616 | |
| 593 | −int mlx5_vdpa_create_mr(struct mlx5_vdpa_dev *mvdev, struct vhost_iotlb *iotlb, | |
| 594 | − unsigned int asid) | |
| 617 | +int mlx5_vdpa_update_cvq_iotlb(struct mlx5_vdpa_dev *mvdev, | |
| 618 | + struct vhost_iotlb *iotlb, | |
| 619 | + unsigned int asid) | |
| 595 | 620 | { |
| 596 | 621 | int err; |
| 597 | 622 | |
| 598 | − mutex_lock(&mvdev->mr.mkey_mtx); | |
| 599 | − err = _mlx5_vdpa_create_mr(mvdev, iotlb, asid); | |
| 600 | − mutex_unlock(&mvdev->mr.mkey_mtx); | |
| 623 | + if (mvdev->group2asid[MLX5_VDPA_CVQ_GROUP] != asid) | |
| 624 | + return 0; | |
| 625 | + | |
| 626 | + spin_lock(&mvdev->cvq.iommu_lock); | |
| 627 | + | |
| 628 | + prune_iotlb(mvdev->cvq.iotlb); | |
| 629 | + err = dup_iotlb(mvdev->cvq.iotlb, iotlb); | |
| 630 | + | |
| 631 | + spin_unlock(&mvdev->cvq.iommu_lock); | |
| 632 | + | |
| 601 | 633 | return err; |
| 602 | 634 | } |
| 603 | 635 | |
| 604 | −int mlx5_vdpa_handle_set_map(struct mlx5_vdpa_dev *mvdev, struct vhost_iotlb *iotlb, | |
| 605 | − bool *change_map, unsigned int asid) | |
| 636 | +int mlx5_vdpa_create_dma_mr(struct mlx5_vdpa_dev *mvdev) | |
| 606 | 637 | { |
| 607 | − struct mlx5_vdpa_mr *mr = &mvdev->mr; | |
| 608 | − int err = 0; | |
| 638 | + struct mlx5_vdpa_mr *mr; | |
| 639 | + | |
| 640 | + mr = mlx5_vdpa_create_mr(mvdev, NULL); | |
| 641 | + if (IS_ERR(mr)) | |
| 642 | + return PTR_ERR(mr); | |
| 609 | 643 | |
| 610 | − *change_map = false; | |
| 611 | − mutex_lock(&mr->mkey_mtx); | |
| 612 | − if (mr->initialized) { | |
| 613 | − mlx5_vdpa_info(mvdev, "memory map update\n"); | |
| 614 | − *change_map = true; | |
| 644 | + mlx5_vdpa_update_mr(mvdev, mr, 0); | |
| 645 | + | |
| 646 | + return mlx5_vdpa_update_cvq_iotlb(mvdev, NULL, 0); | |
| 647 | +} | |
| 648 | + | |
| 649 | +int mlx5_vdpa_reset_mr(struct mlx5_vdpa_dev *mvdev, unsigned int asid) | |
| 650 | +{ | |
| 651 | + if (asid >= MLX5_VDPA_NUM_AS) | |
| 652 | + return -EINVAL; | |
| 653 | + | |
| 654 | + mlx5_vdpa_destroy_mr(mvdev, mvdev->mr[asid]); | |
| 655 | + | |
| 656 | + if (asid == 0 && MLX5_CAP_GEN(mvdev->mdev, umem_uid_0)) { | |
| 657 | + if (mlx5_vdpa_create_dma_mr(mvdev)) | |
| 658 | + mlx5_vdpa_warn(mvdev, "create DMA MR failed\n"); | |
| 659 | + } else { | |
| 660 | + mlx5_vdpa_update_cvq_iotlb(mvdev, NULL, asid); | |
| 615 | 661 | } |
| 616 | − if (!*change_map) | |
| 617 | − err = _mlx5_vdpa_create_mr(mvdev, iotlb, asid); | |
| 618 | − mutex_unlock(&mr->mkey_mtx); | |
| 619 | 662 | |
| 620 | − return err; | |
| 663 | + return 0; | |
| 621 | 664 | } |
| @@ -256,7 +256,7 @@ int mlx5_vdpa_alloc_resources(struct mlx5_vdpa_dev *mvdev) · 255 unmodified lines | ||
| 256 | 256 | mlx5_vdpa_warn(mvdev, "resources already allocated\n"); |
| 257 | 257 | return -EINVAL; |
| 258 | 258 | } |
| 259 | − mutex_init(&mvdev->mr.mkey_mtx); | |
| 259 | + mutex_init(&mvdev->mr_mtx); | |
| 260 | 260 | res->uar = mlx5_get_uars_page(mdev); |
| 261 | 261 | if (IS_ERR(res->uar)) { |
| 262 | 262 | err = PTR_ERR(res->uar); |
| @@ -301,7 +301,7 @@ err_pd: · 38 unmodified lines | ||
| 301 | 301 | err_uctx: |
| 302 | 302 | mlx5_put_uars_page(mdev, res->uar); |
| 303 | 303 | err_uars: |
| 304 | − mutex_destroy(&mvdev->mr.mkey_mtx); | |
| 304 | + mutex_destroy(&mvdev->mr_mtx); | |
| 305 | 305 | return err; |
| 306 | 306 | } |
| 307 | 307 | |
| @@ -318,6 +318,6 @@ void mlx5_vdpa_free_resources(struct mlx5_vdpa_dev *mvdev) · 10 unmodified lines | ||
| 318 | 318 | dealloc_pd(mvdev, res->pdn, res->uid); |
| 319 | 319 | destroy_uctx(mvdev, res->uid); |
| 320 | 320 | mlx5_put_uars_page(mvdev->mdev, res->uar); |
| 321 | − mutex_destroy(&mvdev->mr.mkey_mtx); | |
| 321 | + mutex_destroy(&mvdev->mr_mtx); | |
| 322 | 322 | res->valid = false; |
| 323 | 323 | } |
| @@ -7,6 +7,7 @@ · 6 unmodified lines | ||
| 7 | 7 | #include <uapi/linux/virtio_net.h> |
| 8 | 8 | #include <uapi/linux/virtio_ids.h> |
| 9 | 9 | #include <uapi/linux/vdpa.h> |
| 10 | +#include <uapi/linux/vhost_types.h> | |
| 10 | 11 | #include <linux/virtio_config.h> |
| 11 | 12 | #include <linux/auxiliary_bus.h> |
| 12 | 13 | #include <linux/mlx5/cq.h> |
| @@ -861,6 +862,9 @@ static int create_virtqueue(struct mlx5_vdpa_net *ndev, struct mlx5_vdpa_virtque · 848 unmodified lines | ||
| 861 | 862 | { |
| 862 | 863 | int inlen = MLX5_ST_SZ_BYTES(create_virtio_net_q_in); |
| 863 | 864 | u32 out[MLX5_ST_SZ_DW(create_virtio_net_q_out)] = {}; |
| 865 | + struct mlx5_vdpa_dev *mvdev = &ndev->mvdev; | |
| 866 | + struct mlx5_vdpa_mr *vq_mr; | |
| 867 | + struct mlx5_vdpa_mr *vq_desc_mr; | |
| 864 | 868 | void *obj_context; |
| 865 | 869 | u16 mlx_features; |
| 866 | 870 | void *cmd_hdr; |
| @@ -913,7 +917,14 @@ static int create_virtqueue(struct mlx5_vdpa_net *ndev, struct mlx5_vdpa_virtque · 46 unmodified lines | ||
| 913 | 917 | MLX5_SET64(virtio_q, vq_ctx, desc_addr, mvq->desc_addr); |
| 914 | 918 | MLX5_SET64(virtio_q, vq_ctx, used_addr, mvq->device_addr); |
| 915 | 919 | MLX5_SET64(virtio_q, vq_ctx, available_addr, mvq->driver_addr); |
| 916 | − MLX5_SET(virtio_q, vq_ctx, virtio_q_mkey, ndev->mvdev.mr.mkey); | |
| 920 | + vq_mr = mvdev->mr[mvdev->group2asid[MLX5_VDPA_DATAVQ_GROUP]]; | |
| 921 | + if (vq_mr) | |
| 922 | + MLX5_SET(virtio_q, vq_ctx, virtio_q_mkey, vq_mr->mkey); | |
| 923 | + | |
| 924 | + vq_desc_mr = mvdev->mr[mvdev->group2asid[MLX5_VDPA_DATAVQ_DESC_GROUP]]; | |
| 925 | + if (vq_desc_mr && MLX5_CAP_DEV_VDPA_EMULATION(mvdev->mdev, desc_group_mkey_supported)) | |
| 926 | + MLX5_SET(virtio_q, vq_ctx, desc_group_mkey, vq_desc_mr->mkey); | |
| 927 | + | |
| 917 | 928 | MLX5_SET(virtio_q, vq_ctx, umem_1_id, mvq->umem1.id); |
| 918 | 929 | MLX5_SET(virtio_q, vq_ctx, umem_1_size, mvq->umem1.size); |
| 919 | 930 | MLX5_SET(virtio_q, vq_ctx, umem_2_id, mvq->umem2.id); |
| @@ -2301,6 +2312,16 @@ static u32 mlx5_vdpa_get_vq_group(struct vdpa_device *vdev, u16 idx) · 1381 unmodified lines | ||
| 2301 | 2312 | return MLX5_VDPA_DATAVQ_GROUP; |
| 2302 | 2313 | } |
| 2303 | 2314 | |
| 2315 | +static u32 mlx5_vdpa_get_vq_desc_group(struct vdpa_device *vdev, u16 idx) | |
| 2316 | +{ | |
| 2317 | + struct mlx5_vdpa_dev *mvdev = to_mvdev(vdev); | |
| 2318 | + | |
| 2319 | + if (is_ctrl_vq_idx(mvdev, idx)) | |
| 2320 | + return MLX5_VDPA_CVQ_GROUP; | |
| 2321 | + | |
| 2322 | + return MLX5_VDPA_DATAVQ_DESC_GROUP; | |
| 2323 | +} | |
| 2324 | + | |
| 2304 | 2325 | static u64 mlx_to_vritio_features(u16 dev_features) |
| 2305 | 2326 | { |
| 2306 | 2327 | u64 result = 0; |
| @@ -2539,6 +2560,11 @@ static void unregister_link_notifier(struct mlx5_vdpa_net *ndev) · 232 unmodified lines | ||
| 2539 | 2560 | flush_workqueue(ndev->mvdev.wq); |
| 2540 | 2561 | } |
| 2541 | 2562 | |
| 2563 | +static u64 mlx5_vdpa_get_backend_features(const struct vdpa_device *vdpa) | |
| 2564 | +{ | |
| 2565 | + return BIT_ULL(VHOST_BACKEND_F_ENABLE_AFTER_DRIVER_OK); | |
| 2566 | +} | |
| 2567 | + | |
| 2542 | 2568 | static int mlx5_vdpa_set_driver_features(struct vdpa_device *vdev, u64 features) |
| 2543 | 2569 | { |
| 2544 | 2570 | struct mlx5_vdpa_dev *mvdev = to_mvdev(vdev); |
| @@ -2673,7 +2699,8 @@ static void restore_channels_info(struct mlx5_vdpa_net *ndev) · 128 unmodified lines | ||
| 2673 | 2699 | } |
| 2674 | 2700 | |
| 2675 | 2701 | static int mlx5_vdpa_change_map(struct mlx5_vdpa_dev *mvdev, |
| 2676 | − struct vhost_iotlb *iotlb, unsigned int asid) | |
| 2702 | + struct mlx5_vdpa_mr *new_mr, | |
| 2703 | + unsigned int asid) | |
| 2677 | 2704 | { |
| 2678 | 2705 | struct mlx5_vdpa_net *ndev = to_mlx5_vdpa_ndev(mvdev); |
| 2679 | 2706 | int err; |
| @@ -2681,28 +2708,21 @@ static int mlx5_vdpa_change_map(struct mlx5_vdpa_dev *mvdev, · 1 unmodified line | ||
| 2681 | 2708 | suspend_vqs(ndev); |
| 2682 | 2709 | err = save_channels_info(ndev); |
| 2683 | 2710 | if (err) |
| 2684 | − goto err_mr; | |
| 2711 | + return err; | |
| 2685 | 2712 | |
| 2686 | 2713 | teardown_driver(ndev); |
| 2687 | − mlx5_vdpa_destroy_mr_asid(mvdev, asid); | |
| 2688 | − err = mlx5_vdpa_create_mr(mvdev, iotlb, asid); | |
| 2689 | − if (err) | |
| 2690 | − goto err_mr; | |
| 2714 | + | |
| 2715 | + mlx5_vdpa_update_mr(mvdev, new_mr, asid); | |
| 2691 | 2716 | |
| 2692 | 2717 | if (!(mvdev->status & VIRTIO_CONFIG_S_DRIVER_OK) || mvdev->suspended) |
| 2693 | − goto err_mr; | |
| 2718 | + return 0; | |
| 2694 | 2719 | |
| 2695 | 2720 | restore_channels_info(ndev); |
| 2696 | 2721 | err = setup_driver(mvdev); |
| 2697 | 2722 | if (err) |
| 2698 | − goto err_setup; | |
| 2723 | + return err; | |
| 2699 | 2724 | |
| 2700 | 2725 | return 0; |
| 2701 | − | |
| 2702 | −err_setup: | |
| 2703 | − mlx5_vdpa_destroy_mr_asid(mvdev, asid); | |
| 2704 | −err_mr: | |
| 2705 | − return err; | |
| 2706 | 2726 | } |
| 2707 | 2727 | |
| 2708 | 2728 | /* reslock must be held for this function */ |
| @@ -2841,7 +2861,7 @@ static void mlx5_vdpa_set_status(struct vdpa_device *vdev, u8 status) · 132 unmodified lines | ||
| 2841 | 2861 | err_driver: |
| 2842 | 2862 | unregister_link_notifier(ndev); |
| 2843 | 2863 | err_setup: |
| 2844 | − mlx5_vdpa_destroy_mr(&ndev->mvdev); | |
| 2864 | + mlx5_vdpa_destroy_mr_resources(&ndev->mvdev); | |
| 2845 | 2865 | ndev->mvdev.status |= VIRTIO_CONFIG_S_FAILED; |
| 2846 | 2866 | err_clear: |
| 2847 | 2867 | up_write(&ndev->reslock); |
| @@ -2856,7 +2876,7 @@ static void init_group_to_asid_map(struct mlx5_vdpa_dev *mvdev) · 8 unmodified lines | ||
| 2856 | 2876 | mvdev->group2asid[i] = 0; |
| 2857 | 2877 | } |
| 2858 | 2878 | |
| 2859 | −static int mlx5_vdpa_reset(struct vdpa_device *vdev) | |
| 2879 | +static int mlx5_vdpa_compat_reset(struct vdpa_device *vdev, u32 flags) | |
| 2860 | 2880 | { |
| 2861 | 2881 | struct mlx5_vdpa_dev *mvdev = to_mvdev(vdev); |
| 2862 | 2882 | struct mlx5_vdpa_net *ndev = to_mlx5_vdpa_ndev(mvdev); |
| @@ -2868,7 +2888,8 @@ static int mlx5_vdpa_reset(struct vdpa_device *vdev) · 5 unmodified lines | ||
| 2868 | 2888 | unregister_link_notifier(ndev); |
| 2869 | 2889 | teardown_driver(ndev); |
| 2870 | 2890 | clear_vqs_ready(ndev); |
| 2871 | − mlx5_vdpa_destroy_mr(&ndev->mvdev); | |
| 2891 | + if (flags & VDPA_RESET_F_CLEAN_MAP) | |
| 2892 | + mlx5_vdpa_destroy_mr_resources(&ndev->mvdev); | |
| 2872 | 2893 | ndev->mvdev.status = 0; |
| 2873 | 2894 | ndev->mvdev.suspended = false; |
| 2874 | 2895 | ndev->cur_num_vqs = 0; |
| @@ -2879,8 +2900,9 @@ static int mlx5_vdpa_reset(struct vdpa_device *vdev) · 4 unmodified lines | ||
| 2879 | 2900 | init_group_to_asid_map(mvdev); |
| 2880 | 2901 | ++mvdev->generation; |
| 2881 | 2902 | |
| 2882 | − if (MLX5_CAP_GEN(mvdev->mdev, umem_uid_0)) { | |
| 2883 | − if (mlx5_vdpa_create_mr(mvdev, NULL, 0)) | |
| 2903 | + if ((flags & VDPA_RESET_F_CLEAN_MAP) && | |
| 2904 | + MLX5_CAP_GEN(mvdev->mdev, umem_uid_0)) { | |
| 2905 | + if (mlx5_vdpa_create_dma_mr(mvdev)) | |
| 2884 | 2906 | mlx5_vdpa_warn(mvdev, "create MR failed\n"); |
| 2885 | 2907 | } |
| 2886 | 2908 | up_write(&ndev->reslock); |
| @@ -2888,6 +2910,11 @@ static int mlx5_vdpa_reset(struct vdpa_device *vdev) · 1 unmodified line | ||
| 2888 | 2910 | return 0; |
| 2889 | 2911 | } |
| 2890 | 2912 | |
| 2913 | +static int mlx5_vdpa_reset(struct vdpa_device *vdev) | |
| 2914 | +{ | |
| 2915 | + return mlx5_vdpa_compat_reset(vdev, 0); | |
| 2916 | +} | |
| 2917 | + | |
| 2891 | 2918 | static size_t mlx5_vdpa_get_config_size(struct vdpa_device *vdev) |
| 2892 | 2919 | { |
| 2893 | 2920 | return sizeof(struct virtio_net_config); |
| @@ -2919,18 +2946,38 @@ static u32 mlx5_vdpa_get_generation(struct vdpa_device *vdev) · 25 unmodified lines | ||
| 2919 | 2946 | static int set_map_data(struct mlx5_vdpa_dev *mvdev, struct vhost_iotlb *iotlb, |
| 2920 | 2947 | unsigned int asid) |
| 2921 | 2948 | { |
| 2922 | − bool change_map; | |
| 2949 | + struct mlx5_vdpa_mr *new_mr; | |
| 2923 | 2950 | int err; |
| 2924 | 2951 | |
| 2925 | − err = mlx5_vdpa_handle_set_map(mvdev, iotlb, &change_map, asid); | |
| 2926 | − if (err) { | |
| 2927 | − mlx5_vdpa_warn(mvdev, "set map failed(%d)\n", err); | |
| 2928 | − return err; | |
| 2952 | + if (asid >= MLX5_VDPA_NUM_AS) | |
| 2953 | + return -EINVAL; | |
| 2954 | + | |
| 2955 | + if (vhost_iotlb_itree_first(iotlb, 0, U64_MAX)) { | |
| 2956 | + new_mr = mlx5_vdpa_create_mr(mvdev, iotlb); | |
| 2957 | + if (IS_ERR(new_mr)) { | |
| 2958 | + err = PTR_ERR(new_mr); | |
| 2959 | + mlx5_vdpa_warn(mvdev, "create map failed(%d)\n", err); | |
| 2960 | + return err; | |
| 2961 | + } | |
| 2962 | + } else { | |
| 2963 | + /* Empty iotlbs don't have an mr but will clear the previous mr. */ | |
| 2964 | + new_mr = NULL; | |
| 2965 | + } | |
| 2966 | + | |
| 2967 | + if (!mvdev->mr[asid]) { | |
| 2968 | + mlx5_vdpa_update_mr(mvdev, new_mr, asid); | |
| 2969 | + } else { | |
| 2970 | + err = mlx5_vdpa_change_map(mvdev, new_mr, asid); | |
| 2971 | + if (err) { | |
| 2972 | + mlx5_vdpa_warn(mvdev, "change map failed(%d)\n", err); | |
| 2973 | + goto out_err; | |
| 2974 | + } | |
| 2929 | 2975 | } |
| 2930 | 2976 | |
| 2931 | − if (change_map) | |
| 2932 | − err = mlx5_vdpa_change_map(mvdev, iotlb, asid); | |
| 2977 | + return mlx5_vdpa_update_cvq_iotlb(mvdev, iotlb, asid); | |
| 2933 | 2978 | |
| 2979 | +out_err: | |
| 2980 | + mlx5_vdpa_destroy_mr(mvdev, new_mr); | |
| 2934 | 2981 | return err; |
| 2935 | 2982 | } |
| 2936 | 2983 | |
| @@ -2947,6 +2994,18 @@ static int mlx5_vdpa_set_map(struct vdpa_device *vdev, unsigned int asid, · 10 unmodified lines | ||
| 2947 | 2994 | return err; |
| 2948 | 2995 | } |
| 2949 | 2996 | |
| 2997 | +static int mlx5_vdpa_reset_map(struct vdpa_device *vdev, unsigned int asid) | |
| 2998 | +{ | |
| 2999 | + struct mlx5_vdpa_dev *mvdev = to_mvdev(vdev); | |
| 3000 | + struct mlx5_vdpa_net *ndev = to_mlx5_vdpa_ndev(mvdev); | |
| 3001 | + int err; | |
| 3002 | + | |
| 3003 | + down_write(&ndev->reslock); | |
| 3004 | + err = mlx5_vdpa_reset_mr(mvdev, asid); | |
| 3005 | + up_write(&ndev->reslock); | |
| 3006 | + return err; | |
| 3007 | +} | |
| 3008 | + | |
| 2950 | 3009 | static struct device *mlx5_get_vq_dma_dev(struct vdpa_device *vdev, u16 idx) |
| 2951 | 3010 | { |
| 2952 | 3011 | struct mlx5_vdpa_dev *mvdev = to_mvdev(vdev); |
| @@ -2985,7 +3044,7 @@ static void mlx5_vdpa_free(struct vdpa_device *vdev) · 32 unmodified lines | ||
| 2985 | 3044 | ndev = to_mlx5_vdpa_ndev(mvdev); |
| 2986 | 3045 | |
| 2987 | 3046 | free_resources(ndev); |
| 2988 | − mlx5_vdpa_destroy_mr(mvdev); | |
| 3047 | + mlx5_vdpa_destroy_mr_resources(mvdev); | |
| 2989 | 3048 | if (!is_zero_ether_addr(ndev->config.mac)) { |
| 2990 | 3049 | pfmdev = pci_get_drvdata(pci_physfn(mvdev->mdev->pdev)); |
| 2991 | 3050 | mlx5_mpfs_del_mac(pfmdev, ndev->config.mac); |
| @@ -3169,12 +3228,19 @@ static int mlx5_set_group_asid(struct vdpa_device *vdev, u32 group, · 177 unmodified lines | ||
| 3169 | 3228 | unsigned int asid) |
| 3170 | 3229 | { |
| 3171 | 3230 | struct mlx5_vdpa_dev *mvdev = to_mvdev(vdev); |
| 3231 | + int err = 0; | |
| 3172 | 3232 | |
| 3173 | 3233 | if (group >= MLX5_VDPA_NUMVQ_GROUPS) |
| 3174 | 3234 | return -EINVAL; |
| 3175 | 3235 | |
| 3176 | 3236 | mvdev->group2asid[group] = asid; |
| 3177 | − return 0; | |
| 3237 | + | |
| 3238 | + mutex_lock(&mvdev->mr_mtx); | |
| 3239 | + if (group == MLX5_VDPA_CVQ_GROUP && mvdev->mr[asid]) | |
| 3240 | + err = mlx5_vdpa_update_cvq_iotlb(mvdev, mvdev->mr[asid]->iotlb, asid); | |
| 3241 | + mutex_unlock(&mvdev->mr_mtx); | |
| 3242 | + | |
| 3243 | + return err; | |
| 3178 | 3244 | } |
| 3179 | 3245 | |
| 3180 | 3246 | static const struct vdpa_config_ops mlx5_vdpa_ops = { |
| @@ -3191,7 +3257,9 @@ static const struct vdpa_config_ops mlx5_vdpa_ops = { · 10 unmodified lines | ||
| 3191 | 3257 | .get_vq_irq = mlx5_get_vq_irq, |
| 3192 | 3258 | .get_vq_align = mlx5_vdpa_get_vq_align, |
| 3193 | 3259 | .get_vq_group = mlx5_vdpa_get_vq_group, |
| 3260 | + .get_vq_desc_group = mlx5_vdpa_get_vq_desc_group, /* Op disabled if not supported. */ | |
| 3194 | 3261 | .get_device_features = mlx5_vdpa_get_device_features, |
| 3262 | + .get_backend_features = mlx5_vdpa_get_backend_features, | |
| 3195 | 3263 | .set_driver_features = mlx5_vdpa_set_driver_features, |
| 3196 | 3264 | .get_driver_features = mlx5_vdpa_get_driver_features, |
| 3197 | 3265 | .set_config_cb = mlx5_vdpa_set_config_cb, |
| @@ -3201,11 +3269,13 @@ static const struct vdpa_config_ops mlx5_vdpa_ops = { · 3 unmodified lines | ||
| 3201 | 3269 | .get_status = mlx5_vdpa_get_status, |
| 3202 | 3270 | .set_status = mlx5_vdpa_set_status, |
| 3203 | 3271 | .reset = mlx5_vdpa_reset, |
| 3272 | + .compat_reset = mlx5_vdpa_compat_reset, | |
| 3204 | 3273 | .get_config_size = mlx5_vdpa_get_config_size, |
| 3205 | 3274 | .get_config = mlx5_vdpa_get_config, |
| 3206 | 3275 | .set_config = mlx5_vdpa_set_config, |
| 3207 | 3276 | .get_generation = mlx5_vdpa_get_generation, |
| 3208 | 3277 | .set_map = mlx5_vdpa_set_map, |
| 3278 | + .reset_map = mlx5_vdpa_reset_map, | |
| 3209 | 3279 | .set_group_asid = mlx5_set_group_asid, |
| 3210 | 3280 | .get_vq_dma_dev = mlx5_get_vq_dma_dev, |
| 3211 | 3281 | .free = mlx5_vdpa_free, |
| @@ -3289,6 +3359,7 @@ struct mlx5_vdpa_mgmtdev { · 77 unmodified lines | ||
| 3289 | 3359 | struct vdpa_mgmt_dev mgtdev; |
| 3290 | 3360 | struct mlx5_adev *madev; |
| 3291 | 3361 | struct mlx5_vdpa_net *ndev; |
| 3362 | + struct vdpa_config_ops vdpa_ops; | |
| 3292 | 3363 | }; |
| 3293 | 3364 | |
| 3294 | 3365 | static int config_func_mtu(struct mlx5_core_dev *mdev, u16 mtu) |
| @@ -3402,7 +3473,7 @@ static int mlx5_vdpa_dev_add(struct vdpa_mgmt_dev *v_mdev, const char *name, · 107 unmodified lines | ||
| 3402 | 3473 | max_vqs = 2; |
| 3403 | 3474 | } |
| 3404 | 3475 | |
| 3405 | − ndev = vdpa_alloc_device(struct mlx5_vdpa_net, mvdev.vdev, mdev->device, &mlx5_vdpa_ops, | |
| 3476 | + ndev = vdpa_alloc_device(struct mlx5_vdpa_net, mvdev.vdev, mdev->device, &mgtdev->vdpa_ops, | |
| 3406 | 3477 | MLX5_VDPA_NUMVQ_GROUPS, MLX5_VDPA_NUM_AS, name, false); |
| 3407 | 3478 | if (IS_ERR(ndev)) |
| 3408 | 3479 | return PTR_ERR(ndev); |
| @@ -3485,7 +3556,7 @@ static int mlx5_vdpa_dev_add(struct vdpa_mgmt_dev *v_mdev, const char *name, · 76 unmodified lines | ||
| 3485 | 3556 | goto err_mpfs; |
| 3486 | 3557 | |
| 3487 | 3558 | if (MLX5_CAP_GEN(mvdev->mdev, umem_uid_0)) { |
| 3488 | − err = mlx5_vdpa_create_mr(mvdev, NULL, 0); | |
| 3559 | + err = mlx5_vdpa_create_dma_mr(mvdev); | |
| 3489 | 3560 | if (err) |
| 3490 | 3561 | goto err_res; |
| 3491 | 3562 | } |
| @@ -3515,7 +3586,7 @@ err_reg: · 23 unmodified lines | ||
| 3515 | 3586 | err_res2: |
| 3516 | 3587 | free_resources(ndev); |
| 3517 | 3588 | err_mr: |
| 3518 | − mlx5_vdpa_destroy_mr(mvdev); | |
| 3589 | + mlx5_vdpa_destroy_mr_resources(mvdev); | |
| 3519 | 3590 | err_res: |
| 3520 | 3591 | mlx5_vdpa_free_resources(&ndev->mvdev); |
| 3521 | 3592 | err_mpfs: |
| @@ -3575,6 +3646,10 @@ static int mlx5v_probe(struct auxiliary_device *adev, · 53 unmodified lines | ||
| 3575 | 3646 | MLX5_CAP_DEV_VDPA_EMULATION(mdev, max_num_virtio_queues) + 1; |
| 3576 | 3647 | mgtdev->mgtdev.supported_features = get_supported_features(mdev); |
| 3577 | 3648 | mgtdev->madev = madev; |
| 3649 | + mgtdev->vdpa_ops = mlx5_vdpa_ops; | |
| 3650 | + | |
| 3651 | + if (!MLX5_CAP_DEV_VDPA_EMULATION(mdev, desc_group_mkey_supported)) | |
| 3652 | + mgtdev->vdpa_ops.get_vq_desc_group = NULL; | |
| 3578 | 3653 | |
| 3579 | 3654 | err = vdpa_mgmtdev_register(&mgtdev->mgtdev); |
| 3580 | 3655 | if (err) |
| @@ -139,7 +139,7 @@ static void vdpasim_vq_reset(struct vdpasim *vdpasim, · 138 unmodified lines | ||
| 139 | 139 | vq->vring.notify = NULL; |
| 140 | 140 | } |
| 141 | 141 | |
| 142 | −static void vdpasim_do_reset(struct vdpasim *vdpasim) | |
| 142 | +static void vdpasim_do_reset(struct vdpasim *vdpasim, u32 flags) | |
| 143 | 143 | { |
| 144 | 144 | int i; |
| 145 | 145 | |
| @@ -151,11 +151,13 @@ static void vdpasim_do_reset(struct vdpasim *vdpasim) · 5 unmodified lines | ||
| 151 | 151 | &vdpasim->iommu_lock); |
| 152 | 152 | } |
| 153 | 153 | |
| 154 | − for (i = 0; i < vdpasim->dev_attr.nas; i++) { | |
| 155 | − vhost_iotlb_reset(&vdpasim->iommu[i]); | |
| 156 | − vhost_iotlb_add_range(&vdpasim->iommu[i], 0, ULONG_MAX, | |
| 157 | − 0, VHOST_MAP_RW); | |
| 158 | − vdpasim->iommu_pt[i] = true; | |
| 154 | + if (flags & VDPA_RESET_F_CLEAN_MAP) { | |
| 155 | + for (i = 0; i < vdpasim->dev_attr.nas; i++) { | |
| 156 | + vhost_iotlb_reset(&vdpasim->iommu[i]); | |
| 157 | + vhost_iotlb_add_range(&vdpasim->iommu[i], 0, ULONG_MAX, | |
| 158 | + 0, VHOST_MAP_RW); | |
| 159 | + vdpasim->iommu_pt[i] = true; | |
| 160 | + } | |
| 159 | 161 | } |
| 160 | 162 | |
| 161 | 163 | vdpasim->running = true; |
| @@ -259,8 +261,12 @@ struct vdpasim *vdpasim_create(struct vdpasim_dev_attr *dev_attr, · 97 unmodified lines | ||
| 259 | 261 | if (!vdpasim->iommu_pt) |
| 260 | 262 | goto err_iommu; |
| 261 | 263 | |
| 262 | − for (i = 0; i < vdpasim->dev_attr.nas; i++) | |
| 264 | + for (i = 0; i < vdpasim->dev_attr.nas; i++) { | |
| 263 | 265 | vhost_iotlb_init(&vdpasim->iommu[i], max_iotlb_entries, 0); |
| 266 | + vhost_iotlb_add_range(&vdpasim->iommu[i], 0, ULONG_MAX, 0, | |
| 267 | + VHOST_MAP_RW); | |
| 268 | + vdpasim->iommu_pt[i] = true; | |
| 269 | + } | |
| 264 | 270 | |
| 265 | 271 | for (i = 0; i < dev_attr->nvqs; i++) |
| 266 | 272 | vringh_set_iotlb(&vdpasim->vqs[i].vring, &vdpasim->iommu[0], |
| @@ -480,18 +486,23 @@ static void vdpasim_set_status(struct vdpa_device *vdpa, u8 status) · 213 unmodified lines | ||
| 480 | 486 | mutex_unlock(&vdpasim->mutex); |
| 481 | 487 | } |
| 482 | 488 | |
| 483 | −static int vdpasim_reset(struct vdpa_device *vdpa) | |
| 489 | +static int vdpasim_compat_reset(struct vdpa_device *vdpa, u32 flags) | |
| 484 | 490 | { |
| 485 | 491 | struct vdpasim *vdpasim = vdpa_to_sim(vdpa); |
| 486 | 492 | |
| 487 | 493 | mutex_lock(&vdpasim->mutex); |
| 488 | 494 | vdpasim->status = 0; |
| 489 | − vdpasim_do_reset(vdpasim); | |
| 495 | + vdpasim_do_reset(vdpasim, flags); | |
| 490 | 496 | mutex_unlock(&vdpasim->mutex); |
| 491 | 497 | |
| 492 | 498 | return 0; |
| 493 | 499 | } |
| 494 | 500 | |
| 501 | +static int vdpasim_reset(struct vdpa_device *vdpa) | |
| 502 | +{ | |
| 503 | + return vdpasim_compat_reset(vdpa, 0); | |
| 504 | +} | |
| 505 | + | |
| 495 | 506 | static int vdpasim_suspend(struct vdpa_device *vdpa) |
| 496 | 507 | { |
| 497 | 508 | struct vdpasim *vdpasim = vdpa_to_sim(vdpa); |
| @@ -637,6 +648,25 @@ err: · 139 unmodified lines | ||
| 637 | 648 | return ret; |
| 638 | 649 | } |
| 639 | 650 | |
| 651 | +static int vdpasim_reset_map(struct vdpa_device *vdpa, unsigned int asid) | |
| 652 | +{ | |
| 653 | + struct vdpasim *vdpasim = vdpa_to_sim(vdpa); | |
| 654 | + | |
| 655 | + if (asid >= vdpasim->dev_attr.nas) | |
| 656 | + return -EINVAL; | |
| 657 | + | |
| 658 | + spin_lock(&vdpasim->iommu_lock); | |
| 659 | + if (vdpasim->iommu_pt[asid]) | |
| 660 | + goto out; | |
| 661 | + vhost_iotlb_reset(&vdpasim->iommu[asid]); | |
| 662 | + vhost_iotlb_add_range(&vdpasim->iommu[asid], 0, ULONG_MAX, | |
| 663 | + 0, VHOST_MAP_RW); | |
| 664 | + vdpasim->iommu_pt[asid] = true; | |
| 665 | +out: | |
| 666 | + spin_unlock(&vdpasim->iommu_lock); | |
| 667 | + return 0; | |
| 668 | +} | |
| 669 | + | |
| 640 | 670 | static int vdpasim_bind_mm(struct vdpa_device *vdpa, struct mm_struct *mm) |
| 641 | 671 | { |
| 642 | 672 | struct vdpasim *vdpasim = vdpa_to_sim(vdpa); |
| @@ -749,6 +779,7 @@ static const struct vdpa_config_ops vdpasim_config_ops = { · 106 unmodified lines | ||
| 749 | 779 | .get_status = vdpasim_get_status, |
| 750 | 780 | .set_status = vdpasim_set_status, |
| 751 | 781 | .reset = vdpasim_reset, |
| 782 | + .compat_reset = vdpasim_compat_reset, | |
| 752 | 783 | .suspend = vdpasim_suspend, |
| 753 | 784 | .resume = vdpasim_resume, |
| 754 | 785 | .get_config_size = vdpasim_get_config_size, |
| @@ -759,6 +790,7 @@ static const struct vdpa_config_ops vdpasim_config_ops = { · 4 unmodified lines | ||
| 759 | 790 | .set_group_asid = vdpasim_set_group_asid, |
| 760 | 791 | .dma_map = vdpasim_dma_map, |
| 761 | 792 | .dma_unmap = vdpasim_dma_unmap, |
| 793 | + .reset_map = vdpasim_reset_map, | |
| 762 | 794 | .bind_mm = vdpasim_bind_mm, |
| 763 | 795 | .unbind_mm = vdpasim_unbind_mm, |
| 764 | 796 | .free = vdpasim_free, |
| @@ -787,6 +819,7 @@ static const struct vdpa_config_ops vdpasim_batch_config_ops = { · 22 unmodified lines | ||
| 787 | 819 | .get_status = vdpasim_get_status, |
| 788 | 820 | .set_status = vdpasim_set_status, |
| 789 | 821 | .reset = vdpasim_reset, |
| 822 | + .compat_reset = vdpasim_compat_reset, | |
| 790 | 823 | .suspend = vdpasim_suspend, |
| 791 | 824 | .resume = vdpasim_resume, |
| 792 | 825 | .get_config_size = vdpasim_get_config_size, |
| @@ -796,6 +829,7 @@ static const struct vdpa_config_ops vdpasim_batch_config_ops = { · 3 unmodified lines | ||
| 796 | 829 | .get_iova_range = vdpasim_get_iova_range, |
| 797 | 830 | .set_group_asid = vdpasim_set_group_asid, |
| 798 | 831 | .set_map = vdpasim_set_map, |
| 832 | + .reset_map = vdpasim_reset_map, | |
| 799 | 833 | .bind_mm = vdpasim_bind_mm, |
| 800 | 834 | .unbind_mm = vdpasim_unbind_mm, |
| 801 | 835 | .free = vdpasim_free, |
| @@ -134,7 +134,6 @@ static DEFINE_MUTEX(vduse_lock); · 133 unmodified lines | ||
| 134 | 134 | static DEFINE_IDR(vduse_idr); |
| 135 | 135 | |
| 136 | 136 | static dev_t vduse_major; |
| 137 | −static struct class *vduse_class; | |
| 138 | 137 | static struct cdev vduse_ctrl_cdev; |
| 139 | 138 | static struct cdev vduse_cdev; |
| 140 | 139 | static struct workqueue_struct *vduse_irq_wq; |
| @@ -1528,6 +1527,16 @@ static const struct kobj_type vq_type = { · 1387 unmodified lines | ||
| 1528 | 1527 | .default_groups = vq_groups, |
| 1529 | 1528 | }; |
| 1530 | 1529 | |
| 1530 | +static char *vduse_devnode(const struct device *dev, umode_t *mode) | |
| 1531 | +{ | |
| 1532 | + return kasprintf(GFP_KERNEL, "vduse/%s", dev_name(dev)); | |
| 1533 | +} | |
| 1534 | + | |
| 1535 | +static const struct class vduse_class = { | |
| 1536 | + .name = "vduse", | |
| 1537 | + .devnode = vduse_devnode, | |
| 1538 | +}; | |
| 1539 | + | |
| 1531 | 1540 | static void vduse_dev_deinit_vqs(struct vduse_dev *dev) |
| 1532 | 1541 | { |
| 1533 | 1542 | int i; |
| @@ -1638,7 +1647,7 @@ static int vduse_destroy_dev(char *name) · 104 unmodified lines | ||
| 1638 | 1647 | mutex_unlock(&dev->lock); |
| 1639 | 1648 | |
| 1640 | 1649 | vduse_dev_reset(dev); |
| 1641 | − device_destroy(vduse_class, MKDEV(MAJOR(vduse_major), dev->minor)); | |
| 1650 | + device_destroy(&vduse_class, MKDEV(MAJOR(vduse_major), dev->minor)); | |
| 1642 | 1651 | idr_remove(&vduse_idr, dev->minor); |
| 1643 | 1652 | kvfree(dev->config); |
| 1644 | 1653 | vduse_dev_deinit_vqs(dev); |
| @@ -1805,7 +1814,7 @@ static int vduse_create_dev(struct vduse_dev_config *config, · 160 unmodified lines | ||
| 1805 | 1814 | |
| 1806 | 1815 | dev->minor = ret; |
| 1807 | 1816 | dev->msg_timeout = VDUSE_MSG_DEFAULT_TIMEOUT; |
| 1808 | − dev->dev = device_create_with_groups(vduse_class, NULL, | |
| 1817 | + dev->dev = device_create_with_groups(&vduse_class, NULL, | |
| 1809 | 1818 | MKDEV(MAJOR(vduse_major), dev->minor), |
| 1810 | 1819 | dev, vduse_dev_groups, "%s", config->name); |
| 1811 | 1820 | if (IS_ERR(dev->dev)) { |
| @@ -1821,7 +1830,7 @@ static int vduse_create_dev(struct vduse_dev_config *config, · 9 unmodified lines | ||
| 1821 | 1830 | |
| 1822 | 1831 | return 0; |
| 1823 | 1832 | err_vqs: |
| 1824 | − device_destroy(vduse_class, MKDEV(MAJOR(vduse_major), dev->minor)); | |
| 1833 | + device_destroy(&vduse_class, MKDEV(MAJOR(vduse_major), dev->minor)); | |
| 1825 | 1834 | err_dev: |
| 1826 | 1835 | idr_remove(&vduse_idr, dev->minor); |
| 1827 | 1836 | err_idr: |
| @@ -1934,11 +1943,6 @@ static const struct file_operations vduse_ctrl_fops = { · 106 unmodified lines | ||
| 1934 | 1943 | .llseek = noop_llseek, |
| 1935 | 1944 | }; |
| 1936 | 1945 | |
| 1937 | −static char *vduse_devnode(const struct device *dev, umode_t *mode) | |
| 1938 | −{ | |
| 1939 | − return kasprintf(GFP_KERNEL, "vduse/%s", dev_name(dev)); | |
| 1940 | −} | |
| 1941 | − | |
| 1942 | 1946 | struct vduse_mgmt_dev { |
| 1943 | 1947 | struct vdpa_mgmt_dev mgmt_dev; |
| 1944 | 1948 | struct device dev; |
| @@ -2082,11 +2086,9 @@ static int vduse_init(void) · 137 unmodified lines | ||
| 2082 | 2086 | int ret; |
| 2083 | 2087 | struct device *dev; |
| 2084 | 2088 | |
| 2085 | − vduse_class = class_create("vduse"); | |
| 2086 | − if (IS_ERR(vduse_class)) | |
| 2087 | − return PTR_ERR(vduse_class); | |
| 2088 | − | |
| 2089 | − vduse_class->devnode = vduse_devnode; | |
| 2089 | + ret = class_register(&vduse_class); | |
| 2090 | + if (ret) | |
| 2091 | + return ret; | |
| 2090 | 2092 | |
| 2091 | 2093 | ret = alloc_chrdev_region(&vduse_major, 0, VDUSE_DEV_MAX, "vduse"); |
| 2092 | 2094 | if (ret) |
| @@ -2099,7 +2101,7 @@ static int vduse_init(void) · 6 unmodified lines | ||
| 2099 | 2101 | if (ret) |
| 2100 | 2102 | goto err_ctrl_cdev; |
| 2101 | 2103 | |
| 2102 | − dev = device_create(vduse_class, NULL, vduse_major, NULL, "control"); | |
| 2104 | + dev = device_create(&vduse_class, NULL, vduse_major, NULL, "control"); | |
| 2103 | 2105 | if (IS_ERR(dev)) { |
| 2104 | 2106 | ret = PTR_ERR(dev); |
| 2105 | 2107 | goto err_device; |
| @@ -2141,13 +2143,13 @@ err_bound_wq: · 35 unmodified lines | ||
| 2141 | 2143 | err_wq: |
| 2142 | 2144 | cdev_del(&vduse_cdev); |
| 2143 | 2145 | err_cdev: |
| 2144 | − device_destroy(vduse_class, vduse_major); | |
| 2146 | + device_destroy(&vduse_class, vduse_major); | |
| 2145 | 2147 | err_device: |
| 2146 | 2148 | cdev_del(&vduse_ctrl_cdev); |
| 2147 | 2149 | err_ctrl_cdev: |
| 2148 | 2150 | unregister_chrdev_region(vduse_major, VDUSE_DEV_MAX); |
| 2149 | 2151 | err_chardev_region: |
| 2150 | − class_destroy(vduse_class); | |
| 2152 | + class_unregister(&vduse_class); | |
| 2151 | 2153 | return ret; |
| 2152 | 2154 | } |
| 2153 | 2155 | module_init(vduse_init); |
| @@ -2159,10 +2161,10 @@ static void vduse_exit(void) · 5 unmodified lines | ||
| 2159 | 2161 | destroy_workqueue(vduse_irq_bound_wq); |
| 2160 | 2162 | destroy_workqueue(vduse_irq_wq); |
| 2161 | 2163 | cdev_del(&vduse_cdev); |
| 2162 | − device_destroy(vduse_class, vduse_major); | |
| 2164 | + device_destroy(&vduse_class, vduse_major); | |
| 2163 | 2165 | cdev_del(&vduse_ctrl_cdev); |
| 2164 | 2166 | unregister_chrdev_region(vduse_major, VDUSE_DEV_MAX); |
| 2165 | − class_destroy(vduse_class); | |
| 2167 | + class_unregister(&vduse_class); | |
| 2166 | 2168 | } |
| 2167 | 2169 | module_exit(vduse_exit); |
| 2168 | 2170 | |
| @@ -1158,7 +1158,7 @@ vhost_scsi_handle_vq(struct vhost_scsi *vs, struct vhost_virtqueue *vq) · 1157 unmodified lines | ||
| 1158 | 1158 | /* |
| 1159 | 1159 | * Set prot_iter to data_iter and truncate it to |
| 1160 | 1160 | * prot_bytes, and advance data_iter past any |
| 1161 | − * preceeding prot_bytes that may be present. | |
| 1161 | + * preceding prot_bytes that may be present. | |
| 1162 | 1162 | * |
| 1163 | 1163 | * Also fix up the exp_data_len to reflect only the |
| 1164 | 1164 | * actual data payload length. |
| @@ -131,6 +131,15 @@ static struct vhost_vdpa_as *vhost_vdpa_find_alloc_as(struct vhost_vdpa *v, · 130 unmodified lines | ||
| 131 | 131 | return vhost_vdpa_alloc_as(v, asid); |
| 132 | 132 | } |
| 133 | 133 | |
| 134 | +static void vhost_vdpa_reset_map(struct vhost_vdpa *v, u32 asid) | |
| 135 | +{ | |
| 136 | + struct vdpa_device *vdpa = v->vdpa; | |
| 137 | + const struct vdpa_config_ops *ops = vdpa->config; | |
| 138 | + | |
| 139 | + if (ops->reset_map) | |
| 140 | + ops->reset_map(vdpa, asid); | |
| 141 | +} | |
| 142 | + | |
| 134 | 143 | static int vhost_vdpa_remove_as(struct vhost_vdpa *v, u32 asid) |
| 135 | 144 | { |
| 136 | 145 | struct vhost_vdpa_as *as = asid_to_as(v, asid); |
| @@ -140,6 +149,14 @@ static int vhost_vdpa_remove_as(struct vhost_vdpa *v, u32 asid) · 3 unmodified lines | ||
| 140 | 149 | |
| 141 | 150 | hlist_del(&as->hash_link); |
| 142 | 151 | vhost_vdpa_iotlb_unmap(v, &as->iotlb, 0ULL, 0ULL - 1, asid); |
| 152 | + /* | |
| 153 | + * Devices with vendor specific IOMMU may need to restore | |
| 154 | + * iotlb to the initial or default state, which cannot be | |
| 155 | + * cleaned up in the all range unmap call above. Give them | |
| 156 | + * a chance to clean up or reset the map to the desired | |
| 157 | + * state. | |
| 158 | + */ | |
| 159 | + vhost_vdpa_reset_map(v, asid); | |
| 143 | 160 | kfree(as); |
| 144 | 161 | |
| 145 | 162 | return 0; |
| @@ -210,13 +227,24 @@ static void vhost_vdpa_unsetup_vq_irq(struct vhost_vdpa *v, u16 qid) · 64 unmodified lines | ||
| 210 | 227 | irq_bypass_unregister_producer(&vq->call_ctx.producer); |
| 211 | 228 | } |
| 212 | 229 | |
| 213 | −static int vhost_vdpa_reset(struct vhost_vdpa *v) | |
| 230 | +static int _compat_vdpa_reset(struct vhost_vdpa *v) | |
| 214 | 231 | { |
| 215 | 232 | struct vdpa_device *vdpa = v->vdpa; |
| 233 | + u32 flags = 0; | |
| 216 | 234 | |
| 217 | − v->in_batch = 0; | |
| 235 | + if (v->vdev.vqs) { | |
| 236 | + flags |= !vhost_backend_has_feature(v->vdev.vqs[0], | |
| 237 | + VHOST_BACKEND_F_IOTLB_PERSIST) ? | |
| 238 | + VDPA_RESET_F_CLEAN_MAP : 0; | |
| 239 | + } | |
| 218 | 240 | |
| 219 | − return vdpa_reset(vdpa); | |
| 241 | + return vdpa_reset(vdpa, flags); | |
| 242 | +} | |
| 243 | + | |
| 244 | +static int vhost_vdpa_reset(struct vhost_vdpa *v) | |
| 245 | +{ | |
| 246 | + v->in_batch = 0; | |
| 247 | + return _compat_vdpa_reset(v); | |
| 220 | 248 | } |
| 221 | 249 | |
| 222 | 250 | static long vhost_vdpa_bind_mm(struct vhost_vdpa *v) |
| @@ -295,7 +323,7 @@ static long vhost_vdpa_set_status(struct vhost_vdpa *v, u8 __user *statusp) · 72 unmodified lines | ||
| 295 | 323 | vhost_vdpa_unsetup_vq_irq(v, i); |
| 296 | 324 | |
| 297 | 325 | if (status == 0) { |
| 298 | − ret = vdpa_reset(vdpa); | |
| 326 | + ret = _compat_vdpa_reset(v); | |
| 299 | 327 | if (ret) |
| 300 | 328 | return ret; |
| 301 | 329 | } else |
| @@ -389,6 +417,14 @@ static bool vhost_vdpa_can_resume(const struct vhost_vdpa *v) · 87 unmodified lines | ||
| 389 | 417 | return ops->resume; |
| 390 | 418 | } |
| 391 | 419 | |
| 420 | +static bool vhost_vdpa_has_desc_group(const struct vhost_vdpa *v) | |
| 421 | +{ | |
| 422 | + struct vdpa_device *vdpa = v->vdpa; | |
| 423 | + const struct vdpa_config_ops *ops = vdpa->config; | |
| 424 | + | |
| 425 | + return ops->get_vq_desc_group; | |
| 426 | +} | |
| 427 | + | |
| 392 | 428 | static long vhost_vdpa_get_features(struct vhost_vdpa *v, u64 __user *featurep) |
| 393 | 429 | { |
| 394 | 430 | struct vdpa_device *vdpa = v->vdpa; |
| @@ -414,6 +450,15 @@ static u64 vhost_vdpa_get_backend_features(const struct vhost_vdpa *v) · 19 unmodified lines | ||
| 414 | 450 | return ops->get_backend_features(vdpa); |
| 415 | 451 | } |
| 416 | 452 | |
| 453 | +static bool vhost_vdpa_has_persistent_map(const struct vhost_vdpa *v) | |
| 454 | +{ | |
| 455 | + struct vdpa_device *vdpa = v->vdpa; | |
| 456 | + const struct vdpa_config_ops *ops = vdpa->config; | |
| 457 | + | |
| 458 | + return (!ops->set_map && !ops->dma_map) || ops->reset_map || | |
| 459 | + vhost_vdpa_get_backend_features(v) & BIT_ULL(VHOST_BACKEND_F_IOTLB_PERSIST); | |
| 460 | +} | |
| 461 | + | |
| 417 | 462 | static long vhost_vdpa_set_features(struct vhost_vdpa *v, u64 __user *featurep) |
| 418 | 463 | { |
| 419 | 464 | struct vdpa_device *vdpa = v->vdpa; |
| @@ -605,6 +650,16 @@ static long vhost_vdpa_vring_ioctl(struct vhost_vdpa *v, unsigned int cmd, · 185 unmodified lines | ||
| 605 | 650 | else if (copy_to_user(argp, &s, sizeof(s))) |
| 606 | 651 | return -EFAULT; |
| 607 | 652 | return 0; |
| 653 | + case VHOST_VDPA_GET_VRING_DESC_GROUP: | |
| 654 | + if (!vhost_vdpa_has_desc_group(v)) | |
| 655 | + return -EOPNOTSUPP; | |
| 656 | + s.index = idx; | |
| 657 | + s.num = ops->get_vq_desc_group(vdpa, idx); | |
| 658 | + if (s.num >= vdpa->ngroups) | |
| 659 | + return -EIO; | |
| 660 | + else if (copy_to_user(argp, &s, sizeof(s))) | |
| 661 | + return -EFAULT; | |
| 662 | + return 0; | |
| 608 | 663 | case VHOST_VDPA_SET_GROUP_ASID: |
| 609 | 664 | if (copy_from_user(&s, argp, sizeof(s))) |
| 610 | 665 | return -EFAULT; |
| @@ -690,6 +745,8 @@ static long vhost_vdpa_unlocked_ioctl(struct file *filep, · 79 unmodified lines | ||
| 690 | 745 | if (copy_from_user(&features, featurep, sizeof(features))) |
| 691 | 746 | return -EFAULT; |
| 692 | 747 | if (features & ~(VHOST_VDPA_BACKEND_FEATURES | |
| 748 | + BIT_ULL(VHOST_BACKEND_F_DESC_ASID) | | |
| 749 | + BIT_ULL(VHOST_BACKEND_F_IOTLB_PERSIST) | | |
| 693 | 750 | BIT_ULL(VHOST_BACKEND_F_SUSPEND) | |
| 694 | 751 | BIT_ULL(VHOST_BACKEND_F_RESUME) | |
| 695 | 752 | BIT_ULL(VHOST_BACKEND_F_ENABLE_AFTER_DRIVER_OK))) |
| @@ -700,6 +757,15 @@ static long vhost_vdpa_unlocked_ioctl(struct file *filep, · 4 unmodified lines | ||
| 700 | 757 | if ((features & BIT_ULL(VHOST_BACKEND_F_RESUME)) && |
| 701 | 758 | !vhost_vdpa_can_resume(v)) |
| 702 | 759 | return -EOPNOTSUPP; |
| 760 | + if ((features & BIT_ULL(VHOST_BACKEND_F_DESC_ASID)) && | |
| 761 | + !(features & BIT_ULL(VHOST_BACKEND_F_IOTLB_ASID))) | |
| 762 | + return -EINVAL; | |
| 763 | + if ((features & BIT_ULL(VHOST_BACKEND_F_DESC_ASID)) && | |
| 764 | + !vhost_vdpa_has_desc_group(v)) | |
| 765 | + return -EOPNOTSUPP; | |
| 766 | + if ((features & BIT_ULL(VHOST_BACKEND_F_IOTLB_PERSIST)) && | |
| 767 | + !vhost_vdpa_has_persistent_map(v)) | |
| 768 | + return -EOPNOTSUPP; | |
| 703 | 769 | vhost_set_backend_features(&v->vdev, features); |
| 704 | 770 | return 0; |
| 705 | 771 | } |
| @@ -753,6 +819,10 @@ static long vhost_vdpa_unlocked_ioctl(struct file *filep, · 47 unmodified lines | ||
| 753 | 819 | features |= BIT_ULL(VHOST_BACKEND_F_SUSPEND); |
| 754 | 820 | if (vhost_vdpa_can_resume(v)) |
| 755 | 821 | features |= BIT_ULL(VHOST_BACKEND_F_RESUME); |
| 822 | + if (vhost_vdpa_has_desc_group(v)) | |
| 823 | + features |= BIT_ULL(VHOST_BACKEND_F_DESC_ASID); | |
| 824 | + if (vhost_vdpa_has_persistent_map(v)) | |
| 825 | + features |= BIT_ULL(VHOST_BACKEND_F_IOTLB_PERSIST); | |
| 756 | 826 | features |= vhost_vdpa_get_backend_features(v); |
| 757 | 827 | if (copy_to_user(featurep, &features, sizeof(features))) |
| 758 | 828 | r = -EFAULT; |
| @@ -1285,6 +1355,7 @@ static void vhost_vdpa_cleanup(struct vhost_vdpa *v) · 526 unmodified lines | ||
| 1285 | 1355 | vhost_vdpa_free_domain(v); |
| 1286 | 1356 | vhost_dev_cleanup(&v->vdev); |
| 1287 | 1357 | kfree(v->vdev.vqs); |
| 1358 | + v->vdev.vqs = NULL; | |
| 1288 | 1359 | } |
| 1289 | 1360 | |
| 1290 | 1361 | static int vhost_vdpa_open(struct inode *inode, struct file *filep) |
| @@ -745,7 +745,7 @@ static void report_free_page_func(struct work_struct *work) · 744 unmodified lines | ||
| 745 | 745 | * 2) update the host about the old page removed from vb->pages list; |
| 746 | 746 | * |
| 747 | 747 | * This function preforms the balloon page migration task. |
| 748 | − * Called through balloon_mapping->a_ops->migratepage | |
| 748 | + * Called through movable_operations->migrate_page | |
| 749 | 749 | */ |
| 750 | 750 | static int virtballoon_migratepage(struct balloon_dev_info *vb_dev_info, |
| 751 | 751 | struct page *newpage, struct page *page, enum migrate_mode mode) |
| @@ -39,6 +39,39 @@ static void vp_transport_features(struct virtio_device *vdev, u64 features) · 38 unmodified lines | ||
| 39 | 39 | __virtio_set_bit(vdev, VIRTIO_F_RING_RESET); |
| 40 | 40 | } |
| 41 | 41 | |
| 42 | +static int __vp_check_common_size_one_feature(struct virtio_device *vdev, u32 fbit, | |
| 43 | + u32 offset, const char *fname) | |
| 44 | +{ | |
| 45 | + struct virtio_pci_device *vp_dev = to_vp_device(vdev); | |
| 46 | + | |
| 47 | + if (!__virtio_test_bit(vdev, fbit)) | |
| 48 | + return 0; | |
| 49 | + | |
| 50 | + if (likely(vp_dev->mdev.common_len >= offset)) | |
| 51 | + return 0; | |
| 52 | + | |
| 53 | + dev_err(&vdev->dev, | |
| 54 | + "virtio: common cfg size(%zu) does not match the feature %s\n", | |
| 55 | + vp_dev->mdev.common_len, fname); | |
| 56 | + | |
| 57 | + return -EINVAL; | |
| 58 | +} | |
| 59 | + | |
| 60 | +#define vp_check_common_size_one_feature(vdev, fbit, field) \ | |
| 61 | + __vp_check_common_size_one_feature(vdev, fbit, \ | |
| 62 | + offsetofend(struct virtio_pci_modern_common_cfg, field), #fbit) | |
| 63 | + | |
| 64 | +static int vp_check_common_size(struct virtio_device *vdev) | |
| 65 | +{ | |
| 66 | + if (vp_check_common_size_one_feature(vdev, VIRTIO_F_NOTIF_CONFIG_DATA, queue_notify_data)) | |
| 67 | + return -EINVAL; | |
| 68 | + | |
| 69 | + if (vp_check_common_size_one_feature(vdev, VIRTIO_F_RING_RESET, queue_reset)) | |
| 70 | + return -EINVAL; | |
| 71 | + | |
| 72 | + return 0; | |
| 73 | +} | |
| 74 | + | |
| 42 | 75 | /* virtio config->finalize_features() implementation */ |
| 43 | 76 | static int vp_finalize_features(struct virtio_device *vdev) |
| 44 | 77 | { |
| @@ -57,6 +90,9 @@ static int vp_finalize_features(struct virtio_device *vdev) · 12 unmodified lines | ||
| 57 | 90 | return -EINVAL; |
| 58 | 91 | } |
| 59 | 92 | |
| 93 | + if (vp_check_common_size(vdev)) | |
| 94 | + return -EINVAL; | |
| 95 | + | |
| 60 | 96 | vp_modern_set_features(&vp_dev->mdev, vdev->features); |
| 61 | 97 | |
| 62 | 98 | return 0; |
| @@ -203,6 +203,10 @@ static inline void check_offsets(void) · 202 unmodified lines | ||
| 203 | 203 | offsetof(struct virtio_pci_common_cfg, queue_used_lo)); |
| 204 | 204 | BUILD_BUG_ON(VIRTIO_PCI_COMMON_Q_USEDHI != |
| 205 | 205 | offsetof(struct virtio_pci_common_cfg, queue_used_hi)); |
| 206 | + BUILD_BUG_ON(VIRTIO_PCI_COMMON_Q_NDATA != | |
| 207 | + offsetof(struct virtio_pci_modern_common_cfg, queue_notify_data)); | |
| 208 | + BUILD_BUG_ON(VIRTIO_PCI_COMMON_Q_RESET != | |
| 209 | + offsetof(struct virtio_pci_modern_common_cfg, queue_reset)); | |
| 206 | 210 | } |
| 207 | 211 | |
| 208 | 212 | /* |
| @@ -292,7 +296,7 @@ int vp_modern_probe(struct virtio_pci_modern_device *mdev) · 83 unmodified lines | ||
| 292 | 296 | mdev->common = vp_modern_map_capability(mdev, common, |
| 293 | 297 | sizeof(struct virtio_pci_common_cfg), 4, |
| 294 | 298 | 0, sizeof(struct virtio_pci_modern_common_cfg), |
| 295 | − NULL, NULL); | |
| 299 | + &mdev->common_len, NULL); | |
| 296 | 300 | if (!mdev->common) |
| 297 | 301 | goto err_map_common; |
| 298 | 302 | mdev->isr = vp_modern_map_capability(mdev, isr, sizeof(u8), 1, |
| @@ -100,7 +100,7 @@ static void virtio_vdpa_reset(struct virtio_device *vdev) · 99 unmodified lines | ||
| 100 | 100 | { |
| 101 | 101 | struct vdpa_device *vdpa = vd_get_vdpa(vdev); |
| 102 | 102 | |
| 103 | − vdpa_reset(vdpa); | |
| 103 | + vdpa_reset(vdpa, 0); | |
| 104 | 104 | } |
| 105 | 105 | |
| 106 | 106 | static bool virtio_vdpa_notify(struct virtqueue *vq) |
| @@ -1232,7 +1232,13 @@ struct mlx5_ifc_virtio_emulation_cap_bits { · 1231 unmodified lines | ||
| 1232 | 1232 | u8 max_emulated_devices[0x8]; |
| 1233 | 1233 | u8 max_num_virtio_queues[0x18]; |
| 1234 | 1234 | |
| 1235 | − u8 reserved_at_a0[0x60]; | |
| 1235 | + u8 reserved_at_a0[0x20]; | |
| 1236 | + | |
| 1237 | + u8 reserved_at_c0[0x13]; | |
| 1238 | + u8 desc_group_mkey_supported[0x1]; | |
| 1239 | + u8 reserved_at_d4[0xc]; | |
| 1240 | + | |
| 1241 | + u8 reserved_at_e0[0x20]; | |
| 1236 | 1242 | |
| 1237 | 1243 | u8 umem_1_buffer_param_a[0x20]; |
| 1238 | 1244 | |
| @@ -74,7 +74,11 @@ struct mlx5_ifc_virtio_q_bits { · 73 unmodified lines | ||
| 74 | 74 | u8 reserved_at_320[0x8]; |
| 75 | 75 | u8 pd[0x18]; |
| 76 | 76 | |
| 77 | − u8 reserved_at_340[0xc0]; | |
| 77 | + u8 reserved_at_340[0x20]; | |
| 78 | + | |
| 79 | + u8 desc_group_mkey[0x20]; | |
| 80 | + | |
| 81 | + u8 reserved_at_380[0x80]; | |
| 78 | 82 | }; |
| 79 | 83 | |
| 80 | 84 | struct mlx5_ifc_virtio_net_q_object_bits { |
| @@ -141,6 +145,7 @@ enum { · 60 unmodified lines | ||
| 141 | 145 | MLX5_VIRTQ_MODIFY_MASK_STATE = (u64)1 << 0, |
| 142 | 146 | MLX5_VIRTQ_MODIFY_MASK_DIRTY_BITMAP_PARAMS = (u64)1 << 3, |
| 143 | 147 | MLX5_VIRTQ_MODIFY_MASK_DIRTY_BITMAP_DUMP_ENABLE = (u64)1 << 4, |
| 148 | + MLX5_VIRTQ_MODIFY_MASK_DESC_GROUP_MKEY = (u64)1 << 14, | |
| 144 | 149 | }; |
| 145 | 150 | |
| 146 | 151 | enum { |
| @@ -204,6 +204,16 @@ struct vdpa_map_file { · 203 unmodified lines | ||
| 204 | 204 | * @vdev: vdpa device |
| 205 | 205 | * @idx: virtqueue index |
| 206 | 206 | * Returns u32: group id for this virtqueue |
| 207 | + * @get_vq_desc_group: Get the group id for the descriptor table of | |
| 208 | + * a specific virtqueue (optional) | |
| 209 | + * @vdev: vdpa device | |
| 210 | + * @idx: virtqueue index | |
| 211 | + * Returns u32: group id for the descriptor table | |
| 212 | + * portion of this virtqueue. Could be different | |
| 213 | + * than the one from @get_vq_group, in which case | |
| 214 | + * the access to the descriptor table can be | |
| 215 | + * confined to a separate asid, isolating from | |
| 216 | + * the virtqueue's buffer address access. | |
| 207 | 217 | * @get_device_features: Get virtio features supported by the device |
| 208 | 218 | * @vdev: vdpa device |
| 209 | 219 | * Returns the virtio features support by the |
| @@ -242,6 +252,17 @@ struct vdpa_map_file { · 32 unmodified lines | ||
| 242 | 252 | * @reset: Reset device |
| 243 | 253 | * @vdev: vdpa device |
| 244 | 254 | * Returns integer: success (0) or error (< 0) |
| 255 | + * @compat_reset: Reset device with compatibility quirks to | |
| 256 | + * accommodate older userspace. Only needed by | |
| 257 | + * parent driver which used to have bogus reset | |
| 258 | + * behaviour, and has to maintain such behaviour | |
| 259 | + * for compatibility with older userspace. | |
| 260 | + * Historically compliant driver only has to | |
| 261 | + * implement .reset, Historically non-compliant | |
| 262 | + * driver should implement both. | |
| 263 | + * @vdev: vdpa device | |
| 264 | + * @flags: compatibility quirks for reset | |
| 265 | + * Returns integer: success (0) or error (< 0) | |
| 245 | 266 | * @suspend: Suspend the device (optional) |
| 246 | 267 | * @vdev: vdpa device |
| 247 | 268 | * Returns integer: success (0) or error (< 0) |
| @@ -317,6 +338,15 @@ struct vdpa_map_file { · 69 unmodified lines | ||
| 317 | 338 | * @iova: iova to be unmapped |
| 318 | 339 | * @size: size of the area |
| 319 | 340 | * Returns integer: success (0) or error (< 0) |
| 341 | + * @reset_map: Reset device memory mapping to the default | |
| 342 | + * state (optional) | |
| 343 | + * Needed for devices that are using device | |
| 344 | + * specific DMA translation and prefer mapping | |
| 345 | + * to be decoupled from the virtio life cycle, | |
| 346 | + * i.e. device .reset op does not reset mapping | |
| 347 | + * @vdev: vdpa device | |
| 348 | + * @asid: address space identifier | |
| 349 | + * Returns integer: success (0) or error (< 0) | |
| 320 | 350 | * @get_vq_dma_dev: Get the dma device for a specific |
| 321 | 351 | * virtqueue (optional) |
| 322 | 352 | * @vdev: vdpa device |
| @@ -360,6 +390,7 @@ struct vdpa_config_ops { · 37 unmodified lines | ||
| 360 | 390 | /* Device ops */ |
| 361 | 391 | u32 (*get_vq_align)(struct vdpa_device *vdev); |
| 362 | 392 | u32 (*get_vq_group)(struct vdpa_device *vdev, u16 idx); |
| 393 | + u32 (*get_vq_desc_group)(struct vdpa_device *vdev, u16 idx); | |
| 363 | 394 | u64 (*get_device_features)(struct vdpa_device *vdev); |
| 364 | 395 | u64 (*get_backend_features)(const struct vdpa_device *vdev); |
| 365 | 396 | int (*set_driver_features)(struct vdpa_device *vdev, u64 features); |
| @@ -373,6 +404,8 @@ struct vdpa_config_ops { · 7 unmodified lines | ||
| 373 | 404 | u8 (*get_status)(struct vdpa_device *vdev); |
| 374 | 405 | void (*set_status)(struct vdpa_device *vdev, u8 status); |
| 375 | 406 | int (*reset)(struct vdpa_device *vdev); |
| 407 | + int (*compat_reset)(struct vdpa_device *vdev, u32 flags); | |
| 408 | +#define VDPA_RESET_F_CLEAN_MAP 1 | |
| 376 | 409 | int (*suspend)(struct vdpa_device *vdev); |
| 377 | 410 | int (*resume)(struct vdpa_device *vdev); |
| 378 | 411 | size_t (*get_config_size)(struct vdpa_device *vdev); |
| @@ -394,6 +427,7 @@ struct vdpa_config_ops { · 15 unmodified lines | ||
| 394 | 427 | u64 iova, u64 size, u64 pa, u32 perm, void *opaque); |
| 395 | 428 | int (*dma_unmap)(struct vdpa_device *vdev, unsigned int asid, |
| 396 | 429 | u64 iova, u64 size); |
| 430 | + int (*reset_map)(struct vdpa_device *vdev, unsigned int asid); | |
| 397 | 431 | int (*set_group_asid)(struct vdpa_device *vdev, unsigned int group, |
| 398 | 432 | unsigned int asid); |
| 399 | 433 | struct device *(*get_vq_dma_dev)(struct vdpa_device *vdev, u16 idx); |
| @@ -485,14 +519,17 @@ static inline struct device *vdpa_get_dma_dev(struct vdpa_device *vdev) · 85 unmodified lines | ||
| 485 | 519 | return vdev->dma_dev; |
| 486 | 520 | } |
| 487 | 521 | |
| 488 | −static inline int vdpa_reset(struct vdpa_device *vdev) | |
| 522 | +static inline int vdpa_reset(struct vdpa_device *vdev, u32 flags) | |
| 489 | 523 | { |
| 490 | 524 | const struct vdpa_config_ops *ops = vdev->config; |
| 491 | 525 | int ret; |
| 492 | 526 | |
| 493 | 527 | down_write(&vdev->cf_lock); |
| 494 | 528 | vdev->features_valid = false; |
| 495 | − ret = ops->reset(vdev); | |
| 529 | + if (ops->compat_reset && flags) | |
| 530 | + ret = ops->compat_reset(vdev, flags); | |
| 531 | + else | |
| 532 | + ret = ops->reset(vdev); | |
| 496 | 533 | up_write(&vdev->cf_lock); |
| 497 | 534 | return ret; |
| 498 | 535 | } |
| @@ -12,37 +12,48 @@ struct virtio_pci_modern_common_cfg { · 11 unmodified lines | ||
| 12 | 12 | __le16 queue_reset; /* read-write */ |
| 13 | 13 | }; |
| 14 | 14 | |
| 15 | +/** | |
| 16 | + * struct virtio_pci_modern_device - info for modern PCI virtio | |
| 17 | + * @pci_dev: Ptr to the PCI device struct | |
| 18 | + * @common: Position of the common capability in the PCI config | |
| 19 | + * @device: Device-specific data (non-legacy mode) | |
| 20 | + * @notify_base: Base of vq notifications (non-legacy mode) | |
| 21 | + * @notify_pa: Physical base of vq notifications | |
| 22 | + * @isr: Where to read and clear interrupt | |
| 23 | + * @notify_len: So we can sanity-check accesses | |
| 24 | + * @device_len: So we can sanity-check accesses | |
| 25 | + * @notify_map_cap: Capability for when we need to map notifications per-vq | |
| 26 | + * @notify_offset_multiplier: Multiply queue_notify_off by this value | |
| 27 | + * (non-legacy mode). | |
| 28 | + * @modern_bars: Bitmask of BARs | |
| 29 | + * @id: Device and vendor id | |
| 30 | + * @device_id_check: Callback defined before vp_modern_probe() to be used to | |
| 31 | + * verify the PCI device is a vendor's expected device rather | |
| 32 | + * than the standard virtio PCI device | |
| 33 | + * Returns the found device id or ERRNO | |
| 34 | + * @dma_mask: Optional mask instead of the traditional DMA_BIT_MASK(64), | |
| 35 | + * for vendor devices with DMA space address limitations | |
| 36 | + */ | |
| 15 | 37 | struct virtio_pci_modern_device { |
| 16 | 38 | struct pci_dev *pci_dev; |
| 17 | 39 | |
| 18 | 40 | struct virtio_pci_common_cfg __iomem *common; |
| 19 | − /* Device-specific data (non-legacy mode) */ | |
| 20 | 41 | void __iomem *device; |
| 21 | − /* Base of vq notifications (non-legacy mode). */ | |
| 22 | 42 | void __iomem *notify_base; |
| 23 | − /* Physical base of vq notifications */ | |
| 24 | 43 | resource_size_t notify_pa; |
| 25 | − /* Where to read and clear interrupt */ | |
| 26 | 44 | u8 __iomem *isr; |
| 27 | 45 | |
| 28 | − /* So we can sanity-check accesses. */ | |
| 29 | 46 | size_t notify_len; |
| 30 | 47 | size_t device_len; |
| 48 | + size_t common_len; | |
| 31 | 49 | |
| 32 | − /* Capability for when we need to map notifications per-vq. */ | |
| 33 | 50 | int notify_map_cap; |
| 34 | 51 | |
| 35 | − /* Multiply queue_notify_off by this value. (non-legacy mode). */ | |
| 36 | 52 | u32 notify_offset_multiplier; |
| 37 | − | |
| 38 | 53 | int modern_bars; |
| 39 | − | |
| 40 | 54 | struct virtio_device_id id; |
| 41 | 55 | |
| 42 | − /* optional check for vendor virtio device, returns dev_id or -ERRNO */ | |
| 43 | 56 | int (*device_id_check)(struct pci_dev *pdev); |
| 44 | − | |
| 45 | − /* optional mask for devices with limited DMA space */ | |
| 46 | 57 | u64 dma_mask; |
| 47 | 58 | }; |
| 48 | 59 | |
| @@ -219,4 +219,12 @@ · 218 unmodified lines | ||
| 219 | 219 | */ |
| 220 | 220 | #define VHOST_VDPA_RESUME _IO(VHOST_VIRTIO, 0x7E) |
| 221 | 221 | |
| 222 | +/* Get the group for the descriptor table including driver & device areas | |
| 223 | + * of a virtqueue: read index, write group in num. | |
| 224 | + * The virtqueue index is stored in the index field of vhost_vring_state. | |
| 225 | + * The group ID of the descriptor table for this specific virtqueue | |
| 226 | + * is returned via num field of vhost_vring_state. | |
| 227 | + */ | |
| 228 | +#define VHOST_VDPA_GET_VRING_DESC_GROUP _IOWR(VHOST_VIRTIO, 0x7F, \ | |
| 229 | + struct vhost_vring_state) | |
| 222 | 230 | #endif |
| @@ -185,5 +185,12 @@ struct vhost_vdpa_iova_range { · 184 unmodified lines | ||
| 185 | 185 | * DRIVER_OK |
| 186 | 186 | */ |
| 187 | 187 | #define VHOST_BACKEND_F_ENABLE_AFTER_DRIVER_OK 0x6 |
| 188 | +/* Device may expose the virtqueue's descriptor area, driver area and | |
| 189 | + * device area to a different group for ASID binding than where its | |
| 190 | + * buffers may reside. Requires VHOST_BACKEND_F_IOTLB_ASID. | |
| 191 | + */ | |
| 192 | +#define VHOST_BACKEND_F_DESC_ASID 0x7 | |
| 193 | +/* IOTLB don't flush memory mapping across device reset */ | |
| 194 | +#define VHOST_BACKEND_F_IOTLB_PERSIST 0x8 | |
| 188 | 195 | |
| 189 | 196 | #endif |
| @@ -105,6 +105,11 @@ · 104 unmodified lines | ||
| 105 | 105 | */ |
| 106 | 106 | #define VIRTIO_F_NOTIFICATION_DATA 38 |
| 107 | 107 | |
| 108 | +/* This feature indicates that the driver uses the data provided by the device | |
| 109 | + * as a virtqueue identifier in available buffer notifications. | |
| 110 | + */ | |
| 111 | +#define VIRTIO_F_NOTIF_CONFIG_DATA 39 | |
| 112 | + | |
| 108 | 113 | /* |
| 109 | 114 | * This feature indicates that the driver can reset a queue individually. |
| 110 | 115 | */ |