Message ID | 7e9842376e6235d9e3471356d035afe2bfe8f33b.1733263737.git.nicolinc@nvidia.com |
---|---|
State | Superseded |
Headers | show |
Series | None | expand |
> 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
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 --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");
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(+)