Skip to content

Commit 351ffcb

Browse files
LuBaolujoergroedel
authored andcommitted
iommu: Make iommu_queue_iopf() more generic
Make iommu_queue_iopf() more generic by making the iopf_group a minimal set of iopf's that an iopf handler of domain should handle and respond to. Add domain parameter to struct iopf_group so that the handler can retrieve and use it directly. Change iommu_queue_iopf() to forward groups of iopf's to the domain's iopf handler. This is also a necessary step to decouple the sva iopf handling code from this interface. Signed-off-by: Lu Baolu <[email protected]> Reviewed-by: Kevin Tian <[email protected]> Reviewed-by: Jason Gunthorpe <[email protected]> Reviewed-by: Yi Liu <[email protected]> Tested-by: Yan Zhao <[email protected]> Tested-by: Longfang Liu <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Joerg Roedel <[email protected]>
1 parent 24b5d26 commit 351ffcb

File tree

4 files changed

+61
-20
lines changed

4 files changed

+61
-20
lines changed

drivers/iommu/io-pgfault.c

Lines changed: 56 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,9 @@
1313

1414
#include "iommu-sva.h"
1515

16+
enum iommu_page_response_code
17+
iommu_sva_handle_mm(struct iommu_fault *fault, struct mm_struct *mm);
18+
1619
static void iopf_free_group(struct iopf_group *group)
1720
{
1821
struct iopf_fault *iopf, *next;
@@ -45,29 +48,48 @@ static void iopf_handler(struct work_struct *work)
4548
{
4649
struct iopf_fault *iopf;
4750
struct iopf_group *group;
48-
struct iommu_domain *domain;
4951
enum iommu_page_response_code status = IOMMU_PAGE_RESP_SUCCESS;
5052

5153
group = container_of(work, struct iopf_group, work);
52-
domain = iommu_get_domain_for_dev_pasid(group->dev,
53-
group->last_fault.fault.prm.pasid, 0);
54-
if (!domain || !domain->iopf_handler)
55-
status = IOMMU_PAGE_RESP_INVALID;
56-
5754
list_for_each_entry(iopf, &group->faults, list) {
5855
/*
5956
* For the moment, errors are sticky: don't handle subsequent
6057
* faults in the group if there is an error.
6158
*/
62-
if (status == IOMMU_PAGE_RESP_SUCCESS)
63-
status = domain->iopf_handler(&iopf->fault,
64-
domain->fault_data);
59+
if (status != IOMMU_PAGE_RESP_SUCCESS)
60+
break;
61+
62+
status = iommu_sva_handle_mm(&iopf->fault, group->domain->mm);
6563
}
6664

6765
iopf_complete_group(group->dev, &group->last_fault, status);
6866
iopf_free_group(group);
6967
}
7068

69+
static struct iommu_domain *get_domain_for_iopf(struct device *dev,
70+
struct iommu_fault *fault)
71+
{
72+
struct iommu_domain *domain;
73+
74+
if (fault->prm.flags & IOMMU_FAULT_PAGE_REQUEST_PASID_VALID) {
75+
domain = iommu_get_domain_for_dev_pasid(dev, fault->prm.pasid, 0);
76+
if (IS_ERR(domain))
77+
domain = NULL;
78+
} else {
79+
domain = iommu_get_domain_for_dev(dev);
80+
}
81+
82+
if (!domain || !domain->iopf_handler) {
83+
dev_warn_ratelimited(dev,
84+
"iopf (pasid %d) without domain attached or handler installed\n",
85+
fault->prm.pasid);
86+
87+
return NULL;
88+
}
89+
90+
return domain;
91+
}
92+
7193
/**
7294
* iommu_queue_iopf - IO Page Fault handler
7395
* @fault: fault event
@@ -112,6 +134,7 @@ int iommu_queue_iopf(struct iommu_fault *fault, struct device *dev)
112134
{
113135
int ret;
114136
struct iopf_group *group;
137+
struct iommu_domain *domain;
115138
struct iopf_fault *iopf, *next;
116139
struct iommu_fault_param *iopf_param;
117140
struct dev_iommu *param = dev->iommu;
@@ -143,6 +166,12 @@ int iommu_queue_iopf(struct iommu_fault *fault, struct device *dev)
143166
return 0;
144167
}
145168

169+
domain = get_domain_for_iopf(dev, fault);
170+
if (!domain) {
171+
ret = -EINVAL;
172+
goto cleanup_partial;
173+
}
174+
146175
group = kzalloc(sizeof(*group), GFP_KERNEL);
147176
if (!group) {
148177
/*
@@ -157,8 +186,8 @@ int iommu_queue_iopf(struct iommu_fault *fault, struct device *dev)
157186
group->dev = dev;
158187
group->last_fault.fault = *fault;
159188
INIT_LIST_HEAD(&group->faults);
189+
group->domain = domain;
160190
list_add(&group->last_fault.list, &group->faults);
161-
INIT_WORK(&group->work, iopf_handler);
162191

163192
/* See if we have partial faults for this group */
164193
list_for_each_entry_safe(iopf, next, &iopf_param->partial, list) {
@@ -167,9 +196,13 @@ int iommu_queue_iopf(struct iommu_fault *fault, struct device *dev)
167196
list_move(&iopf->list, &group->faults);
168197
}
169198

170-
queue_work(iopf_param->queue->wq, &group->work);
171-
return 0;
199+
mutex_unlock(&iopf_param->lock);
200+
ret = domain->iopf_handler(group);
201+
mutex_lock(&iopf_param->lock);
202+
if (ret)
203+
iopf_free_group(group);
172204

205+
return ret;
173206
cleanup_partial:
174207
list_for_each_entry_safe(iopf, next, &iopf_param->partial, list) {
175208
if (iopf->fault.prm.grpid == fault->prm.grpid) {
@@ -181,6 +214,17 @@ int iommu_queue_iopf(struct iommu_fault *fault, struct device *dev)
181214
}
182215
EXPORT_SYMBOL_GPL(iommu_queue_iopf);
183216

217+
int iommu_sva_handle_iopf(struct iopf_group *group)
218+
{
219+
struct iommu_fault_param *fault_param = group->dev->iommu->fault_param;
220+
221+
INIT_WORK(&group->work, iopf_handler);
222+
if (!queue_work(fault_param->queue->wq, &group->work))
223+
return -EBUSY;
224+
225+
return 0;
226+
}
227+
184228
/**
185229
* iopf_queue_flush_dev - Ensure that all queued faults have been processed
186230
* @dev: the endpoint whose faults need to be flushed.

drivers/iommu/iommu-sva.c

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -163,11 +163,10 @@ EXPORT_SYMBOL_GPL(iommu_sva_get_pasid);
163163
* I/O page fault handler for SVA
164164
*/
165165
enum iommu_page_response_code
166-
iommu_sva_handle_iopf(struct iommu_fault *fault, void *data)
166+
iommu_sva_handle_mm(struct iommu_fault *fault, struct mm_struct *mm)
167167
{
168168
vm_fault_t ret;
169169
struct vm_area_struct *vma;
170-
struct mm_struct *mm = data;
171170
unsigned int access_flags = 0;
172171
unsigned int fault_flags = FAULT_FLAG_REMOTE;
173172
struct iommu_fault_page_request *prm = &fault->prm;

drivers/iommu/iommu-sva.h

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,7 @@ int iopf_queue_flush_dev(struct device *dev);
2222
struct iopf_queue *iopf_queue_alloc(const char *name);
2323
void iopf_queue_free(struct iopf_queue *queue);
2424
int iopf_queue_discard_partial(struct iopf_queue *queue);
25-
enum iommu_page_response_code
26-
iommu_sva_handle_iopf(struct iommu_fault *fault, void *data);
25+
int iommu_sva_handle_iopf(struct iopf_group *group);
2726

2827
#else /* CONFIG_IOMMU_SVA */
2928
static inline int iommu_queue_iopf(struct iommu_fault *fault, struct device *dev)
@@ -62,8 +61,7 @@ static inline int iopf_queue_discard_partial(struct iopf_queue *queue)
6261
return -ENODEV;
6362
}
6463

65-
static inline enum iommu_page_response_code
66-
iommu_sva_handle_iopf(struct iommu_fault *fault, void *data)
64+
static inline int iommu_sva_handle_iopf(struct iopf_group *group)
6765
{
6866
return IOMMU_PAGE_RESP_INVALID;
6967
}

include/linux/iommu.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,7 @@ struct iopf_group {
130130
struct list_head faults;
131131
struct work_struct work;
132132
struct device *dev;
133+
struct iommu_domain *domain;
133134
};
134135

135136
/**
@@ -209,8 +210,7 @@ struct iommu_domain {
209210
unsigned long pgsize_bitmap; /* Bitmap of page sizes in use */
210211
struct iommu_domain_geometry geometry;
211212
struct iommu_dma_cookie *iova_cookie;
212-
enum iommu_page_response_code (*iopf_handler)(struct iommu_fault *fault,
213-
void *data);
213+
int (*iopf_handler)(struct iopf_group *group);
214214
void *fault_data;
215215
union {
216216
struct {

0 commit comments

Comments
 (0)