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

vfio/platform: Use the new device life cycle helpers

Move vfio_device_ops from platform core to platform drivers so device
specific init/cleanup can be added.

Introduce two new helpers vfio_platform_init/release_common() for the
use in driver @init/@release.

vfio_platform_probe/remove_common() will be deprecated.

Signed-off-by: Kevin Tian <kevin.tian@intel.com>
Reviewed-by: Jason Gunthorpe <jgg@nvidia.com>
Reviewed-by: Eric Auger <eric.auger@redhat.com>
Tested-by: Eric Auger <eric.auger@redhat.com>
Link: https://lore.kernel.org/r/20220921104401.38898-12-kevin.tian@intel.com
Signed-off-by: Alex Williamson <alex.williamson@redhat.com>

authored by

Kevin Tian and committed by
Alex Williamson
5f6c7e08 7566692c

+111 -23
+52 -14
drivers/vfio/platform/vfio_platform.c
··· 7 7 #include <linux/module.h> 8 8 #include <linux/slab.h> 9 9 #include <linux/vfio.h> 10 + #include <linux/pm_runtime.h> 10 11 #include <linux/platform_device.h> 11 12 12 13 #include "vfio_platform_private.h" ··· 37 36 return platform_get_irq_optional(pdev, i); 38 37 } 39 38 40 - static int vfio_platform_probe(struct platform_device *pdev) 39 + static int vfio_platform_init_dev(struct vfio_device *core_vdev) 41 40 { 42 - struct vfio_platform_device *vdev; 43 - int ret; 44 - 45 - vdev = kzalloc(sizeof(*vdev), GFP_KERNEL); 46 - if (!vdev) 47 - return -ENOMEM; 41 + struct vfio_platform_device *vdev = 42 + container_of(core_vdev, struct vfio_platform_device, vdev); 43 + struct platform_device *pdev = to_platform_device(core_vdev->dev); 48 44 49 45 vdev->opaque = (void *) pdev; 50 46 vdev->name = pdev->name; ··· 50 52 vdev->get_irq = get_platform_irq; 51 53 vdev->reset_required = reset_required; 52 54 53 - ret = vfio_platform_probe_common(vdev, &pdev->dev); 54 - if (ret) { 55 - kfree(vdev); 56 - return ret; 57 - } 55 + return vfio_platform_init_common(vdev); 56 + } 57 + 58 + static const struct vfio_device_ops vfio_platform_ops; 59 + static int vfio_platform_probe(struct platform_device *pdev) 60 + { 61 + struct vfio_platform_device *vdev; 62 + int ret; 63 + 64 + vdev = vfio_alloc_device(vfio_platform_device, vdev, &pdev->dev, 65 + &vfio_platform_ops); 66 + if (IS_ERR(vdev)) 67 + return PTR_ERR(vdev); 68 + 69 + ret = vfio_register_group_dev(&vdev->vdev); 70 + if (ret) 71 + goto out_put_vdev; 72 + 73 + pm_runtime_enable(&pdev->dev); 58 74 dev_set_drvdata(&pdev->dev, vdev); 59 75 return 0; 76 + 77 + out_put_vdev: 78 + vfio_put_device(&vdev->vdev); 79 + return ret; 80 + } 81 + 82 + static void vfio_platform_release_dev(struct vfio_device *core_vdev) 83 + { 84 + struct vfio_platform_device *vdev = 85 + container_of(core_vdev, struct vfio_platform_device, vdev); 86 + 87 + vfio_platform_release_common(vdev); 88 + vfio_free_device(core_vdev); 60 89 } 61 90 62 91 static int vfio_platform_remove(struct platform_device *pdev) 63 92 { 64 93 struct vfio_platform_device *vdev = dev_get_drvdata(&pdev->dev); 65 94 66 - vfio_platform_remove_common(vdev); 67 - kfree(vdev); 95 + vfio_unregister_group_dev(&vdev->vdev); 96 + pm_runtime_disable(vdev->device); 97 + vfio_put_device(&vdev->vdev); 68 98 return 0; 69 99 } 100 + 101 + static const struct vfio_device_ops vfio_platform_ops = { 102 + .name = "vfio-platform", 103 + .init = vfio_platform_init_dev, 104 + .release = vfio_platform_release_dev, 105 + .open_device = vfio_platform_open_device, 106 + .close_device = vfio_platform_close_device, 107 + .ioctl = vfio_platform_ioctl, 108 + .read = vfio_platform_read, 109 + .write = vfio_platform_write, 110 + .mmap = vfio_platform_mmap, 111 + }; 70 112 71 113 static struct platform_driver vfio_platform_driver = { 72 114 .probe = vfio_platform_probe,
+44 -9
drivers/vfio/platform/vfio_platform_common.c
··· 218 218 return -EINVAL; 219 219 } 220 220 221 - static void vfio_platform_close_device(struct vfio_device *core_vdev) 221 + void vfio_platform_close_device(struct vfio_device *core_vdev) 222 222 { 223 223 struct vfio_platform_device *vdev = 224 224 container_of(core_vdev, struct vfio_platform_device, vdev); ··· 236 236 vfio_platform_regions_cleanup(vdev); 237 237 vfio_platform_irq_cleanup(vdev); 238 238 } 239 + EXPORT_SYMBOL_GPL(vfio_platform_close_device); 239 240 240 - static int vfio_platform_open_device(struct vfio_device *core_vdev) 241 + int vfio_platform_open_device(struct vfio_device *core_vdev) 241 242 { 242 243 struct vfio_platform_device *vdev = 243 244 container_of(core_vdev, struct vfio_platform_device, vdev); ··· 274 273 vfio_platform_regions_cleanup(vdev); 275 274 return ret; 276 275 } 276 + EXPORT_SYMBOL_GPL(vfio_platform_open_device); 277 277 278 - static long vfio_platform_ioctl(struct vfio_device *core_vdev, 279 - unsigned int cmd, unsigned long arg) 278 + long vfio_platform_ioctl(struct vfio_device *core_vdev, 279 + unsigned int cmd, unsigned long arg) 280 280 { 281 281 struct vfio_platform_device *vdev = 282 282 container_of(core_vdev, struct vfio_platform_device, vdev); ··· 384 382 385 383 return -ENOTTY; 386 384 } 385 + EXPORT_SYMBOL_GPL(vfio_platform_ioctl); 387 386 388 387 static ssize_t vfio_platform_read_mmio(struct vfio_platform_region *reg, 389 388 char __user *buf, size_t count, ··· 441 438 return -EFAULT; 442 439 } 443 440 444 - static ssize_t vfio_platform_read(struct vfio_device *core_vdev, 445 - char __user *buf, size_t count, loff_t *ppos) 441 + ssize_t vfio_platform_read(struct vfio_device *core_vdev, 442 + char __user *buf, size_t count, loff_t *ppos) 446 443 { 447 444 struct vfio_platform_device *vdev = 448 445 container_of(core_vdev, struct vfio_platform_device, vdev); ··· 463 460 464 461 return -EINVAL; 465 462 } 463 + EXPORT_SYMBOL_GPL(vfio_platform_read); 466 464 467 465 static ssize_t vfio_platform_write_mmio(struct vfio_platform_region *reg, 468 466 const char __user *buf, size_t count, ··· 519 515 return -EFAULT; 520 516 } 521 517 522 - static ssize_t vfio_platform_write(struct vfio_device *core_vdev, const char __user *buf, 523 - size_t count, loff_t *ppos) 518 + ssize_t vfio_platform_write(struct vfio_device *core_vdev, const char __user *buf, 519 + size_t count, loff_t *ppos) 524 520 { 525 521 struct vfio_platform_device *vdev = 526 522 container_of(core_vdev, struct vfio_platform_device, vdev); ··· 541 537 542 538 return -EINVAL; 543 539 } 540 + EXPORT_SYMBOL_GPL(vfio_platform_write); 544 541 545 542 static int vfio_platform_mmap_mmio(struct vfio_platform_region region, 546 543 struct vm_area_struct *vma) ··· 563 558 req_len, vma->vm_page_prot); 564 559 } 565 560 566 - static int vfio_platform_mmap(struct vfio_device *core_vdev, struct vm_area_struct *vma) 561 + int vfio_platform_mmap(struct vfio_device *core_vdev, struct vm_area_struct *vma) 567 562 { 568 563 struct vfio_platform_device *vdev = 569 564 container_of(core_vdev, struct vfio_platform_device, vdev); ··· 603 598 604 599 return -EINVAL; 605 600 } 601 + EXPORT_SYMBOL_GPL(vfio_platform_mmap); 606 602 607 603 static const struct vfio_device_ops vfio_platform_ops = { 608 604 .name = "vfio-platform", ··· 645 639 * If the firmware is ACPI type, then acpi_disabled is 0. All other checks are 646 640 * valid checks. We cannot claim that this system is DT. 647 641 */ 642 + int vfio_platform_init_common(struct vfio_platform_device *vdev) 643 + { 644 + int ret; 645 + struct device *dev = vdev->vdev.dev; 646 + 647 + ret = vfio_platform_acpi_probe(vdev, dev); 648 + if (ret) 649 + ret = vfio_platform_of_probe(vdev, dev); 650 + 651 + if (ret) 652 + return ret; 653 + 654 + vdev->device = dev; 655 + mutex_init(&vdev->igate); 656 + 657 + ret = vfio_platform_get_reset(vdev); 658 + if (ret && vdev->reset_required) 659 + dev_err(dev, "No reset function found for device %s\n", 660 + vdev->name); 661 + return ret; 662 + } 663 + EXPORT_SYMBOL_GPL(vfio_platform_init_common); 664 + 665 + void vfio_platform_release_common(struct vfio_platform_device *vdev) 666 + { 667 + vfio_platform_put_reset(vdev); 668 + } 669 + EXPORT_SYMBOL_GPL(vfio_platform_release_common); 670 + 648 671 int vfio_platform_probe_common(struct vfio_platform_device *vdev, 649 672 struct device *dev) 650 673 {
+15
drivers/vfio/platform/vfio_platform_private.h
··· 81 81 int vfio_platform_probe_common(struct vfio_platform_device *vdev, 82 82 struct device *dev); 83 83 void vfio_platform_remove_common(struct vfio_platform_device *vdev); 84 + int vfio_platform_init_common(struct vfio_platform_device *vdev); 85 + void vfio_platform_release_common(struct vfio_platform_device *vdev); 86 + 87 + int vfio_platform_open_device(struct vfio_device *core_vdev); 88 + void vfio_platform_close_device(struct vfio_device *core_vdev); 89 + long vfio_platform_ioctl(struct vfio_device *core_vdev, 90 + unsigned int cmd, unsigned long arg); 91 + ssize_t vfio_platform_read(struct vfio_device *core_vdev, 92 + char __user *buf, size_t count, 93 + loff_t *ppos); 94 + ssize_t vfio_platform_write(struct vfio_device *core_vdev, 95 + const char __user *buf, 96 + size_t count, loff_t *ppos); 97 + int vfio_platform_mmap(struct vfio_device *core_vdev, 98 + struct vm_area_struct *vma); 84 99 85 100 int vfio_platform_irq_init(struct vfio_platform_device *vdev); 86 101 void vfio_platform_irq_cleanup(struct vfio_platform_device *vdev);