virtio_pmem.c 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129
  1. // SPDX-License-Identifier: GPL-2.0
  2. /*
  3. * virtio_pmem.c: Virtio pmem Driver
  4. *
  5. * Discovers persistent memory range information
  6. * from host and registers the virtual pmem device
  7. * with libnvdimm core.
  8. */
  9. #include "virtio_pmem.h"
  10. #include "nd.h"
  11. static struct virtio_device_id id_table[] = {
  12. { VIRTIO_ID_PMEM, VIRTIO_DEV_ANY_ID },
  13. { 0 },
  14. };
  15. /* Initialize virt queue */
  16. static int init_vq(struct virtio_pmem *vpmem)
  17. {
  18. /* single vq */
  19. vpmem->req_vq = virtio_find_single_vq(vpmem->vdev,
  20. virtio_pmem_host_ack, "flush_queue");
  21. if (IS_ERR(vpmem->req_vq))
  22. return PTR_ERR(vpmem->req_vq);
  23. spin_lock_init(&vpmem->pmem_lock);
  24. INIT_LIST_HEAD(&vpmem->req_list);
  25. return 0;
  26. };
  27. static int virtio_pmem_probe(struct virtio_device *vdev)
  28. {
  29. struct nd_region_desc ndr_desc = {};
  30. int nid = dev_to_node(&vdev->dev);
  31. struct nd_region *nd_region;
  32. struct virtio_pmem *vpmem;
  33. struct resource res;
  34. int err = 0;
  35. if (!vdev->config->get) {
  36. dev_err(&vdev->dev, "%s failure: config access disabled\n",
  37. __func__);
  38. return -EINVAL;
  39. }
  40. vpmem = devm_kzalloc(&vdev->dev, sizeof(*vpmem), GFP_KERNEL);
  41. if (!vpmem) {
  42. err = -ENOMEM;
  43. goto out_err;
  44. }
  45. vpmem->vdev = vdev;
  46. vdev->priv = vpmem;
  47. err = init_vq(vpmem);
  48. if (err) {
  49. dev_err(&vdev->dev, "failed to initialize virtio pmem vq's\n");
  50. goto out_err;
  51. }
  52. virtio_cread_le(vpmem->vdev, struct virtio_pmem_config,
  53. start, &vpmem->start);
  54. virtio_cread_le(vpmem->vdev, struct virtio_pmem_config,
  55. size, &vpmem->size);
  56. res.start = vpmem->start;
  57. res.end = vpmem->start + vpmem->size - 1;
  58. vpmem->nd_desc.provider_name = "virtio-pmem";
  59. vpmem->nd_desc.module = THIS_MODULE;
  60. vpmem->nvdimm_bus = nvdimm_bus_register(&vdev->dev,
  61. &vpmem->nd_desc);
  62. if (!vpmem->nvdimm_bus) {
  63. dev_err(&vdev->dev, "failed to register device with nvdimm_bus\n");
  64. err = -ENXIO;
  65. goto out_vq;
  66. }
  67. dev_set_drvdata(&vdev->dev, vpmem->nvdimm_bus);
  68. ndr_desc.res = &res;
  69. ndr_desc.numa_node = nid;
  70. ndr_desc.flush = async_pmem_flush;
  71. ndr_desc.provider_data = vdev;
  72. set_bit(ND_REGION_PAGEMAP, &ndr_desc.flags);
  73. set_bit(ND_REGION_ASYNC, &ndr_desc.flags);
  74. /*
  75. * The NVDIMM region could be available before the
  76. * virtio_device_ready() that is called by
  77. * virtio_dev_probe(), so we set device ready here.
  78. */
  79. virtio_device_ready(vdev);
  80. nd_region = nvdimm_pmem_region_create(vpmem->nvdimm_bus, &ndr_desc);
  81. if (!nd_region) {
  82. dev_err(&vdev->dev, "failed to create nvdimm region\n");
  83. err = -ENXIO;
  84. goto out_nd;
  85. }
  86. return 0;
  87. out_nd:
  88. virtio_reset_device(vdev);
  89. nvdimm_bus_unregister(vpmem->nvdimm_bus);
  90. out_vq:
  91. vdev->config->del_vqs(vdev);
  92. out_err:
  93. return err;
  94. }
  95. static void virtio_pmem_remove(struct virtio_device *vdev)
  96. {
  97. struct nvdimm_bus *nvdimm_bus = dev_get_drvdata(&vdev->dev);
  98. nvdimm_bus_unregister(nvdimm_bus);
  99. vdev->config->del_vqs(vdev);
  100. virtio_reset_device(vdev);
  101. }
  102. static struct virtio_driver virtio_pmem_driver = {
  103. .driver.name = KBUILD_MODNAME,
  104. .driver.owner = THIS_MODULE,
  105. .id_table = id_table,
  106. .probe = virtio_pmem_probe,
  107. .remove = virtio_pmem_remove,
  108. };
  109. module_virtio_driver(virtio_pmem_driver);
  110. MODULE_DEVICE_TABLE(virtio, id_table);
  111. MODULE_DESCRIPTION("Virtio pmem driver");
  112. MODULE_LICENSE("GPL");