Skip to content

Commit fb21b15

Browse files
nicolincjgunthorpe
authored andcommitted
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 <[email protected]> Reviewed-by: Yi Liu <[email protected]> Signed-off-by: Jason Gunthorpe <[email protected]>
1 parent a64dcfb commit fb21b15

File tree

3 files changed

+113
-33
lines changed

3 files changed

+113
-33
lines changed

drivers/iommu/iommufd/device.c

Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -352,6 +352,111 @@ iommufd_device_attach_reserved_iova(struct iommufd_device *idev,
352352
return 0;
353353
}
354354

355+
/* The device attach/detach/replace helpers for attach_handle */
356+
357+
static int iommufd_hwpt_attach_device(struct iommufd_hw_pagetable *hwpt,
358+
struct iommufd_device *idev)
359+
{
360+
struct iommufd_attach_handle *handle;
361+
int rc;
362+
363+
lockdep_assert_held(&idev->igroup->lock);
364+
365+
handle = kzalloc(sizeof(*handle), GFP_KERNEL);
366+
if (!handle)
367+
return -ENOMEM;
368+
369+
if (hwpt->fault) {
370+
rc = iommufd_fault_iopf_enable(idev);
371+
if (rc)
372+
goto out_free_handle;
373+
}
374+
375+
handle->idev = idev;
376+
rc = iommu_attach_group_handle(hwpt->domain, idev->igroup->group,
377+
&handle->handle);
378+
if (rc)
379+
goto out_disable_iopf;
380+
381+
return 0;
382+
383+
out_disable_iopf:
384+
if (hwpt->fault)
385+
iommufd_fault_iopf_disable(idev);
386+
out_free_handle:
387+
kfree(handle);
388+
return rc;
389+
}
390+
391+
static struct iommufd_attach_handle *
392+
iommufd_device_get_attach_handle(struct iommufd_device *idev)
393+
{
394+
struct iommu_attach_handle *handle;
395+
396+
lockdep_assert_held(&idev->igroup->lock);
397+
398+
handle =
399+
iommu_attach_handle_get(idev->igroup->group, IOMMU_NO_PASID, 0);
400+
if (IS_ERR(handle))
401+
return NULL;
402+
return to_iommufd_handle(handle);
403+
}
404+
405+
static void iommufd_hwpt_detach_device(struct iommufd_hw_pagetable *hwpt,
406+
struct iommufd_device *idev)
407+
{
408+
struct iommufd_attach_handle *handle;
409+
410+
handle = iommufd_device_get_attach_handle(idev);
411+
iommu_detach_group_handle(hwpt->domain, idev->igroup->group);
412+
if (hwpt->fault) {
413+
iommufd_auto_response_faults(hwpt, handle);
414+
iommufd_fault_iopf_disable(idev);
415+
}
416+
kfree(handle);
417+
}
418+
419+
static int iommufd_hwpt_replace_device(struct iommufd_device *idev,
420+
struct iommufd_hw_pagetable *hwpt,
421+
struct iommufd_hw_pagetable *old)
422+
{
423+
struct iommufd_attach_handle *handle, *old_handle =
424+
iommufd_device_get_attach_handle(idev);
425+
int rc;
426+
427+
handle = kzalloc(sizeof(*handle), GFP_KERNEL);
428+
if (!handle)
429+
return -ENOMEM;
430+
431+
if (hwpt->fault && !old->fault) {
432+
rc = iommufd_fault_iopf_enable(idev);
433+
if (rc)
434+
goto out_free_handle;
435+
}
436+
437+
handle->idev = idev;
438+
rc = iommu_replace_group_handle(idev->igroup->group, hwpt->domain,
439+
&handle->handle);
440+
if (rc)
441+
goto out_disable_iopf;
442+
443+
if (old->fault) {
444+
iommufd_auto_response_faults(hwpt, old_handle);
445+
if (!hwpt->fault)
446+
iommufd_fault_iopf_disable(idev);
447+
}
448+
kfree(old_handle);
449+
450+
return 0;
451+
452+
out_disable_iopf:
453+
if (hwpt->fault && !old->fault)
454+
iommufd_fault_iopf_disable(idev);
455+
out_free_handle:
456+
kfree(handle);
457+
return rc;
458+
}
459+
355460
int iommufd_hw_pagetable_attach(struct iommufd_hw_pagetable *hwpt,
356461
struct iommufd_device *idev)
357462
{

drivers/iommu/iommufd/fault.c

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
#include "../iommu-priv.h"
1818
#include "iommufd_private.h"
1919

20-
static int iommufd_fault_iopf_enable(struct iommufd_device *idev)
20+
int iommufd_fault_iopf_enable(struct iommufd_device *idev)
2121
{
2222
struct device *dev = idev->dev;
2323
int ret;
@@ -50,7 +50,7 @@ static int iommufd_fault_iopf_enable(struct iommufd_device *idev)
5050
return ret;
5151
}
5252

53-
static void iommufd_fault_iopf_disable(struct iommufd_device *idev)
53+
void iommufd_fault_iopf_disable(struct iommufd_device *idev)
5454
{
5555
mutex_lock(&idev->iopf_lock);
5656
if (!WARN_ON(idev->iopf_enabled == 0)) {
@@ -98,8 +98,8 @@ int iommufd_fault_domain_attach_dev(struct iommufd_hw_pagetable *hwpt,
9898
return ret;
9999
}
100100

101-
static void iommufd_auto_response_faults(struct iommufd_hw_pagetable *hwpt,
102-
struct iommufd_attach_handle *handle)
101+
void iommufd_auto_response_faults(struct iommufd_hw_pagetable *hwpt,
102+
struct iommufd_attach_handle *handle)
103103
{
104104
struct iommufd_fault *fault = hwpt->fault;
105105
struct iopf_group *group, *next;

drivers/iommu/iommufd/iommufd_private.h

Lines changed: 4 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -504,35 +504,10 @@ int iommufd_fault_domain_replace_dev(struct iommufd_device *idev,
504504
struct iommufd_hw_pagetable *hwpt,
505505
struct iommufd_hw_pagetable *old);
506506

507-
static inline int iommufd_hwpt_attach_device(struct iommufd_hw_pagetable *hwpt,
508-
struct iommufd_device *idev)
509-
{
510-
if (hwpt->fault)
511-
return iommufd_fault_domain_attach_dev(hwpt, idev);
512-
513-
return iommu_attach_group(hwpt->domain, idev->igroup->group);
514-
}
515-
516-
static inline void iommufd_hwpt_detach_device(struct iommufd_hw_pagetable *hwpt,
517-
struct iommufd_device *idev)
518-
{
519-
if (hwpt->fault) {
520-
iommufd_fault_domain_detach_dev(hwpt, idev);
521-
return;
522-
}
523-
524-
iommu_detach_group(hwpt->domain, idev->igroup->group);
525-
}
526-
527-
static inline int iommufd_hwpt_replace_device(struct iommufd_device *idev,
528-
struct iommufd_hw_pagetable *hwpt,
529-
struct iommufd_hw_pagetable *old)
530-
{
531-
if (old->fault || hwpt->fault)
532-
return iommufd_fault_domain_replace_dev(idev, hwpt, old);
533-
534-
return iommu_group_replace_domain(idev->igroup->group, hwpt->domain);
535-
}
507+
int iommufd_fault_iopf_enable(struct iommufd_device *idev);
508+
void iommufd_fault_iopf_disable(struct iommufd_device *idev);
509+
void iommufd_auto_response_faults(struct iommufd_hw_pagetable *hwpt,
510+
struct iommufd_attach_handle *handle);
536511

537512
static inline struct iommufd_viommu *
538513
iommufd_get_viommu(struct iommufd_ucmd *ucmd, u32 id)

0 commit comments

Comments
 (0)