vfio_fsl_mc_intr.c 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194
  1. // SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause)
  2. /*
  3. * Copyright 2013-2016 Freescale Semiconductor Inc.
  4. * Copyright 2019 NXP
  5. */
  6. #include <linux/vfio.h>
  7. #include <linux/slab.h>
  8. #include <linux/types.h>
  9. #include <linux/eventfd.h>
  10. #include <linux/msi.h>
  11. #include "linux/fsl/mc.h"
  12. #include "vfio_fsl_mc_private.h"
  13. static int vfio_fsl_mc_irqs_allocate(struct vfio_fsl_mc_device *vdev)
  14. {
  15. struct fsl_mc_device *mc_dev = vdev->mc_dev;
  16. struct vfio_fsl_mc_irq *mc_irq;
  17. int irq_count;
  18. int ret, i;
  19. /* Device does not support any interrupt */
  20. if (mc_dev->obj_desc.irq_count == 0)
  21. return 0;
  22. /* interrupts were already allocated for this device */
  23. if (vdev->mc_irqs)
  24. return 0;
  25. irq_count = mc_dev->obj_desc.irq_count;
  26. mc_irq = kcalloc(irq_count, sizeof(*mc_irq), GFP_KERNEL);
  27. if (!mc_irq)
  28. return -ENOMEM;
  29. /* Allocate IRQs */
  30. ret = fsl_mc_allocate_irqs(mc_dev);
  31. if (ret) {
  32. kfree(mc_irq);
  33. return ret;
  34. }
  35. for (i = 0; i < irq_count; i++) {
  36. mc_irq[i].count = 1;
  37. mc_irq[i].flags = VFIO_IRQ_INFO_EVENTFD;
  38. }
  39. vdev->mc_irqs = mc_irq;
  40. return 0;
  41. }
  42. static irqreturn_t vfio_fsl_mc_irq_handler(int irq_num, void *arg)
  43. {
  44. struct vfio_fsl_mc_irq *mc_irq = (struct vfio_fsl_mc_irq *)arg;
  45. eventfd_signal(mc_irq->trigger, 1);
  46. return IRQ_HANDLED;
  47. }
  48. static int vfio_set_trigger(struct vfio_fsl_mc_device *vdev,
  49. int index, int fd)
  50. {
  51. struct vfio_fsl_mc_irq *irq = &vdev->mc_irqs[index];
  52. struct eventfd_ctx *trigger;
  53. int hwirq;
  54. int ret;
  55. hwirq = vdev->mc_dev->irqs[index]->msi_desc->irq;
  56. if (irq->trigger) {
  57. free_irq(hwirq, irq);
  58. kfree(irq->name);
  59. eventfd_ctx_put(irq->trigger);
  60. irq->trigger = NULL;
  61. }
  62. if (fd < 0) /* Disable only */
  63. return 0;
  64. irq->name = kasprintf(GFP_KERNEL, "vfio-irq[%d](%s)",
  65. hwirq, dev_name(&vdev->mc_dev->dev));
  66. if (!irq->name)
  67. return -ENOMEM;
  68. trigger = eventfd_ctx_fdget(fd);
  69. if (IS_ERR(trigger)) {
  70. kfree(irq->name);
  71. return PTR_ERR(trigger);
  72. }
  73. irq->trigger = trigger;
  74. ret = request_irq(hwirq, vfio_fsl_mc_irq_handler, 0,
  75. irq->name, irq);
  76. if (ret) {
  77. kfree(irq->name);
  78. eventfd_ctx_put(trigger);
  79. irq->trigger = NULL;
  80. return ret;
  81. }
  82. return 0;
  83. }
  84. static int vfio_fsl_mc_set_irq_trigger(struct vfio_fsl_mc_device *vdev,
  85. unsigned int index, unsigned int start,
  86. unsigned int count, u32 flags,
  87. void *data)
  88. {
  89. struct fsl_mc_device *mc_dev = vdev->mc_dev;
  90. int ret, hwirq;
  91. struct vfio_fsl_mc_irq *irq;
  92. struct device *cont_dev = fsl_mc_cont_dev(&mc_dev->dev);
  93. struct fsl_mc_device *mc_cont = to_fsl_mc_device(cont_dev);
  94. if (!count && (flags & VFIO_IRQ_SET_DATA_NONE))
  95. return vfio_set_trigger(vdev, index, -1);
  96. if (start != 0 || count != 1)
  97. return -EINVAL;
  98. mutex_lock(&vdev->reflck->lock);
  99. ret = fsl_mc_populate_irq_pool(mc_cont,
  100. FSL_MC_IRQ_POOL_MAX_TOTAL_IRQS);
  101. if (ret)
  102. goto unlock;
  103. ret = vfio_fsl_mc_irqs_allocate(vdev);
  104. if (ret)
  105. goto unlock;
  106. mutex_unlock(&vdev->reflck->lock);
  107. if (flags & VFIO_IRQ_SET_DATA_EVENTFD) {
  108. s32 fd = *(s32 *)data;
  109. return vfio_set_trigger(vdev, index, fd);
  110. }
  111. hwirq = vdev->mc_dev->irqs[index]->msi_desc->irq;
  112. irq = &vdev->mc_irqs[index];
  113. if (flags & VFIO_IRQ_SET_DATA_NONE) {
  114. vfio_fsl_mc_irq_handler(hwirq, irq);
  115. } else if (flags & VFIO_IRQ_SET_DATA_BOOL) {
  116. u8 trigger = *(u8 *)data;
  117. if (trigger)
  118. vfio_fsl_mc_irq_handler(hwirq, irq);
  119. }
  120. return 0;
  121. unlock:
  122. mutex_unlock(&vdev->reflck->lock);
  123. return ret;
  124. }
  125. int vfio_fsl_mc_set_irqs_ioctl(struct vfio_fsl_mc_device *vdev,
  126. u32 flags, unsigned int index,
  127. unsigned int start, unsigned int count,
  128. void *data)
  129. {
  130. if (flags & VFIO_IRQ_SET_ACTION_TRIGGER)
  131. return vfio_fsl_mc_set_irq_trigger(vdev, index, start,
  132. count, flags, data);
  133. else
  134. return -EINVAL;
  135. }
  136. /* Free All IRQs for the given MC object */
  137. void vfio_fsl_mc_irqs_cleanup(struct vfio_fsl_mc_device *vdev)
  138. {
  139. struct fsl_mc_device *mc_dev = vdev->mc_dev;
  140. int irq_count = mc_dev->obj_desc.irq_count;
  141. int i;
  142. /*
  143. * Device does not support any interrupt or the interrupts
  144. * were not configured
  145. */
  146. if (!vdev->mc_irqs)
  147. return;
  148. for (i = 0; i < irq_count; i++)
  149. vfio_set_trigger(vdev, i, -1);
  150. fsl_mc_free_irqs(mc_dev);
  151. kfree(vdev->mc_irqs);
  152. vdev->mc_irqs = NULL;
  153. }