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 | Date: March 2020 | 2 | Date: March 2020 |
| 3 | Contact: virtualization@lists.linux-foundation.org | 3 | Contact: virtualization@lists.linux-foundation.org |
| 4 | Description: | 4 | Description: |
| @@ -17,7 +17,7 @@ Description: · 12 unmodified lines | |||
| 17 | Writing a device name to this file will cause the kernel binds | 17 | Writing a device name to this file will cause the kernel binds |
| 18 | devices to a compatible driver. | 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 | disabled. | 21 | disabled. |
| 22 | 22 | ||
| 23 | What: /sys/bus/vdpa/drivers/.../bind | 23 | What: /sys/bus/vdpa/drivers/.../bind |
| @@ -13790,6 +13790,12 @@ F: drivers/infiniband/hw/mlx5/ · 13789 unmodified lines | |||
| 13790 | F: include/linux/mlx5/ | 13790 | F: include/linux/mlx5/ |
| 13791 | F: include/uapi/rdma/mlx5-abi.h | 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 | MELLANOX MLXCPLD I2C AND MUX DRIVER | 13799 | MELLANOX MLXCPLD I2C AND MUX DRIVER |
| 13794 | M: Vadim Pasternak <vadimp@nvidia.com> | 13800 | M: Vadim Pasternak <vadimp@nvidia.com> |
| 13795 | M: Michael Shych <michaelsh@nvidia.com> | 13801 | M: Michael Shych <michaelsh@nvidia.com> |
| @@ -1311,6 +1311,7 @@ static int virtblk_probe(struct virtio_device *vdev) · 1310 unmodified lines | |||
| 1311 | u16 min_io_size; | 1311 | u16 min_io_size; |
| 1312 | u8 physical_block_exp, alignment_offset; | 1312 | u8 physical_block_exp, alignment_offset; |
| 1313 | unsigned int queue_depth; | 1313 | unsigned int queue_depth; |
| 1314 | size_t max_dma_size; | ||
| 1314 | 1315 | ||
| 1315 | if (!vdev->config->get) { | 1316 | if (!vdev->config->get) { |
| 1316 | dev_err(&vdev->dev, "%s failure: config access disabled\n", | 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 | /* No real sector limit. */ | 1410 | /* No real sector limit. */ |
| 1410 | blk_queue_max_hw_sectors(q, UINT_MAX); | 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 | /* Host can optionally specify maximum segment size and number of | 1416 | /* Host can optionally specify maximum segment size and number of |
| 1415 | * segments. */ | 1417 | * segments. */ |
| @@ -31,11 +31,9 @@ struct mlx5_vdpa_mr { · 30 unmodified lines | |||
| 31 | struct list_head head; | 31 | struct list_head head; |
| 32 | unsigned long num_directs; | 32 | unsigned long num_directs; |
| 33 | unsigned long num_klms; | 33 | unsigned long num_klms; |
| 34 | /* state of dvq mr */ | ||
| 35 | bool initialized; | ||
| 36 | 34 | ||
| 37 | /* serialize mkey creation and destruction */ | 35 | struct vhost_iotlb *iotlb; |
| 38 | struct mutex mkey_mtx; | 36 | |
| 39 | bool user_mr; | 37 | bool user_mr; |
| 40 | }; | 38 | }; |
| 41 | 39 | ||
| @@ -74,11 +72,12 @@ struct mlx5_vdpa_wq_ent { · 32 unmodified lines | |||
| 74 | enum { | 72 | enum { |
| 75 | MLX5_VDPA_DATAVQ_GROUP, | 73 | MLX5_VDPA_DATAVQ_GROUP, |
| 76 | MLX5_VDPA_CVQ_GROUP, | 74 | MLX5_VDPA_CVQ_GROUP, |
| 75 | MLX5_VDPA_DATAVQ_DESC_GROUP, | ||
| 77 | MLX5_VDPA_NUMVQ_GROUPS | 76 | MLX5_VDPA_NUMVQ_GROUPS |
| 78 | }; | 77 | }; |
| 79 | 78 | ||
| 80 | enum { | 79 | enum { |
| 81 | MLX5_VDPA_NUM_AS = MLX5_VDPA_NUMVQ_GROUPS | 80 | MLX5_VDPA_NUM_AS = 2 |
| 82 | }; | 81 | }; |
| 83 | 82 | ||
| 84 | struct mlx5_vdpa_dev { | 83 | struct mlx5_vdpa_dev { |
| @@ -93,7 +92,9 @@ struct mlx5_vdpa_dev { · 8 unmodified lines | |||
| 93 | u16 max_idx; | 92 | u16 max_idx; |
| 94 | u32 generation; | 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 | struct mlx5_control_vq cvq; | 98 | struct mlx5_control_vq cvq; |
| 98 | struct workqueue_struct *wq; | 99 | struct workqueue_struct *wq; |
| 99 | unsigned int group2asid[MLX5_VDPA_NUMVQ_GROUPS]; | 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 | int mlx5_vdpa_create_mkey(struct mlx5_vdpa_dev *mvdev, u32 *mkey, u32 *in, | 115 | int mlx5_vdpa_create_mkey(struct mlx5_vdpa_dev *mvdev, u32 *mkey, u32 *in, |
| 115 | int inlen); | 116 | int inlen); |
| 116 | int mlx5_vdpa_destroy_mkey(struct mlx5_vdpa_dev *mvdev, u32 mkey); | 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 | struct mlx5_vdpa_mr *mlx5_vdpa_create_mr(struct mlx5_vdpa_dev *mvdev, |
| 118 | bool *change_map, unsigned int asid); | 119 | struct vhost_iotlb *iotlb); |
| 119 | int mlx5_vdpa_create_mr(struct mlx5_vdpa_dev *mvdev, struct vhost_iotlb *iotlb, | 120 | void mlx5_vdpa_destroy_mr_resources(struct mlx5_vdpa_dev *mvdev); |
| 120 | unsigned int asid); | 121 | void mlx5_vdpa_destroy_mr(struct mlx5_vdpa_dev *mvdev, |
| 121 | void mlx5_vdpa_destroy_mr(struct mlx5_vdpa_dev *mvdev); | 122 | struct mlx5_vdpa_mr *mr); |
| 122 | void mlx5_vdpa_destroy_mr_asid(struct mlx5_vdpa_dev *mvdev, unsigned int asid); | 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 | #define mlx5_vdpa_warn(__dev, format, ...) \ | 132 | #define mlx5_vdpa_warn(__dev, format, ...) \ |
| 125 | dev_warn((__dev)->mdev->device, "%s:%d:(pid %d) warning: " format, __func__, __LINE__, \ | 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 | sg_free_table(&mr->sg_head); | 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 | struct vhost_iotlb *iotlb) | 309 | struct vhost_iotlb *iotlb) |
| 306 | { | 310 | { |
| 307 | struct mlx5_vdpa_mr *mr = &mvdev->mr; | ||
| 308 | struct mlx5_vdpa_direct_mr *dmr; | 311 | struct mlx5_vdpa_direct_mr *dmr; |
| 309 | struct mlx5_vdpa_direct_mr *n; | 312 | struct mlx5_vdpa_direct_mr *n; |
| 310 | LIST_HEAD(tmp); | 313 | LIST_HEAD(tmp); |
| @@ -354,9 +357,10 @@ err_alloc: · 43 unmodified lines | |||
| 354 | * indirect memory key that provides access to the enitre address space given | 357 | * indirect memory key that provides access to the enitre address space given |
| 355 | * by iotlb. | 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 | struct mlx5_vdpa_direct_mr *dmr; | 364 | struct mlx5_vdpa_direct_mr *dmr; |
| 361 | struct mlx5_vdpa_direct_mr *n; | 365 | struct mlx5_vdpa_direct_mr *n; |
| 362 | struct vhost_iotlb_map *map; | 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 | LOG_MAX_KLM_SIZE); | 388 | LOG_MAX_KLM_SIZE); |
| 385 | mr->num_klms += nnuls; | 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 | if (err) | 392 | if (err) |
| 389 | goto err_chain; | 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 | pperm = map->perm; | 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 | if (err) | 401 | if (err) |
| 398 | goto err_chain; | 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 | mlx5_vdpa_destroy_mkey(mvdev, mr->mkey); | 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 | struct vhost_iotlb_map *map; | 459 | struct vhost_iotlb_map *map; |
| 456 | u64 start = 0, last = ULLONG_MAX; | 460 | u64 start = 0, last = ULLONG_MAX; |
| 457 | int err; | 461 | int err; |
| 458 | 462 | ||
| 463 | if (dst == src) | ||
| 464 | return -EINVAL; | ||
| 465 | |||
| 459 | if (!src) { | 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 | return err; | 468 | return err; |
| 462 | } | 469 | } |
| 463 | 470 | ||
| 464 | for (map = vhost_iotlb_itree_first(src, start, last); map; | 471 | for (map = vhost_iotlb_itree_first(src, start, last); map; |
| 465 | map = vhost_iotlb_itree_next(map, start, last)) { | 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 | map->addr, map->perm); | 474 | map->addr, map->perm); |
| 468 | if (err) | 475 | if (err) |
| 469 | return err; | 476 | return err; |
| @@ -471,9 +478,9 @@ static int dup_iotlb(struct mlx5_vdpa_dev *mvdev, struct vhost_iotlb *src) · 1 unmodified line | |||
| 471 | return 0; | 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 | static void destroy_user_mr(struct mlx5_vdpa_dev *mvdev, struct mlx5_vdpa_mr *mr) | 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) | 501 | if (mr->user_mr) |
| 495 | return; | 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; | 512 | if (!mr) |
| 503 | |||
| 504 | if (mvdev->group2asid[MLX5_VDPA_DATAVQ_GROUP] != asid) | ||
| 505 | return; | 513 | return; |
| 506 | 514 | ||
| 507 | if (!mr->initialized) | 515 | mutex_lock(&mvdev->mr_mtx); |
| 508 | return; | ||
| 509 | 516 | ||
| 510 | if (mr->user_mr) | 517 | _mlx5_vdpa_destroy_mr(mvdev, mr); |
| 511 | destroy_user_mr(mvdev, mr); | 518 | |
| 512 | else | 519 | for (int i = 0; i < MLX5_VDPA_NUM_AS; i++) { |
| 513 | destroy_dma_mr(mvdev, mr); | 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); | 537 | mvdev->mr[asid] = new_mr; |
| 525 | _mlx5_vdpa_destroy_cvq_mr(mvdev, asid); | 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); | 543 | mutex_unlock(&mvdev->mr_mtx); |
| 528 | } | ||
| 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, | 547 | void mlx5_vdpa_destroy_mr_resources(struct mlx5_vdpa_dev *mvdev) |
| 537 | struct vhost_iotlb *iotlb, | ||
| 538 | unsigned int asid) | ||
| 539 | { | 548 | { |
| 540 | if (mvdev->group2asid[MLX5_VDPA_CVQ_GROUP] != asid) | 549 | for (int i = 0; i < MLX5_VDPA_NUM_AS; i++) |
| 541 | return 0; | 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, | 555 | static int _mlx5_vdpa_create_mr(struct mlx5_vdpa_dev *mvdev, |
| 547 | struct vhost_iotlb *iotlb, | 556 | struct mlx5_vdpa_mr *mr, |
| 548 | unsigned int asid) | 557 | struct vhost_iotlb *iotlb) |
| 549 | { | 558 | { |
| 550 | struct mlx5_vdpa_mr *mr = &mvdev->mr; | ||
| 551 | int err; | 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 | if (iotlb) | 561 | if (iotlb) |
| 560 | err = create_user_mr(mvdev, iotlb); | 562 | err = create_user_mr(mvdev, mr, iotlb); |
| 561 | else | 563 | else |
| 562 | err = create_dma_mr(mvdev, mr); | 564 | err = create_dma_mr(mvdev, mr); |
| 563 | 565 | ||
| 564 | if (err) | 566 | if (err) |
| 565 | return err; | 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 | return 0; | 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, | 593 | struct mlx5_vdpa_mr *mlx5_vdpa_create_mr(struct mlx5_vdpa_dev *mvdev, |
| 573 | struct vhost_iotlb *iotlb, unsigned int asid) | 594 | struct vhost_iotlb *iotlb) |
| 574 | { | 595 | { |
| 596 | struct mlx5_vdpa_mr *mr; | ||
| 575 | int err; | 597 | int err; |
| 576 | 598 | ||
| 577 | err = _mlx5_vdpa_create_dvq_mr(mvdev, iotlb, asid); | 599 | mr = kzalloc(sizeof(*mr), GFP_KERNEL); |
| 578 | if (err) | 600 | if (!mr) |
| 579 | return err; | 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 | if (err) | 607 | if (err) |
| 583 | goto out_err; | 608 | goto out_err; |
| 584 | 609 | ||
| 585 | return 0; | 610 | return mr; |
| 586 | 611 | ||
| 587 | out_err: | 612 | out_err: |
| 588 | _mlx5_vdpa_destroy_dvq_mr(mvdev, asid); | 613 | kfree(mr); |
| 589 | 614 | return ERR_PTR(err); | |
| 590 | return err; | ||
| 591 | } | 615 | } |
| 592 | 616 | ||
| 593 | int mlx5_vdpa_create_mr(struct mlx5_vdpa_dev *mvdev, struct vhost_iotlb *iotlb, | 617 | int mlx5_vdpa_update_cvq_iotlb(struct mlx5_vdpa_dev *mvdev, |
| 594 | unsigned int asid) | 618 | struct vhost_iotlb *iotlb, |
| 619 | unsigned int asid) | ||
| 595 | { | 620 | { |
| 596 | int err; | 621 | int err; |
| 597 | 622 | ||
| 598 | mutex_lock(&mvdev->mr.mkey_mtx); | 623 | if (mvdev->group2asid[MLX5_VDPA_CVQ_GROUP] != asid) |
| 599 | err = _mlx5_vdpa_create_mr(mvdev, iotlb, asid); | 624 | return 0; |
| 600 | mutex_unlock(&mvdev->mr.mkey_mtx); | 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 | return err; | 633 | return err; |
| 602 | } | 634 | } |
| 603 | 635 | ||
| 604 | int mlx5_vdpa_handle_set_map(struct mlx5_vdpa_dev *mvdev, struct vhost_iotlb *iotlb, | 636 | int mlx5_vdpa_create_dma_mr(struct mlx5_vdpa_dev *mvdev) |
| 605 | bool *change_map, unsigned int asid) | ||
| 606 | { | 637 | { |
| 607 | struct mlx5_vdpa_mr *mr = &mvdev->mr; | 638 | struct mlx5_vdpa_mr *mr; |
| 608 | int err = 0; | 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; | 644 | mlx5_vdpa_update_mr(mvdev, mr, 0); |
| 611 | mutex_lock(&mr->mkey_mtx); | 645 | |
| 612 | if (mr->initialized) { | 646 | return mlx5_vdpa_update_cvq_iotlb(mvdev, NULL, 0); |
| 613 | mlx5_vdpa_info(mvdev, "memory map update\n"); | 647 | } |
| 614 | *change_map = true; | 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 | mlx5_vdpa_warn(mvdev, "resources already allocated\n"); | 256 | mlx5_vdpa_warn(mvdev, "resources already allocated\n"); |
| 257 | return -EINVAL; | 257 | return -EINVAL; |
| 258 | } | 258 | } |
| 259 | mutex_init(&mvdev->mr.mkey_mtx); | 259 | mutex_init(&mvdev->mr_mtx); |
| 260 | res->uar = mlx5_get_uars_page(mdev); | 260 | res->uar = mlx5_get_uars_page(mdev); |
| 261 | if (IS_ERR(res->uar)) { | 261 | if (IS_ERR(res->uar)) { |
| 262 | err = PTR_ERR(res->uar); | 262 | err = PTR_ERR(res->uar); |
| @@ -301,7 +301,7 @@ err_pd: · 38 unmodified lines | |||
| 301 | err_uctx: | 301 | err_uctx: |
| 302 | mlx5_put_uars_page(mdev, res->uar); | 302 | mlx5_put_uars_page(mdev, res->uar); |
| 303 | err_uars: | 303 | err_uars: |
| 304 | mutex_destroy(&mvdev->mr.mkey_mtx); | 304 | mutex_destroy(&mvdev->mr_mtx); |
| 305 | return err; | 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 | dealloc_pd(mvdev, res->pdn, res->uid); | 318 | dealloc_pd(mvdev, res->pdn, res->uid); |
| 319 | destroy_uctx(mvdev, res->uid); | 319 | destroy_uctx(mvdev, res->uid); |
| 320 | mlx5_put_uars_page(mvdev->mdev, res->uar); | 320 | mlx5_put_uars_page(mvdev->mdev, res->uar); |
| 321 | mutex_destroy(&mvdev->mr.mkey_mtx); | 321 | mutex_destroy(&mvdev->mr_mtx); |
| 322 | res->valid = false; | 322 | res->valid = false; |
| 323 | } | 323 | } |
| @@ -7,6 +7,7 @@ · 6 unmodified lines | |||
| 7 | #include <uapi/linux/virtio_net.h> | 7 | #include <uapi/linux/virtio_net.h> |
| 8 | #include <uapi/linux/virtio_ids.h> | 8 | #include <uapi/linux/virtio_ids.h> |
| 9 | #include <uapi/linux/vdpa.h> | 9 | #include <uapi/linux/vdpa.h> |
| 10 | #include <uapi/linux/vhost_types.h> | ||
| 10 | #include <linux/virtio_config.h> | 11 | #include <linux/virtio_config.h> |
| 11 | #include <linux/auxiliary_bus.h> | 12 | #include <linux/auxiliary_bus.h> |
| 12 | #include <linux/mlx5/cq.h> | 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 | int inlen = MLX5_ST_SZ_BYTES(create_virtio_net_q_in); | 863 | int inlen = MLX5_ST_SZ_BYTES(create_virtio_net_q_in); |
| 863 | u32 out[MLX5_ST_SZ_DW(create_virtio_net_q_out)] = {}; | 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 | void *obj_context; | 868 | void *obj_context; |
| 865 | u16 mlx_features; | 869 | u16 mlx_features; |
| 866 | void *cmd_hdr; | 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 | MLX5_SET64(virtio_q, vq_ctx, desc_addr, mvq->desc_addr); | 917 | MLX5_SET64(virtio_q, vq_ctx, desc_addr, mvq->desc_addr); |
| 914 | MLX5_SET64(virtio_q, vq_ctx, used_addr, mvq->device_addr); | 918 | MLX5_SET64(virtio_q, vq_ctx, used_addr, mvq->device_addr); |
| 915 | MLX5_SET64(virtio_q, vq_ctx, available_addr, mvq->driver_addr); | 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 | MLX5_SET(virtio_q, vq_ctx, umem_1_id, mvq->umem1.id); | 928 | MLX5_SET(virtio_q, vq_ctx, umem_1_id, mvq->umem1.id); |
| 918 | MLX5_SET(virtio_q, vq_ctx, umem_1_size, mvq->umem1.size); | 929 | MLX5_SET(virtio_q, vq_ctx, umem_1_size, mvq->umem1.size); |
| 919 | MLX5_SET(virtio_q, vq_ctx, umem_2_id, mvq->umem2.id); | 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 | return MLX5_VDPA_DATAVQ_GROUP; | 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 | static u64 mlx_to_vritio_features(u16 dev_features) | 2325 | static u64 mlx_to_vritio_features(u16 dev_features) |
| 2305 | { | 2326 | { |
| 2306 | u64 result = 0; | 2327 | u64 result = 0; |
| @@ -2539,6 +2560,11 @@ static void unregister_link_notifier(struct mlx5_vdpa_net *ndev) · 232 unmodified lines | |||
| 2539 | flush_workqueue(ndev->mvdev.wq); | 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 | static int mlx5_vdpa_set_driver_features(struct vdpa_device *vdev, u64 features) | 2568 | static int mlx5_vdpa_set_driver_features(struct vdpa_device *vdev, u64 features) |
| 2543 | { | 2569 | { |
| 2544 | struct mlx5_vdpa_dev *mvdev = to_mvdev(vdev); | 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 | static int mlx5_vdpa_change_map(struct mlx5_vdpa_dev *mvdev, | 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 | struct mlx5_vdpa_net *ndev = to_mlx5_vdpa_ndev(mvdev); | 2705 | struct mlx5_vdpa_net *ndev = to_mlx5_vdpa_ndev(mvdev); |
| 2679 | int err; | 2706 | int err; |
| @@ -2681,28 +2708,21 @@ static int mlx5_vdpa_change_map(struct mlx5_vdpa_dev *mvdev, · 1 unmodified line | |||
| 2681 | suspend_vqs(ndev); | 2708 | suspend_vqs(ndev); |
| 2682 | err = save_channels_info(ndev); | 2709 | err = save_channels_info(ndev); |
| 2683 | if (err) | 2710 | if (err) |
| 2684 | goto err_mr; | 2711 | return err; |
| 2685 | 2712 | ||
| 2686 | teardown_driver(ndev); | 2713 | teardown_driver(ndev); |
| 2687 | mlx5_vdpa_destroy_mr_asid(mvdev, asid); | 2714 | |
| 2688 | err = mlx5_vdpa_create_mr(mvdev, iotlb, asid); | 2715 | mlx5_vdpa_update_mr(mvdev, new_mr, asid); |
| 2689 | if (err) | ||
| 2690 | goto err_mr; | ||
| 2691 | 2716 | ||
| 2692 | if (!(mvdev->status & VIRTIO_CONFIG_S_DRIVER_OK) || mvdev->suspended) | 2717 | if (!(mvdev->status & VIRTIO_CONFIG_S_DRIVER_OK) || mvdev->suspended) |
| 2693 | goto err_mr; | 2718 | return 0; |
| 2694 | 2719 | ||
| 2695 | restore_channels_info(ndev); | 2720 | restore_channels_info(ndev); |
| 2696 | err = setup_driver(mvdev); | 2721 | err = setup_driver(mvdev); |
| 2697 | if (err) | 2722 | if (err) |
| 2698 | goto err_setup; | 2723 | return err; |
| 2699 | 2724 | ||
| 2700 | return 0; | 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 | /* reslock must be held for this function */ | 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 | err_driver: | 2861 | err_driver: |
| 2842 | unregister_link_notifier(ndev); | 2862 | unregister_link_notifier(ndev); |
| 2843 | err_setup: | 2863 | err_setup: |
| 2844 | mlx5_vdpa_destroy_mr(&ndev->mvdev); | 2864 | mlx5_vdpa_destroy_mr_resources(&ndev->mvdev); |
| 2845 | ndev->mvdev.status |= VIRTIO_CONFIG_S_FAILED; | 2865 | ndev->mvdev.status |= VIRTIO_CONFIG_S_FAILED; |
| 2846 | err_clear: | 2866 | err_clear: |
| 2847 | up_write(&ndev->reslock); | 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 | mvdev->group2asid[i] = 0; | 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 | struct mlx5_vdpa_dev *mvdev = to_mvdev(vdev); | 2881 | struct mlx5_vdpa_dev *mvdev = to_mvdev(vdev); |
| 2862 | struct mlx5_vdpa_net *ndev = to_mlx5_vdpa_ndev(mvdev); | 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 | unregister_link_notifier(ndev); | 2888 | unregister_link_notifier(ndev); |
| 2869 | teardown_driver(ndev); | 2889 | teardown_driver(ndev); |
| 2870 | clear_vqs_ready(ndev); | 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 | ndev->mvdev.status = 0; | 2893 | ndev->mvdev.status = 0; |
| 2873 | ndev->mvdev.suspended = false; | 2894 | ndev->mvdev.suspended = false; |
| 2874 | ndev->cur_num_vqs = 0; | 2895 | ndev->cur_num_vqs = 0; |
| @@ -2879,8 +2900,9 @@ static int mlx5_vdpa_reset(struct vdpa_device *vdev) · 4 unmodified lines | |||
| 2879 | init_group_to_asid_map(mvdev); | 2900 | init_group_to_asid_map(mvdev); |
| 2880 | ++mvdev->generation; | 2901 | ++mvdev->generation; |
| 2881 | 2902 | ||
| 2882 | if (MLX5_CAP_GEN(mvdev->mdev, umem_uid_0)) { | 2903 | if ((flags & VDPA_RESET_F_CLEAN_MAP) && |
| 2883 | if (mlx5_vdpa_create_mr(mvdev, NULL, 0)) | 2904 | MLX5_CAP_GEN(mvdev->mdev, umem_uid_0)) { |
| 2905 | if (mlx5_vdpa_create_dma_mr(mvdev)) | ||
| 2884 | mlx5_vdpa_warn(mvdev, "create MR failed\n"); | 2906 | mlx5_vdpa_warn(mvdev, "create MR failed\n"); |
| 2885 | } | 2907 | } |
| 2886 | up_write(&ndev->reslock); | 2908 | up_write(&ndev->reslock); |
| @@ -2888,6 +2910,11 @@ static int mlx5_vdpa_reset(struct vdpa_device *vdev) · 1 unmodified line | |||
| 2888 | return 0; | 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 | static size_t mlx5_vdpa_get_config_size(struct vdpa_device *vdev) | 2918 | static size_t mlx5_vdpa_get_config_size(struct vdpa_device *vdev) |
| 2892 | { | 2919 | { |
| 2893 | return sizeof(struct virtio_net_config); | 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 | static int set_map_data(struct mlx5_vdpa_dev *mvdev, struct vhost_iotlb *iotlb, | 2946 | static int set_map_data(struct mlx5_vdpa_dev *mvdev, struct vhost_iotlb *iotlb, |
| 2920 | unsigned int asid) | 2947 | unsigned int asid) |
| 2921 | { | 2948 | { |
| 2922 | bool change_map; | 2949 | struct mlx5_vdpa_mr *new_mr; |
| 2923 | int err; | 2950 | int err; |
| 2924 | 2951 | ||
| 2925 | err = mlx5_vdpa_handle_set_map(mvdev, iotlb, &change_map, asid); | 2952 | if (asid >= MLX5_VDPA_NUM_AS) |
| 2926 | if (err) { | 2953 | return -EINVAL; |
| 2927 | mlx5_vdpa_warn(mvdev, "set map failed(%d)\n", err); | 2954 | |
| 2928 | return err; | 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) | 2977 | return mlx5_vdpa_update_cvq_iotlb(mvdev, iotlb, asid); |
| 2932 | err = mlx5_vdpa_change_map(mvdev, iotlb, asid); | ||
| 2933 | 2978 | ||
| 2979 | out_err: | ||
| 2980 | mlx5_vdpa_destroy_mr(mvdev, new_mr); | ||
| 2934 | return err; | 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 | return err; | 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 | static struct device *mlx5_get_vq_dma_dev(struct vdpa_device *vdev, u16 idx) | 3009 | static struct device *mlx5_get_vq_dma_dev(struct vdpa_device *vdev, u16 idx) |
| 2951 | { | 3010 | { |
| 2952 | struct mlx5_vdpa_dev *mvdev = to_mvdev(vdev); | 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 | ndev = to_mlx5_vdpa_ndev(mvdev); | 3044 | ndev = to_mlx5_vdpa_ndev(mvdev); |
| 2986 | 3045 | ||
| 2987 | free_resources(ndev); | 3046 | free_resources(ndev); |
| 2988 | mlx5_vdpa_destroy_mr(mvdev); | 3047 | mlx5_vdpa_destroy_mr_resources(mvdev); |
| 2989 | if (!is_zero_ether_addr(ndev->config.mac)) { | 3048 | if (!is_zero_ether_addr(ndev->config.mac)) { |
| 2990 | pfmdev = pci_get_drvdata(pci_physfn(mvdev->mdev->pdev)); | 3049 | pfmdev = pci_get_drvdata(pci_physfn(mvdev->mdev->pdev)); |
| 2991 | mlx5_mpfs_del_mac(pfmdev, ndev->config.mac); | 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 | unsigned int asid) | 3228 | unsigned int asid) |
| 3170 | { | 3229 | { |
| 3171 | struct mlx5_vdpa_dev *mvdev = to_mvdev(vdev); | 3230 | struct mlx5_vdpa_dev *mvdev = to_mvdev(vdev); |
| 3231 | int err = 0; | ||
| 3172 | 3232 | ||
| 3173 | if (group >= MLX5_VDPA_NUMVQ_GROUPS) | 3233 | if (group >= MLX5_VDPA_NUMVQ_GROUPS) |
| 3174 | return -EINVAL; | 3234 | return -EINVAL; |
| 3175 | 3235 | ||
| 3176 | mvdev->group2asid[group] = asid; | 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 | static const struct vdpa_config_ops mlx5_vdpa_ops = { | 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 | .get_vq_irq = mlx5_get_vq_irq, | 3257 | .get_vq_irq = mlx5_get_vq_irq, |
| 3192 | .get_vq_align = mlx5_vdpa_get_vq_align, | 3258 | .get_vq_align = mlx5_vdpa_get_vq_align, |
| 3193 | .get_vq_group = mlx5_vdpa_get_vq_group, | 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 | .get_device_features = mlx5_vdpa_get_device_features, | 3261 | .get_device_features = mlx5_vdpa_get_device_features, |
| 3262 | .get_backend_features = mlx5_vdpa_get_backend_features, | ||
| 3195 | .set_driver_features = mlx5_vdpa_set_driver_features, | 3263 | .set_driver_features = mlx5_vdpa_set_driver_features, |
| 3196 | .get_driver_features = mlx5_vdpa_get_driver_features, | 3264 | .get_driver_features = mlx5_vdpa_get_driver_features, |
| 3197 | .set_config_cb = mlx5_vdpa_set_config_cb, | 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 | .get_status = mlx5_vdpa_get_status, | 3269 | .get_status = mlx5_vdpa_get_status, |
| 3202 | .set_status = mlx5_vdpa_set_status, | 3270 | .set_status = mlx5_vdpa_set_status, |
| 3203 | .reset = mlx5_vdpa_reset, | 3271 | .reset = mlx5_vdpa_reset, |
| 3272 | .compat_reset = mlx5_vdpa_compat_reset, | ||
| 3204 | .get_config_size = mlx5_vdpa_get_config_size, | 3273 | .get_config_size = mlx5_vdpa_get_config_size, |
| 3205 | .get_config = mlx5_vdpa_get_config, | 3274 | .get_config = mlx5_vdpa_get_config, |
| 3206 | .set_config = mlx5_vdpa_set_config, | 3275 | .set_config = mlx5_vdpa_set_config, |
| 3207 | .get_generation = mlx5_vdpa_get_generation, | 3276 | .get_generation = mlx5_vdpa_get_generation, |
| 3208 | .set_map = mlx5_vdpa_set_map, | 3277 | .set_map = mlx5_vdpa_set_map, |
| 3278 | .reset_map = mlx5_vdpa_reset_map, | ||
| 3209 | .set_group_asid = mlx5_set_group_asid, | 3279 | .set_group_asid = mlx5_set_group_asid, |
| 3210 | .get_vq_dma_dev = mlx5_get_vq_dma_dev, | 3280 | .get_vq_dma_dev = mlx5_get_vq_dma_dev, |
| 3211 | .free = mlx5_vdpa_free, | 3281 | .free = mlx5_vdpa_free, |
| @@ -3289,6 +3359,7 @@ struct mlx5_vdpa_mgmtdev { · 77 unmodified lines | |||
| 3289 | struct vdpa_mgmt_dev mgtdev; | 3359 | struct vdpa_mgmt_dev mgtdev; |
| 3290 | struct mlx5_adev *madev; | 3360 | struct mlx5_adev *madev; |
| 3291 | struct mlx5_vdpa_net *ndev; | 3361 | struct mlx5_vdpa_net *ndev; |
| 3362 | struct vdpa_config_ops vdpa_ops; | ||
| 3292 | }; | 3363 | }; |
| 3293 | 3364 | ||
| 3294 | static int config_func_mtu(struct mlx5_core_dev *mdev, u16 mtu) | 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 | max_vqs = 2; | 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 | MLX5_VDPA_NUMVQ_GROUPS, MLX5_VDPA_NUM_AS, name, false); | 3477 | MLX5_VDPA_NUMVQ_GROUPS, MLX5_VDPA_NUM_AS, name, false); |
| 3407 | if (IS_ERR(ndev)) | 3478 | if (IS_ERR(ndev)) |
| 3408 | return PTR_ERR(ndev); | 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 | goto err_mpfs; | 3556 | goto err_mpfs; |
| 3486 | 3557 | ||
| 3487 | if (MLX5_CAP_GEN(mvdev->mdev, umem_uid_0)) { | 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 | if (err) | 3560 | if (err) |
| 3490 | goto err_res; | 3561 | goto err_res; |
| 3491 | } | 3562 | } |
| @@ -3515,7 +3586,7 @@ err_reg: · 23 unmodified lines | |||
| 3515 | err_res2: | 3586 | err_res2: |
| 3516 | free_resources(ndev); | 3587 | free_resources(ndev); |
| 3517 | err_mr: | 3588 | err_mr: |
| 3518 | mlx5_vdpa_destroy_mr(mvdev); | 3589 | mlx5_vdpa_destroy_mr_resources(mvdev); |
| 3519 | err_res: | 3590 | err_res: |
| 3520 | mlx5_vdpa_free_resources(&ndev->mvdev); | 3591 | mlx5_vdpa_free_resources(&ndev->mvdev); |
| 3521 | err_mpfs: | 3592 | err_mpfs: |
| @@ -3575,6 +3646,10 @@ static int mlx5v_probe(struct auxiliary_device *adev, · 53 unmodified lines | |||
| 3575 | MLX5_CAP_DEV_VDPA_EMULATION(mdev, max_num_virtio_queues) + 1; | 3646 | MLX5_CAP_DEV_VDPA_EMULATION(mdev, max_num_virtio_queues) + 1; |
| 3576 | mgtdev->mgtdev.supported_features = get_supported_features(mdev); | 3647 | mgtdev->mgtdev.supported_features = get_supported_features(mdev); |
| 3577 | mgtdev->madev = madev; | 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 | err = vdpa_mgmtdev_register(&mgtdev->mgtdev); | 3654 | err = vdpa_mgmtdev_register(&mgtdev->mgtdev); |
| 3580 | if (err) | 3655 | if (err) |
| @@ -139,7 +139,7 @@ static void vdpasim_vq_reset(struct vdpasim *vdpasim, · 138 unmodified lines | |||
| 139 | vq->vring.notify = NULL; | 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 | int i; | 144 | int i; |
| 145 | 145 | ||
| @@ -151,11 +151,13 @@ static void vdpasim_do_reset(struct vdpasim *vdpasim) · 5 unmodified lines | |||
| 151 | &vdpasim->iommu_lock); | 151 | &vdpasim->iommu_lock); |
| 152 | } | 152 | } |
| 153 | 153 | ||
| 154 | for (i = 0; i < vdpasim->dev_attr.nas; i++) { | 154 | if (flags & VDPA_RESET_F_CLEAN_MAP) { |
| 155 | vhost_iotlb_reset(&vdpasim->iommu[i]); | 155 | for (i = 0; i < vdpasim->dev_attr.nas; i++) { |
| 156 | vhost_iotlb_add_range(&vdpasim->iommu[i], 0, ULONG_MAX, | 156 | vhost_iotlb_reset(&vdpasim->iommu[i]); |
| 157 | 0, VHOST_MAP_RW); | 157 | vhost_iotlb_add_range(&vdpasim->iommu[i], 0, ULONG_MAX, |
| 158 | vdpasim->iommu_pt[i] = true; | 158 | 0, VHOST_MAP_RW); |
| 159 | vdpasim->iommu_pt[i] = true; | ||
| 160 | } | ||
| 159 | } | 161 | } |
| 160 | 162 | ||
| 161 | vdpasim->running = true; | 163 | vdpasim->running = true; |
| @@ -259,8 +261,12 @@ struct vdpasim *vdpasim_create(struct vdpasim_dev_attr *dev_attr, · 97 unmodified lines | |||
| 259 | if (!vdpasim->iommu_pt) | 261 | if (!vdpasim->iommu_pt) |
| 260 | goto err_iommu; | 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 | vhost_iotlb_init(&vdpasim->iommu[i], max_iotlb_entries, 0); | 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 | for (i = 0; i < dev_attr->nvqs; i++) | 271 | for (i = 0; i < dev_attr->nvqs; i++) |
| 266 | vringh_set_iotlb(&vdpasim->vqs[i].vring, &vdpasim->iommu[0], | 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 | mutex_unlock(&vdpasim->mutex); | 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 | struct vdpasim *vdpasim = vdpa_to_sim(vdpa); | 491 | struct vdpasim *vdpasim = vdpa_to_sim(vdpa); |
| 486 | 492 | ||
| 487 | mutex_lock(&vdpasim->mutex); | 493 | mutex_lock(&vdpasim->mutex); |
| 488 | vdpasim->status = 0; | 494 | vdpasim->status = 0; |
| 489 | vdpasim_do_reset(vdpasim); | 495 | vdpasim_do_reset(vdpasim, flags); |
| 490 | mutex_unlock(&vdpasim->mutex); | 496 | mutex_unlock(&vdpasim->mutex); |
| 491 | 497 | ||
| 492 | return 0; | 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 | static int vdpasim_suspend(struct vdpa_device *vdpa) | 506 | static int vdpasim_suspend(struct vdpa_device *vdpa) |
| 496 | { | 507 | { |
| 497 | struct vdpasim *vdpasim = vdpa_to_sim(vdpa); | 508 | struct vdpasim *vdpasim = vdpa_to_sim(vdpa); |
| @@ -637,6 +648,25 @@ err: · 139 unmodified lines | |||
| 637 | return ret; | 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 | static int vdpasim_bind_mm(struct vdpa_device *vdpa, struct mm_struct *mm) | 670 | static int vdpasim_bind_mm(struct vdpa_device *vdpa, struct mm_struct *mm) |
| 641 | { | 671 | { |
| 642 | struct vdpasim *vdpasim = vdpa_to_sim(vdpa); | 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 | .get_status = vdpasim_get_status, | 779 | .get_status = vdpasim_get_status, |
| 750 | .set_status = vdpasim_set_status, | 780 | .set_status = vdpasim_set_status, |
| 751 | .reset = vdpasim_reset, | 781 | .reset = vdpasim_reset, |
| 782 | .compat_reset = vdpasim_compat_reset, | ||
| 752 | .suspend = vdpasim_suspend, | 783 | .suspend = vdpasim_suspend, |
| 753 | .resume = vdpasim_resume, | 784 | .resume = vdpasim_resume, |
| 754 | .get_config_size = vdpasim_get_config_size, | 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 | .set_group_asid = vdpasim_set_group_asid, | 790 | .set_group_asid = vdpasim_set_group_asid, |
| 760 | .dma_map = vdpasim_dma_map, | 791 | .dma_map = vdpasim_dma_map, |
| 761 | .dma_unmap = vdpasim_dma_unmap, | 792 | .dma_unmap = vdpasim_dma_unmap, |
| 793 | .reset_map = vdpasim_reset_map, | ||
| 762 | .bind_mm = vdpasim_bind_mm, | 794 | .bind_mm = vdpasim_bind_mm, |
| 763 | .unbind_mm = vdpasim_unbind_mm, | 795 | .unbind_mm = vdpasim_unbind_mm, |
| 764 | .free = vdpasim_free, | 796 | .free = vdpasim_free, |
| @@ -787,6 +819,7 @@ static const struct vdpa_config_ops vdpasim_batch_config_ops = { · 22 unmodified lines | |||
| 787 | .get_status = vdpasim_get_status, | 819 | .get_status = vdpasim_get_status, |
| 788 | .set_status = vdpasim_set_status, | 820 | .set_status = vdpasim_set_status, |
| 789 | .reset = vdpasim_reset, | 821 | .reset = vdpasim_reset, |
| 822 | .compat_reset = vdpasim_compat_reset, | ||
| 790 | .suspend = vdpasim_suspend, | 823 | .suspend = vdpasim_suspend, |
| 791 | .resume = vdpasim_resume, | 824 | .resume = vdpasim_resume, |
| 792 | .get_config_size = vdpasim_get_config_size, | 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 | .get_iova_range = vdpasim_get_iova_range, | 829 | .get_iova_range = vdpasim_get_iova_range, |
| 797 | .set_group_asid = vdpasim_set_group_asid, | 830 | .set_group_asid = vdpasim_set_group_asid, |
| 798 | .set_map = vdpasim_set_map, | 831 | .set_map = vdpasim_set_map, |
| 832 | .reset_map = vdpasim_reset_map, | ||
| 799 | .bind_mm = vdpasim_bind_mm, | 833 | .bind_mm = vdpasim_bind_mm, |
| 800 | .unbind_mm = vdpasim_unbind_mm, | 834 | .unbind_mm = vdpasim_unbind_mm, |
| 801 | .free = vdpasim_free, | 835 | .free = vdpasim_free, |
| @@ -134,7 +134,6 @@ static DEFINE_MUTEX(vduse_lock); · 133 unmodified lines | |||
| 134 | static DEFINE_IDR(vduse_idr); | 134 | static DEFINE_IDR(vduse_idr); |
| 135 | 135 | ||
| 136 | static dev_t vduse_major; | 136 | static dev_t vduse_major; |
| 137 | static struct class *vduse_class; | ||
| 138 | static struct cdev vduse_ctrl_cdev; | 137 | static struct cdev vduse_ctrl_cdev; |
| 139 | static struct cdev vduse_cdev; | 138 | static struct cdev vduse_cdev; |
| 140 | static struct workqueue_struct *vduse_irq_wq; | 139 | static struct workqueue_struct *vduse_irq_wq; |
| @@ -1528,6 +1527,16 @@ static const struct kobj_type vq_type = { · 1387 unmodified lines | |||
| 1528 | .default_groups = vq_groups, | 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 | static void vduse_dev_deinit_vqs(struct vduse_dev *dev) | 1540 | static void vduse_dev_deinit_vqs(struct vduse_dev *dev) |
| 1532 | { | 1541 | { |
| 1533 | int i; | 1542 | int i; |
| @@ -1638,7 +1647,7 @@ static int vduse_destroy_dev(char *name) · 104 unmodified lines | |||
| 1638 | mutex_unlock(&dev->lock); | 1647 | mutex_unlock(&dev->lock); |
| 1639 | 1648 | ||
| 1640 | vduse_dev_reset(dev); | 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 | idr_remove(&vduse_idr, dev->minor); | 1651 | idr_remove(&vduse_idr, dev->minor); |
| 1643 | kvfree(dev->config); | 1652 | kvfree(dev->config); |
| 1644 | vduse_dev_deinit_vqs(dev); | 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 | dev->minor = ret; | 1815 | dev->minor = ret; |
| 1807 | dev->msg_timeout = VDUSE_MSG_DEFAULT_TIMEOUT; | 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 | MKDEV(MAJOR(vduse_major), dev->minor), | 1818 | MKDEV(MAJOR(vduse_major), dev->minor), |
| 1810 | dev, vduse_dev_groups, "%s", config->name); | 1819 | dev, vduse_dev_groups, "%s", config->name); |
| 1811 | if (IS_ERR(dev->dev)) { | 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 | return 0; | 1831 | return 0; |
| 1823 | err_vqs: | 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 | err_dev: | 1834 | err_dev: |
| 1826 | idr_remove(&vduse_idr, dev->minor); | 1835 | idr_remove(&vduse_idr, dev->minor); |
| 1827 | err_idr: | 1836 | err_idr: |
| @@ -1934,11 +1943,6 @@ static const struct file_operations vduse_ctrl_fops = { · 106 unmodified lines | |||
| 1934 | .llseek = noop_llseek, | 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 | struct vduse_mgmt_dev { | 1946 | struct vduse_mgmt_dev { |
| 1943 | struct vdpa_mgmt_dev mgmt_dev; | 1947 | struct vdpa_mgmt_dev mgmt_dev; |
| 1944 | struct device dev; | 1948 | struct device dev; |
| @@ -2082,11 +2086,9 @@ static int vduse_init(void) · 137 unmodified lines | |||
| 2082 | int ret; | 2086 | int ret; |
| 2083 | struct device *dev; | 2087 | struct device *dev; |
| 2084 | 2088 | ||
| 2085 | vduse_class = class_create("vduse"); | 2089 | ret = class_register(&vduse_class); |
| 2086 | if (IS_ERR(vduse_class)) | 2090 | if (ret) |
| 2087 | return PTR_ERR(vduse_class); | 2091 | return ret; |
| 2088 | |||
| 2089 | vduse_class->devnode = vduse_devnode; | ||
| 2090 | 2092 | ||
| 2091 | ret = alloc_chrdev_region(&vduse_major, 0, VDUSE_DEV_MAX, "vduse"); | 2093 | ret = alloc_chrdev_region(&vduse_major, 0, VDUSE_DEV_MAX, "vduse"); |
| 2092 | if (ret) | 2094 | if (ret) |
| @@ -2099,7 +2101,7 @@ static int vduse_init(void) · 6 unmodified lines | |||
| 2099 | if (ret) | 2101 | if (ret) |
| 2100 | goto err_ctrl_cdev; | 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 | if (IS_ERR(dev)) { | 2105 | if (IS_ERR(dev)) { |
| 2104 | ret = PTR_ERR(dev); | 2106 | ret = PTR_ERR(dev); |
| 2105 | goto err_device; | 2107 | goto err_device; |
| @@ -2141,13 +2143,13 @@ err_bound_wq: · 35 unmodified lines | |||
| 2141 | err_wq: | 2143 | err_wq: |
| 2142 | cdev_del(&vduse_cdev); | 2144 | cdev_del(&vduse_cdev); |
| 2143 | err_cdev: | 2145 | err_cdev: |
| 2144 | device_destroy(vduse_class, vduse_major); | 2146 | device_destroy(&vduse_class, vduse_major); |
| 2145 | err_device: | 2147 | err_device: |
| 2146 | cdev_del(&vduse_ctrl_cdev); | 2148 | cdev_del(&vduse_ctrl_cdev); |
| 2147 | err_ctrl_cdev: | 2149 | err_ctrl_cdev: |
| 2148 | unregister_chrdev_region(vduse_major, VDUSE_DEV_MAX); | 2150 | unregister_chrdev_region(vduse_major, VDUSE_DEV_MAX); |
| 2149 | err_chardev_region: | 2151 | err_chardev_region: |
| 2150 | class_destroy(vduse_class); | 2152 | class_unregister(&vduse_class); |
| 2151 | return ret; | 2153 | return ret; |
| 2152 | } | 2154 | } |
| 2153 | module_init(vduse_init); | 2155 | module_init(vduse_init); |
| @@ -2159,10 +2161,10 @@ static void vduse_exit(void) · 5 unmodified lines | |||
| 2159 | destroy_workqueue(vduse_irq_bound_wq); | 2161 | destroy_workqueue(vduse_irq_bound_wq); |
| 2160 | destroy_workqueue(vduse_irq_wq); | 2162 | destroy_workqueue(vduse_irq_wq); |
| 2161 | cdev_del(&vduse_cdev); | 2163 | cdev_del(&vduse_cdev); |
| 2162 | device_destroy(vduse_class, vduse_major); | 2164 | device_destroy(&vduse_class, vduse_major); |
| 2163 | cdev_del(&vduse_ctrl_cdev); | 2165 | cdev_del(&vduse_ctrl_cdev); |
| 2164 | unregister_chrdev_region(vduse_major, VDUSE_DEV_MAX); | 2166 | unregister_chrdev_region(vduse_major, VDUSE_DEV_MAX); |
| 2165 | class_destroy(vduse_class); | 2167 | class_unregister(&vduse_class); |
| 2166 | } | 2168 | } |
| 2167 | module_exit(vduse_exit); | 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 | * Set prot_iter to data_iter and truncate it to | 1159 | * Set prot_iter to data_iter and truncate it to |
| 1160 | * prot_bytes, and advance data_iter past any | 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 | * Also fix up the exp_data_len to reflect only the | 1163 | * Also fix up the exp_data_len to reflect only the |
| 1164 | * actual data payload length. | 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 | return vhost_vdpa_alloc_as(v, asid); | 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 | static int vhost_vdpa_remove_as(struct vhost_vdpa *v, u32 asid) | 143 | static int vhost_vdpa_remove_as(struct vhost_vdpa *v, u32 asid) |
| 135 | { | 144 | { |
| 136 | struct vhost_vdpa_as *as = asid_to_as(v, asid); | 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 | hlist_del(&as->hash_link); | 150 | hlist_del(&as->hash_link); |
| 142 | vhost_vdpa_iotlb_unmap(v, &as->iotlb, 0ULL, 0ULL - 1, asid); | 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 | kfree(as); | 160 | kfree(as); |
| 144 | 161 | ||
| 145 | return 0; | 162 | return 0; |
| @@ -210,13 +227,24 @@ static void vhost_vdpa_unsetup_vq_irq(struct vhost_vdpa *v, u16 qid) · 64 unmodified lines | |||
| 210 | irq_bypass_unregister_producer(&vq->call_ctx.producer); | 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 | struct vdpa_device *vdpa = v->vdpa; | 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 | static long vhost_vdpa_bind_mm(struct vhost_vdpa *v) | 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 | vhost_vdpa_unsetup_vq_irq(v, i); | 323 | vhost_vdpa_unsetup_vq_irq(v, i); |
| 296 | 324 | ||
| 297 | if (status == 0) { | 325 | if (status == 0) { |
| 298 | ret = vdpa_reset(vdpa); | 326 | ret = _compat_vdpa_reset(v); |
| 299 | if (ret) | 327 | if (ret) |
| 300 | return ret; | 328 | return ret; |
| 301 | } else | 329 | } else |
| @@ -389,6 +417,14 @@ static bool vhost_vdpa_can_resume(const struct vhost_vdpa *v) · 87 unmodified lines | |||
| 389 | return ops->resume; | 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 | static long vhost_vdpa_get_features(struct vhost_vdpa *v, u64 __user *featurep) | 428 | static long vhost_vdpa_get_features(struct vhost_vdpa *v, u64 __user *featurep) |
| 393 | { | 429 | { |
| 394 | struct vdpa_device *vdpa = v->vdpa; | 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 | return ops->get_backend_features(vdpa); | 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 | static long vhost_vdpa_set_features(struct vhost_vdpa *v, u64 __user *featurep) | 462 | static long vhost_vdpa_set_features(struct vhost_vdpa *v, u64 __user *featurep) |
| 418 | { | 463 | { |
| 419 | struct vdpa_device *vdpa = v->vdpa; | 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 | else if (copy_to_user(argp, &s, sizeof(s))) | 650 | else if (copy_to_user(argp, &s, sizeof(s))) |
| 606 | return -EFAULT; | 651 | return -EFAULT; |
| 607 | return 0; | 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 | case VHOST_VDPA_SET_GROUP_ASID: | 663 | case VHOST_VDPA_SET_GROUP_ASID: |
| 609 | if (copy_from_user(&s, argp, sizeof(s))) | 664 | if (copy_from_user(&s, argp, sizeof(s))) |
| 610 | return -EFAULT; | 665 | return -EFAULT; |
| @@ -690,6 +745,8 @@ static long vhost_vdpa_unlocked_ioctl(struct file *filep, · 79 unmodified lines | |||
| 690 | if (copy_from_user(&features, featurep, sizeof(features))) | 745 | if (copy_from_user(&features, featurep, sizeof(features))) |
| 691 | return -EFAULT; | 746 | return -EFAULT; |
| 692 | if (features & ~(VHOST_VDPA_BACKEND_FEATURES | | 747 | if (features & ~(VHOST_VDPA_BACKEND_FEATURES | |
| 748 | BIT_ULL(VHOST_BACKEND_F_DESC_ASID) | | ||
| 749 | BIT_ULL(VHOST_BACKEND_F_IOTLB_PERSIST) | | ||
| 693 | BIT_ULL(VHOST_BACKEND_F_SUSPEND) | | 750 | BIT_ULL(VHOST_BACKEND_F_SUSPEND) | |
| 694 | BIT_ULL(VHOST_BACKEND_F_RESUME) | | 751 | BIT_ULL(VHOST_BACKEND_F_RESUME) | |
| 695 | BIT_ULL(VHOST_BACKEND_F_ENABLE_AFTER_DRIVER_OK))) | 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 | if ((features & BIT_ULL(VHOST_BACKEND_F_RESUME)) && | 757 | if ((features & BIT_ULL(VHOST_BACKEND_F_RESUME)) && |
| 701 | !vhost_vdpa_can_resume(v)) | 758 | !vhost_vdpa_can_resume(v)) |
| 702 | return -EOPNOTSUPP; | 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 | vhost_set_backend_features(&v->vdev, features); | 769 | vhost_set_backend_features(&v->vdev, features); |
| 704 | return 0; | 770 | return 0; |
| 705 | } | 771 | } |
| @@ -753,6 +819,10 @@ static long vhost_vdpa_unlocked_ioctl(struct file *filep, · 47 unmodified lines | |||
| 753 | features |= BIT_ULL(VHOST_BACKEND_F_SUSPEND); | 819 | features |= BIT_ULL(VHOST_BACKEND_F_SUSPEND); |
| 754 | if (vhost_vdpa_can_resume(v)) | 820 | if (vhost_vdpa_can_resume(v)) |
| 755 | features |= BIT_ULL(VHOST_BACKEND_F_RESUME); | 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 | features |= vhost_vdpa_get_backend_features(v); | 826 | features |= vhost_vdpa_get_backend_features(v); |
| 757 | if (copy_to_user(featurep, &features, sizeof(features))) | 827 | if (copy_to_user(featurep, &features, sizeof(features))) |
| 758 | r = -EFAULT; | 828 | r = -EFAULT; |
| @@ -1285,6 +1355,7 @@ static void vhost_vdpa_cleanup(struct vhost_vdpa *v) · 526 unmodified lines | |||
| 1285 | vhost_vdpa_free_domain(v); | 1355 | vhost_vdpa_free_domain(v); |
| 1286 | vhost_dev_cleanup(&v->vdev); | 1356 | vhost_dev_cleanup(&v->vdev); |
| 1287 | kfree(v->vdev.vqs); | 1357 | kfree(v->vdev.vqs); |
| 1358 | v->vdev.vqs = NULL; | ||
| 1288 | } | 1359 | } |
| 1289 | 1360 | ||
| 1290 | static int vhost_vdpa_open(struct inode *inode, struct file *filep) | 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 | * 2) update the host about the old page removed from vb->pages list; | 745 | * 2) update the host about the old page removed from vb->pages list; |
| 746 | * | 746 | * |
| 747 | * This function preforms the balloon page migration task. | 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 | static int virtballoon_migratepage(struct balloon_dev_info *vb_dev_info, | 750 | static int virtballoon_migratepage(struct balloon_dev_info *vb_dev_info, |
| 751 | struct page *newpage, struct page *page, enum migrate_mode mode) | 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 | __virtio_set_bit(vdev, VIRTIO_F_RING_RESET); | 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 | /* virtio config->finalize_features() implementation */ | 75 | /* virtio config->finalize_features() implementation */ |
| 43 | static int vp_finalize_features(struct virtio_device *vdev) | 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 | return -EINVAL; | 90 | return -EINVAL; |
| 58 | } | 91 | } |
| 59 | 92 | ||
| 93 | if (vp_check_common_size(vdev)) | ||
| 94 | return -EINVAL; | ||
| 95 | |||
| 60 | vp_modern_set_features(&vp_dev->mdev, vdev->features); | 96 | vp_modern_set_features(&vp_dev->mdev, vdev->features); |
| 61 | 97 | ||
| 62 | return 0; | 98 | return 0; |
| @@ -203,6 +203,10 @@ static inline void check_offsets(void) · 202 unmodified lines | |||
| 203 | offsetof(struct virtio_pci_common_cfg, queue_used_lo)); | 203 | offsetof(struct virtio_pci_common_cfg, queue_used_lo)); |
| 204 | BUILD_BUG_ON(VIRTIO_PCI_COMMON_Q_USEDHI != | 204 | BUILD_BUG_ON(VIRTIO_PCI_COMMON_Q_USEDHI != |
| 205 | offsetof(struct virtio_pci_common_cfg, queue_used_hi)); | 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 | mdev->common = vp_modern_map_capability(mdev, common, | 296 | mdev->common = vp_modern_map_capability(mdev, common, |
| 293 | sizeof(struct virtio_pci_common_cfg), 4, | 297 | sizeof(struct virtio_pci_common_cfg), 4, |
| 294 | 0, sizeof(struct virtio_pci_modern_common_cfg), | 298 | 0, sizeof(struct virtio_pci_modern_common_cfg), |
| 295 | NULL, NULL); | 299 | &mdev->common_len, NULL); |
| 296 | if (!mdev->common) | 300 | if (!mdev->common) |
| 297 | goto err_map_common; | 301 | goto err_map_common; |
| 298 | mdev->isr = vp_modern_map_capability(mdev, isr, sizeof(u8), 1, | 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 | struct vdpa_device *vdpa = vd_get_vdpa(vdev); | 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 | static bool virtio_vdpa_notify(struct virtqueue *vq) | 106 | static bool virtio_vdpa_notify(struct virtqueue *vq) |
| @@ -1232,7 +1232,13 @@ struct mlx5_ifc_virtio_emulation_cap_bits { · 1231 unmodified lines | |||
| 1232 | u8 max_emulated_devices[0x8]; | 1232 | u8 max_emulated_devices[0x8]; |
| 1233 | u8 max_num_virtio_queues[0x18]; | 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 | u8 umem_1_buffer_param_a[0x20]; | 1243 | u8 umem_1_buffer_param_a[0x20]; |
| 1238 | 1244 | ||
| @@ -74,7 +74,11 @@ struct mlx5_ifc_virtio_q_bits { · 73 unmodified lines | |||
| 74 | u8 reserved_at_320[0x8]; | 74 | u8 reserved_at_320[0x8]; |
| 75 | u8 pd[0x18]; | 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 | struct mlx5_ifc_virtio_net_q_object_bits { | 84 | struct mlx5_ifc_virtio_net_q_object_bits { |
| @@ -141,6 +145,7 @@ enum { · 60 unmodified lines | |||
| 141 | MLX5_VIRTQ_MODIFY_MASK_STATE = (u64)1 << 0, | 145 | MLX5_VIRTQ_MODIFY_MASK_STATE = (u64)1 << 0, |
| 142 | MLX5_VIRTQ_MODIFY_MASK_DIRTY_BITMAP_PARAMS = (u64)1 << 3, | 146 | MLX5_VIRTQ_MODIFY_MASK_DIRTY_BITMAP_PARAMS = (u64)1 << 3, |
| 143 | MLX5_VIRTQ_MODIFY_MASK_DIRTY_BITMAP_DUMP_ENABLE = (u64)1 << 4, | 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 | enum { | 151 | enum { |
| @@ -204,6 +204,16 @@ struct vdpa_map_file { · 203 unmodified lines | |||
| 204 | * @vdev: vdpa device | 204 | * @vdev: vdpa device |
| 205 | * @idx: virtqueue index | 205 | * @idx: virtqueue index |
| 206 | * Returns u32: group id for this virtqueue | 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 | * @get_device_features: Get virtio features supported by the device | 217 | * @get_device_features: Get virtio features supported by the device |
| 208 | * @vdev: vdpa device | 218 | * @vdev: vdpa device |
| 209 | * Returns the virtio features support by the | 219 | * Returns the virtio features support by the |
| @@ -242,6 +252,17 @@ struct vdpa_map_file { · 32 unmodified lines | |||
| 242 | * @reset: Reset device | 252 | * @reset: Reset device |
| 243 | * @vdev: vdpa device | 253 | * @vdev: vdpa device |
| 244 | * Returns integer: success (0) or error (< 0) | 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 | * @suspend: Suspend the device (optional) | 266 | * @suspend: Suspend the device (optional) |
| 246 | * @vdev: vdpa device | 267 | * @vdev: vdpa device |
| 247 | * Returns integer: success (0) or error (< 0) | 268 | * Returns integer: success (0) or error (< 0) |
| @@ -317,6 +338,15 @@ struct vdpa_map_file { · 69 unmodified lines | |||
| 317 | * @iova: iova to be unmapped | 338 | * @iova: iova to be unmapped |
| 318 | * @size: size of the area | 339 | * @size: size of the area |
| 319 | * Returns integer: success (0) or error (< 0) | 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 | * @get_vq_dma_dev: Get the dma device for a specific | 350 | * @get_vq_dma_dev: Get the dma device for a specific |
| 321 | * virtqueue (optional) | 351 | * virtqueue (optional) |
| 322 | * @vdev: vdpa device | 352 | * @vdev: vdpa device |
| @@ -360,6 +390,7 @@ struct vdpa_config_ops { · 37 unmodified lines | |||
| 360 | /* Device ops */ | 390 | /* Device ops */ |
| 361 | u32 (*get_vq_align)(struct vdpa_device *vdev); | 391 | u32 (*get_vq_align)(struct vdpa_device *vdev); |
| 362 | u32 (*get_vq_group)(struct vdpa_device *vdev, u16 idx); | 392 | u32 (*get_vq_group)(struct vdpa_device *vdev, u16 idx); |
| 393 | u32 (*get_vq_desc_group)(struct vdpa_device *vdev, u16 idx); | ||
| 363 | u64 (*get_device_features)(struct vdpa_device *vdev); | 394 | u64 (*get_device_features)(struct vdpa_device *vdev); |
| 364 | u64 (*get_backend_features)(const struct vdpa_device *vdev); | 395 | u64 (*get_backend_features)(const struct vdpa_device *vdev); |
| 365 | int (*set_driver_features)(struct vdpa_device *vdev, u64 features); | 396 | int (*set_driver_features)(struct vdpa_device *vdev, u64 features); |
| @@ -373,6 +404,8 @@ struct vdpa_config_ops { · 7 unmodified lines | |||
| 373 | u8 (*get_status)(struct vdpa_device *vdev); | 404 | u8 (*get_status)(struct vdpa_device *vdev); |
| 374 | void (*set_status)(struct vdpa_device *vdev, u8 status); | 405 | void (*set_status)(struct vdpa_device *vdev, u8 status); |
| 375 | int (*reset)(struct vdpa_device *vdev); | 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 | int (*suspend)(struct vdpa_device *vdev); | 409 | int (*suspend)(struct vdpa_device *vdev); |
| 377 | int (*resume)(struct vdpa_device *vdev); | 410 | int (*resume)(struct vdpa_device *vdev); |
| 378 | size_t (*get_config_size)(struct vdpa_device *vdev); | 411 | size_t (*get_config_size)(struct vdpa_device *vdev); |
| @@ -394,6 +427,7 @@ struct vdpa_config_ops { · 15 unmodified lines | |||
| 394 | u64 iova, u64 size, u64 pa, u32 perm, void *opaque); | 427 | u64 iova, u64 size, u64 pa, u32 perm, void *opaque); |
| 395 | int (*dma_unmap)(struct vdpa_device *vdev, unsigned int asid, | 428 | int (*dma_unmap)(struct vdpa_device *vdev, unsigned int asid, |
| 396 | u64 iova, u64 size); | 429 | u64 iova, u64 size); |
| 430 | int (*reset_map)(struct vdpa_device *vdev, unsigned int asid); | ||
| 397 | int (*set_group_asid)(struct vdpa_device *vdev, unsigned int group, | 431 | int (*set_group_asid)(struct vdpa_device *vdev, unsigned int group, |
| 398 | unsigned int asid); | 432 | unsigned int asid); |
| 399 | struct device *(*get_vq_dma_dev)(struct vdpa_device *vdev, u16 idx); | 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 | return vdev->dma_dev; | 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 | const struct vdpa_config_ops *ops = vdev->config; | 524 | const struct vdpa_config_ops *ops = vdev->config; |
| 491 | int ret; | 525 | int ret; |
| 492 | 526 | ||
| 493 | down_write(&vdev->cf_lock); | 527 | down_write(&vdev->cf_lock); |
| 494 | vdev->features_valid = false; | 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 | up_write(&vdev->cf_lock); | 533 | up_write(&vdev->cf_lock); |
| 497 | return ret; | 534 | return ret; |
| 498 | } | 535 | } |
| @@ -12,37 +12,48 @@ struct virtio_pci_modern_common_cfg { · 11 unmodified lines | |||
| 12 | __le16 queue_reset; /* read-write */ | 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 | struct virtio_pci_modern_device { | 37 | struct virtio_pci_modern_device { |
| 16 | struct pci_dev *pci_dev; | 38 | struct pci_dev *pci_dev; |
| 17 | 39 | ||
| 18 | struct virtio_pci_common_cfg __iomem *common; | 40 | struct virtio_pci_common_cfg __iomem *common; |
| 19 | /* Device-specific data (non-legacy mode) */ | ||
| 20 | void __iomem *device; | 41 | void __iomem *device; |
| 21 | /* Base of vq notifications (non-legacy mode). */ | ||
| 22 | void __iomem *notify_base; | 42 | void __iomem *notify_base; |
| 23 | /* Physical base of vq notifications */ | ||
| 24 | resource_size_t notify_pa; | 43 | resource_size_t notify_pa; |
| 25 | /* Where to read and clear interrupt */ | ||
| 26 | u8 __iomem *isr; | 44 | u8 __iomem *isr; |
| 27 | 45 | ||
| 28 | /* So we can sanity-check accesses. */ | ||
| 29 | size_t notify_len; | 46 | size_t notify_len; |
| 30 | size_t device_len; | 47 | size_t device_len; |
| 48 | size_t common_len; | ||
| 31 | 49 | ||
| 32 | /* Capability for when we need to map notifications per-vq. */ | ||
| 33 | int notify_map_cap; | 50 | int notify_map_cap; |
| 34 | 51 | ||
| 35 | /* Multiply queue_notify_off by this value. (non-legacy mode). */ | ||
| 36 | u32 notify_offset_multiplier; | 52 | u32 notify_offset_multiplier; |
| 37 | |||
| 38 | int modern_bars; | 53 | int modern_bars; |
| 39 | |||
| 40 | struct virtio_device_id id; | 54 | struct virtio_device_id id; |
| 41 | 55 | ||
| 42 | /* optional check for vendor virtio device, returns dev_id or -ERRNO */ | ||
| 43 | int (*device_id_check)(struct pci_dev *pdev); | 56 | int (*device_id_check)(struct pci_dev *pdev); |
| 44 | |||
| 45 | /* optional mask for devices with limited DMA space */ | ||
| 46 | u64 dma_mask; | 57 | u64 dma_mask; |
| 47 | }; | 58 | }; |
| 48 | 59 | ||
| @@ -219,4 +219,12 @@ · 218 unmodified lines | |||
| 219 | */ | 219 | */ |
| 220 | #define VHOST_VDPA_RESUME _IO(VHOST_VIRTIO, 0x7E) | 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 | #endif | 230 | #endif |
| @@ -185,5 +185,12 @@ struct vhost_vdpa_iova_range { · 184 unmodified lines | |||
| 185 | * DRIVER_OK | 185 | * DRIVER_OK |
| 186 | */ | 186 | */ |
| 187 | #define VHOST_BACKEND_F_ENABLE_AFTER_DRIVER_OK 0x6 | 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 | #endif | 196 | #endif |
| @@ -105,6 +105,11 @@ · 104 unmodified lines | |||
| 105 | */ | 105 | */ |
| 106 | #define VIRTIO_F_NOTIFICATION_DATA 38 | 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 | * This feature indicates that the driver can reset a queue individually. | 114 | * This feature indicates that the driver can reset a queue individually. |
| 110 | */ | 115 | */ |