diff mbox series

[v2,07/13] iommufd/viommu: Add iommufd_viommu_report_irq helper

Message ID 7e9842376e6235d9e3471356d035afe2bfe8f33b.1733263737.git.nicolinc@nvidia.com
State Superseded
Headers show
Series None | expand

Commit Message

Nicolin Chen Dec. 3, 2024, 10:10 p.m. UTC
Similar to iommu_report_device_fault, this allows IOMMU drivers to report,
from threaded IRQ handlers to user space hypervisors, IRQs or events that
belong to a vIOMMU.

Signed-off-by: Nicolin Chen <nicolinc@nvidia.com>
---
 include/linux/iommufd.h        |  9 ++++++++
 drivers/iommu/iommufd/driver.c | 41 ++++++++++++++++++++++++++++++++++
 2 files changed, 50 insertions(+)

Comments

Tian, Kevin Dec. 11, 2024, 8:05 a.m. UTC | #1
> From: Nicolin Chen <nicolinc@nvidia.com>
> Sent: Wednesday, December 4, 2024 6:10 AM
> 
> +/* Typically called in driver's threaded IRQ handler */
> +int iommufd_viommu_report_irq(struct iommufd_viommu *viommu,
> unsigned int type,
> +			      void *irq_ptr, size_t irq_len)
> +{
> +	struct iommufd_eventq_virq *eventq_virq;
> +	struct iommufd_virq *virq;
> +	int rc = 0;
> +
> +	might_sleep();

why is it required here but not in the iopf path?

> +
> +	if (!viommu)
> +		return -ENODEV;
> +	if (WARN_ON_ONCE(!irq_len || !irq_ptr))
> +		return -EINVAL;
> +
> +	down_read(&viommu->virqs_rwsem);
> +
> +	eventq_virq = iommufd_viommu_find_eventq_virq(viommu, type);
> +	if (!eventq_virq) {
> +		rc = -EOPNOTSUPP;
> +		goto out_unlock_vdev_ids;

s/out_unlock_vdev_ids/out_unlock_virqs/

> +	}
> +
> +	virq = kzalloc(sizeof(*virq) + irq_len, GFP_KERNEL);
> +	if (!virq) {
> +		rc = -ENOMEM;
> +		goto out_unlock_vdev_ids;
> +	}
> +	virq->irq_data = (void *)virq + sizeof(*virq);
> +	memcpy(virq->irq_data, irq_ptr, irq_len);
> +
> +	virq->eventq_virq = eventq_virq;
> +	virq->irq_len = irq_len;
> +
> +	iommufd_eventq_virq_handler(virq);
> +out_unlock_vdev_ids:
> +	up_read(&viommu->virqs_rwsem);
> +	return rc;
> +}
> +EXPORT_SYMBOL_NS_GPL(iommufd_viommu_report_irq, IOMMUFD);
> +
>  MODULE_DESCRIPTION("iommufd code shared with builtin modules");
>  MODULE_LICENSE("GPL");
> --
> 2.43.0
Nicolin Chen Dec. 12, 2024, 9:23 p.m. UTC | #2
On Wed, Dec 11, 2024 at 08:05:45AM +0000, Tian, Kevin wrote:
> > From: Nicolin Chen <nicolinc@nvidia.com>
> > Sent: Wednesday, December 4, 2024 6:10 AM
> > 
> > +/* Typically called in driver's threaded IRQ handler */
> > +int iommufd_viommu_report_irq(struct iommufd_viommu *viommu,
> > unsigned int type,
> > +			      void *irq_ptr, size_t irq_len)
> > +{
> > +	struct iommufd_eventq_virq *eventq_virq;
> > +	struct iommufd_virq *virq;
> > +	int rc = 0;
> > +
> > +	might_sleep();
> 
> why is it required here but not in the iopf path?

It might not be that *required* as there is a might_sleep inside
the down_read(). So, I can drop this.

> > +
> > +	if (!viommu)
> > +		return -ENODEV;
> > +	if (WARN_ON_ONCE(!irq_len || !irq_ptr))
> > +		return -EINVAL;
> > +
> > +	down_read(&viommu->virqs_rwsem);
> > +
> > +	eventq_virq = iommufd_viommu_find_eventq_virq(viommu, type);
> > +	if (!eventq_virq) {
> > +		rc = -EOPNOTSUPP;
> > +		goto out_unlock_vdev_ids;
> 
> s/out_unlock_vdev_ids/out_unlock_virqs/

Yes..

Thanks!
Nic
diff mbox series

Patch

diff --git a/include/linux/iommufd.h b/include/linux/iommufd.h
index 1f5376476cfa..2ce78edec4e9 100644
--- a/include/linux/iommufd.h
+++ b/include/linux/iommufd.h
@@ -192,6 +192,8 @@  struct device *iommufd_viommu_find_dev(struct iommufd_viommu *viommu,
 				       unsigned long vdev_id);
 unsigned long iommufd_viommu_get_vdev_id(struct iommufd_viommu *viommu,
 					 struct device *dev);
+int iommufd_viommu_report_irq(struct iommufd_viommu *viommu, unsigned int type,
+			      void *irq_ptr, size_t irq_len);
 #else /* !CONFIG_IOMMUFD_DRIVER_CORE */
 static inline struct iommufd_object *
 _iommufd_object_alloc(struct iommufd_ctx *ictx, size_t size,
@@ -211,6 +213,13 @@  iommufd_viommu_get_vdev_id(struct iommufd_viommu *viommu, struct device *dev)
 {
 	return 0;
 }
+
+static inline int iommufd_viommu_report_irq(struct iommufd_viommu *viommu,
+					    unsigned int type, void *irq_ptr,
+					    size_t irq_len)
+{
+	return -EOPNOTSUPP;
+}
 #endif /* CONFIG_IOMMUFD_DRIVER_CORE */
 
 /*
diff --git a/drivers/iommu/iommufd/driver.c b/drivers/iommu/iommufd/driver.c
index 817e430a11bc..339baa270d1e 100644
--- a/drivers/iommu/iommufd/driver.c
+++ b/drivers/iommu/iommufd/driver.c
@@ -67,5 +67,46 @@  unsigned long iommufd_viommu_get_vdev_id(struct iommufd_viommu *viommu,
 }
 EXPORT_SYMBOL_NS_GPL(iommufd_viommu_get_vdev_id, IOMMUFD);
 
+/* Typically called in driver's threaded IRQ handler */
+int iommufd_viommu_report_irq(struct iommufd_viommu *viommu, unsigned int type,
+			      void *irq_ptr, size_t irq_len)
+{
+	struct iommufd_eventq_virq *eventq_virq;
+	struct iommufd_virq *virq;
+	int rc = 0;
+
+	might_sleep();
+
+	if (!viommu)
+		return -ENODEV;
+	if (WARN_ON_ONCE(!irq_len || !irq_ptr))
+		return -EINVAL;
+
+	down_read(&viommu->virqs_rwsem);
+
+	eventq_virq = iommufd_viommu_find_eventq_virq(viommu, type);
+	if (!eventq_virq) {
+		rc = -EOPNOTSUPP;
+		goto out_unlock_vdev_ids;
+	}
+
+	virq = kzalloc(sizeof(*virq) + irq_len, GFP_KERNEL);
+	if (!virq) {
+		rc = -ENOMEM;
+		goto out_unlock_vdev_ids;
+	}
+	virq->irq_data = (void *)virq + sizeof(*virq);
+	memcpy(virq->irq_data, irq_ptr, irq_len);
+
+	virq->eventq_virq = eventq_virq;
+	virq->irq_len = irq_len;
+
+	iommufd_eventq_virq_handler(virq);
+out_unlock_vdev_ids:
+	up_read(&viommu->virqs_rwsem);
+	return rc;
+}
+EXPORT_SYMBOL_NS_GPL(iommufd_viommu_report_irq, IOMMUFD);
+
 MODULE_DESCRIPTION("iommufd code shared with builtin modules");
 MODULE_LICENSE("GPL");