nd_virtio.c 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136
  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 provides a virtio based flushing
  7. * interface.
  8. */
  9. #include "virtio_pmem.h"
  10. #include "nd.h"
  11. /* The interrupt handler */
  12. void virtio_pmem_host_ack(struct virtqueue *vq)
  13. {
  14. struct virtio_pmem *vpmem = vq->vdev->priv;
  15. struct virtio_pmem_request *req_data, *req_buf;
  16. unsigned long flags;
  17. unsigned int len;
  18. spin_lock_irqsave(&vpmem->pmem_lock, flags);
  19. while ((req_data = virtqueue_get_buf(vq, &len)) != NULL) {
  20. req_data->done = true;
  21. wake_up(&req_data->host_acked);
  22. if (!list_empty(&vpmem->req_list)) {
  23. req_buf = list_first_entry(&vpmem->req_list,
  24. struct virtio_pmem_request, list);
  25. req_buf->wq_buf_avail = true;
  26. wake_up(&req_buf->wq_buf);
  27. list_del(&req_buf->list);
  28. }
  29. }
  30. spin_unlock_irqrestore(&vpmem->pmem_lock, flags);
  31. }
  32. EXPORT_SYMBOL_GPL(virtio_pmem_host_ack);
  33. /* The request submission function */
  34. static int virtio_pmem_flush(struct nd_region *nd_region)
  35. {
  36. struct virtio_device *vdev = nd_region->provider_data;
  37. struct virtio_pmem *vpmem = vdev->priv;
  38. struct virtio_pmem_request *req_data;
  39. struct scatterlist *sgs[2], sg, ret;
  40. unsigned long flags;
  41. int err, err1;
  42. /*
  43. * Don't bother to submit the request to the device if the device is
  44. * not activated.
  45. */
  46. if (vdev->config->get_status(vdev) & VIRTIO_CONFIG_S_NEEDS_RESET) {
  47. dev_info(&vdev->dev, "virtio pmem device needs a reset\n");
  48. return -EIO;
  49. }
  50. might_sleep();
  51. req_data = kmalloc(sizeof(*req_data), GFP_KERNEL);
  52. if (!req_data)
  53. return -ENOMEM;
  54. req_data->done = false;
  55. init_waitqueue_head(&req_data->host_acked);
  56. init_waitqueue_head(&req_data->wq_buf);
  57. INIT_LIST_HEAD(&req_data->list);
  58. req_data->req.type = cpu_to_le32(VIRTIO_PMEM_REQ_TYPE_FLUSH);
  59. sg_init_one(&sg, &req_data->req, sizeof(req_data->req));
  60. sgs[0] = &sg;
  61. sg_init_one(&ret, &req_data->resp.ret, sizeof(req_data->resp));
  62. sgs[1] = &ret;
  63. spin_lock_irqsave(&vpmem->pmem_lock, flags);
  64. /*
  65. * If virtqueue_add_sgs returns -ENOSPC then req_vq virtual
  66. * queue does not have free descriptor. We add the request
  67. * to req_list and wait for host_ack to wake us up when free
  68. * slots are available.
  69. */
  70. while ((err = virtqueue_add_sgs(vpmem->req_vq, sgs, 1, 1, req_data,
  71. GFP_ATOMIC)) == -ENOSPC) {
  72. dev_info(&vdev->dev, "failed to send command to virtio pmem device, no free slots in the virtqueue\n");
  73. req_data->wq_buf_avail = false;
  74. list_add_tail(&req_data->list, &vpmem->req_list);
  75. spin_unlock_irqrestore(&vpmem->pmem_lock, flags);
  76. /* A host response results in "host_ack" getting called */
  77. wait_event(req_data->wq_buf, req_data->wq_buf_avail);
  78. spin_lock_irqsave(&vpmem->pmem_lock, flags);
  79. }
  80. err1 = virtqueue_kick(vpmem->req_vq);
  81. spin_unlock_irqrestore(&vpmem->pmem_lock, flags);
  82. /*
  83. * virtqueue_add_sgs failed with error different than -ENOSPC, we can't
  84. * do anything about that.
  85. */
  86. if (err || !err1) {
  87. dev_info(&vdev->dev, "failed to send command to virtio pmem device\n");
  88. err = -EIO;
  89. } else {
  90. /* A host repsonse results in "host_ack" getting called */
  91. wait_event(req_data->host_acked, req_data->done);
  92. err = le32_to_cpu(req_data->resp.ret);
  93. }
  94. kfree(req_data);
  95. return err;
  96. };
  97. /* The asynchronous flush callback function */
  98. int async_pmem_flush(struct nd_region *nd_region, struct bio *bio)
  99. {
  100. /*
  101. * Create child bio for asynchronous flush and chain with
  102. * parent bio. Otherwise directly call nd_region flush.
  103. */
  104. if (bio && bio->bi_iter.bi_sector != -1) {
  105. struct bio *child = bio_alloc(bio->bi_bdev, 0,
  106. REQ_OP_WRITE | REQ_PREFLUSH,
  107. GFP_ATOMIC);
  108. if (!child)
  109. return -ENOMEM;
  110. bio_clone_blkg_association(child, bio);
  111. child->bi_iter.bi_sector = -1;
  112. bio_chain(child, bio);
  113. submit_bio(child);
  114. return 0;
  115. }
  116. if (virtio_pmem_flush(nd_region))
  117. return -EIO;
  118. return 0;
  119. };
  120. EXPORT_SYMBOL_GPL(async_pmem_flush);
  121. MODULE_DESCRIPTION("Virtio Persistent Memory Driver");
  122. MODULE_LICENSE("GPL");