iommufd: Make attach_handle generic than fault specific
"attach_handle" was added exclusively for the iommufd_fault_iopf_handler() used by IOPF/PRI use cases. Now, both the MSI and PASID series require to reuse the attach_handle for non-fault cases. Add a set of new attach/detach/replace helpers that does the attach_handle allocation/releasing/replacement in the common path and also handles those fault specific routines such as iopf enabling/disabling and auto response. This covers both non-fault and fault cases in a clean way, replacing those inline helpers in the header. The following patch will clean up those old helpers in the fault.c file. Link: https://patch.msgid.link/r/32687df01c02291d89986a9fca897bbbe2b10987.1738645017.git.nicolinc@nvidia.com Signed-off-by: Nicolin Chen <nicolinc@nvidia.com> Reviewed-by: Yi Liu <yi.l.liu@intel.com> Signed-off-by: Jason Gunthorpe <jgg@nvidia.com>pull/1193/head
parent
a64dcfb451
commit
fb21b1568a
|
|
@ -352,6 +352,111 @@ iommufd_device_attach_reserved_iova(struct iommufd_device *idev,
|
|||
return 0;
|
||||
}
|
||||
|
||||
/* The device attach/detach/replace helpers for attach_handle */
|
||||
|
||||
static int iommufd_hwpt_attach_device(struct iommufd_hw_pagetable *hwpt,
|
||||
struct iommufd_device *idev)
|
||||
{
|
||||
struct iommufd_attach_handle *handle;
|
||||
int rc;
|
||||
|
||||
lockdep_assert_held(&idev->igroup->lock);
|
||||
|
||||
handle = kzalloc(sizeof(*handle), GFP_KERNEL);
|
||||
if (!handle)
|
||||
return -ENOMEM;
|
||||
|
||||
if (hwpt->fault) {
|
||||
rc = iommufd_fault_iopf_enable(idev);
|
||||
if (rc)
|
||||
goto out_free_handle;
|
||||
}
|
||||
|
||||
handle->idev = idev;
|
||||
rc = iommu_attach_group_handle(hwpt->domain, idev->igroup->group,
|
||||
&handle->handle);
|
||||
if (rc)
|
||||
goto out_disable_iopf;
|
||||
|
||||
return 0;
|
||||
|
||||
out_disable_iopf:
|
||||
if (hwpt->fault)
|
||||
iommufd_fault_iopf_disable(idev);
|
||||
out_free_handle:
|
||||
kfree(handle);
|
||||
return rc;
|
||||
}
|
||||
|
||||
static struct iommufd_attach_handle *
|
||||
iommufd_device_get_attach_handle(struct iommufd_device *idev)
|
||||
{
|
||||
struct iommu_attach_handle *handle;
|
||||
|
||||
lockdep_assert_held(&idev->igroup->lock);
|
||||
|
||||
handle =
|
||||
iommu_attach_handle_get(idev->igroup->group, IOMMU_NO_PASID, 0);
|
||||
if (IS_ERR(handle))
|
||||
return NULL;
|
||||
return to_iommufd_handle(handle);
|
||||
}
|
||||
|
||||
static void iommufd_hwpt_detach_device(struct iommufd_hw_pagetable *hwpt,
|
||||
struct iommufd_device *idev)
|
||||
{
|
||||
struct iommufd_attach_handle *handle;
|
||||
|
||||
handle = iommufd_device_get_attach_handle(idev);
|
||||
iommu_detach_group_handle(hwpt->domain, idev->igroup->group);
|
||||
if (hwpt->fault) {
|
||||
iommufd_auto_response_faults(hwpt, handle);
|
||||
iommufd_fault_iopf_disable(idev);
|
||||
}
|
||||
kfree(handle);
|
||||
}
|
||||
|
||||
static int iommufd_hwpt_replace_device(struct iommufd_device *idev,
|
||||
struct iommufd_hw_pagetable *hwpt,
|
||||
struct iommufd_hw_pagetable *old)
|
||||
{
|
||||
struct iommufd_attach_handle *handle, *old_handle =
|
||||
iommufd_device_get_attach_handle(idev);
|
||||
int rc;
|
||||
|
||||
handle = kzalloc(sizeof(*handle), GFP_KERNEL);
|
||||
if (!handle)
|
||||
return -ENOMEM;
|
||||
|
||||
if (hwpt->fault && !old->fault) {
|
||||
rc = iommufd_fault_iopf_enable(idev);
|
||||
if (rc)
|
||||
goto out_free_handle;
|
||||
}
|
||||
|
||||
handle->idev = idev;
|
||||
rc = iommu_replace_group_handle(idev->igroup->group, hwpt->domain,
|
||||
&handle->handle);
|
||||
if (rc)
|
||||
goto out_disable_iopf;
|
||||
|
||||
if (old->fault) {
|
||||
iommufd_auto_response_faults(hwpt, old_handle);
|
||||
if (!hwpt->fault)
|
||||
iommufd_fault_iopf_disable(idev);
|
||||
}
|
||||
kfree(old_handle);
|
||||
|
||||
return 0;
|
||||
|
||||
out_disable_iopf:
|
||||
if (hwpt->fault && !old->fault)
|
||||
iommufd_fault_iopf_disable(idev);
|
||||
out_free_handle:
|
||||
kfree(handle);
|
||||
return rc;
|
||||
}
|
||||
|
||||
int iommufd_hw_pagetable_attach(struct iommufd_hw_pagetable *hwpt,
|
||||
struct iommufd_device *idev)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@
|
|||
#include "../iommu-priv.h"
|
||||
#include "iommufd_private.h"
|
||||
|
||||
static int iommufd_fault_iopf_enable(struct iommufd_device *idev)
|
||||
int iommufd_fault_iopf_enable(struct iommufd_device *idev)
|
||||
{
|
||||
struct device *dev = idev->dev;
|
||||
int ret;
|
||||
|
|
@ -50,7 +50,7 @@ static int iommufd_fault_iopf_enable(struct iommufd_device *idev)
|
|||
return ret;
|
||||
}
|
||||
|
||||
static void iommufd_fault_iopf_disable(struct iommufd_device *idev)
|
||||
void iommufd_fault_iopf_disable(struct iommufd_device *idev)
|
||||
{
|
||||
mutex_lock(&idev->iopf_lock);
|
||||
if (!WARN_ON(idev->iopf_enabled == 0)) {
|
||||
|
|
@ -98,8 +98,8 @@ int iommufd_fault_domain_attach_dev(struct iommufd_hw_pagetable *hwpt,
|
|||
return ret;
|
||||
}
|
||||
|
||||
static void iommufd_auto_response_faults(struct iommufd_hw_pagetable *hwpt,
|
||||
struct iommufd_attach_handle *handle)
|
||||
void iommufd_auto_response_faults(struct iommufd_hw_pagetable *hwpt,
|
||||
struct iommufd_attach_handle *handle)
|
||||
{
|
||||
struct iommufd_fault *fault = hwpt->fault;
|
||||
struct iopf_group *group, *next;
|
||||
|
|
|
|||
|
|
@ -504,35 +504,10 @@ int iommufd_fault_domain_replace_dev(struct iommufd_device *idev,
|
|||
struct iommufd_hw_pagetable *hwpt,
|
||||
struct iommufd_hw_pagetable *old);
|
||||
|
||||
static inline int iommufd_hwpt_attach_device(struct iommufd_hw_pagetable *hwpt,
|
||||
struct iommufd_device *idev)
|
||||
{
|
||||
if (hwpt->fault)
|
||||
return iommufd_fault_domain_attach_dev(hwpt, idev);
|
||||
|
||||
return iommu_attach_group(hwpt->domain, idev->igroup->group);
|
||||
}
|
||||
|
||||
static inline void iommufd_hwpt_detach_device(struct iommufd_hw_pagetable *hwpt,
|
||||
struct iommufd_device *idev)
|
||||
{
|
||||
if (hwpt->fault) {
|
||||
iommufd_fault_domain_detach_dev(hwpt, idev);
|
||||
return;
|
||||
}
|
||||
|
||||
iommu_detach_group(hwpt->domain, idev->igroup->group);
|
||||
}
|
||||
|
||||
static inline int iommufd_hwpt_replace_device(struct iommufd_device *idev,
|
||||
struct iommufd_hw_pagetable *hwpt,
|
||||
struct iommufd_hw_pagetable *old)
|
||||
{
|
||||
if (old->fault || hwpt->fault)
|
||||
return iommufd_fault_domain_replace_dev(idev, hwpt, old);
|
||||
|
||||
return iommu_group_replace_domain(idev->igroup->group, hwpt->domain);
|
||||
}
|
||||
int iommufd_fault_iopf_enable(struct iommufd_device *idev);
|
||||
void iommufd_fault_iopf_disable(struct iommufd_device *idev);
|
||||
void iommufd_auto_response_faults(struct iommufd_hw_pagetable *hwpt,
|
||||
struct iommufd_attach_handle *handle);
|
||||
|
||||
static inline struct iommufd_viommu *
|
||||
iommufd_get_viommu(struct iommufd_ucmd *ucmd, u32 id)
|
||||
|
|
|
|||
Loading…
Reference in New Issue