Skip to content

Commit cc7338e

Browse files
LuBaolujoergroedel
authored andcommitted
iommu: Refine locking for per-device fault data management
The per-device fault data is a data structure that is used to store information about faults that occur on a device. This data is allocated when IOPF is enabled on the device and freed when IOPF is disabled. The data is used in the paths of iopf reporting, handling, responding, and draining. The fault data is protected by two locks: - dev->iommu->lock: This lock is used to protect the allocation and freeing of the fault data. - dev->iommu->fault_parameter->lock: This lock is used to protect the fault data itself. Apply the locking mechanism to the fault reporting and responding paths. The fault_parameter->lock is also added in iopf_queue_discard_partial(). It does not fix any real issue, as iopf_queue_discard_partial() is only used in the VT-d driver's prq_event_thread(), which is a single-threaded path that reports the IOPFs. Signed-off-by: Lu Baolu <[email protected]> Reviewed-by: Kevin Tian <[email protected]> Reviewed-by: Jason Gunthorpe <[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 17c51a0 commit cc7338e

File tree

1 file changed

+30
-31
lines changed

1 file changed

+30
-31
lines changed

drivers/iommu/io-pgfault.c

Lines changed: 30 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ static struct iommu_domain *get_domain_for_iopf(struct device *dev,
5353
/**
5454
* iommu_handle_iopf - IO Page Fault handler
5555
* @fault: fault event
56-
* @dev: struct device.
56+
* @iopf_param: the fault parameter of the device.
5757
*
5858
* Add a fault to the device workqueue, to be handled by mm.
5959
*
@@ -90,29 +90,21 @@ static struct iommu_domain *get_domain_for_iopf(struct device *dev,
9090
*
9191
* Return: 0 on success and <0 on error.
9292
*/
93-
static int iommu_handle_iopf(struct iommu_fault *fault, struct device *dev)
93+
static int iommu_handle_iopf(struct iommu_fault *fault,
94+
struct iommu_fault_param *iopf_param)
9495
{
9596
int ret;
9697
struct iopf_group *group;
9798
struct iommu_domain *domain;
9899
struct iopf_fault *iopf, *next;
99-
struct iommu_fault_param *iopf_param;
100-
struct dev_iommu *param = dev->iommu;
100+
struct device *dev = iopf_param->dev;
101101

102-
lockdep_assert_held(&param->lock);
102+
lockdep_assert_held(&iopf_param->lock);
103103

104104
if (fault->type != IOMMU_FAULT_PAGE_REQ)
105105
/* Not a recoverable page fault */
106106
return -EOPNOTSUPP;
107107

108-
/*
109-
* As long as we're holding param->lock, the queue can't be unlinked
110-
* from the device and therefore cannot disappear.
111-
*/
112-
iopf_param = param->fault_param;
113-
if (!iopf_param)
114-
return -ENODEV;
115-
116108
if (!(fault->prm.flags & IOMMU_FAULT_PAGE_REQUEST_LAST_PAGE)) {
117109
iopf = kzalloc(sizeof(*iopf), GFP_KERNEL);
118110
if (!iopf)
@@ -186,18 +178,19 @@ static int iommu_handle_iopf(struct iommu_fault *fault, struct device *dev)
186178
*/
187179
int iommu_report_device_fault(struct device *dev, struct iopf_fault *evt)
188180
{
189-
struct dev_iommu *param = dev->iommu;
181+
struct iommu_fault_param *fault_param;
190182
struct iopf_fault *evt_pending = NULL;
191-
struct iommu_fault_param *fparam;
183+
struct dev_iommu *param = dev->iommu;
192184
int ret = 0;
193185

194-
if (!param || !evt)
195-
return -EINVAL;
196-
197-
/* we only report device fault if there is a handler registered */
198186
mutex_lock(&param->lock);
199-
fparam = param->fault_param;
187+
fault_param = param->fault_param;
188+
if (!fault_param) {
189+
mutex_unlock(&param->lock);
190+
return -EINVAL;
191+
}
200192

193+
mutex_lock(&fault_param->lock);
201194
if (evt->fault.type == IOMMU_FAULT_PAGE_REQ &&
202195
(evt->fault.prm.flags & IOMMU_FAULT_PAGE_REQUEST_LAST_PAGE)) {
203196
evt_pending = kmemdup(evt, sizeof(struct iopf_fault),
@@ -206,20 +199,18 @@ int iommu_report_device_fault(struct device *dev, struct iopf_fault *evt)
206199
ret = -ENOMEM;
207200
goto done_unlock;
208201
}
209-
mutex_lock(&fparam->lock);
210-
list_add_tail(&evt_pending->list, &fparam->faults);
211-
mutex_unlock(&fparam->lock);
202+
list_add_tail(&evt_pending->list, &fault_param->faults);
212203
}
213204

214-
ret = iommu_handle_iopf(&evt->fault, dev);
205+
ret = iommu_handle_iopf(&evt->fault, fault_param);
215206
if (ret && evt_pending) {
216-
mutex_lock(&fparam->lock);
217207
list_del(&evt_pending->list);
218-
mutex_unlock(&fparam->lock);
219208
kfree(evt_pending);
220209
}
221210
done_unlock:
211+
mutex_unlock(&fault_param->lock);
222212
mutex_unlock(&param->lock);
213+
223214
return ret;
224215
}
225216
EXPORT_SYMBOL_GPL(iommu_report_device_fault);
@@ -232,26 +223,31 @@ int iommu_page_response(struct device *dev,
232223
struct iopf_fault *evt;
233224
struct iommu_fault_page_request *prm;
234225
struct dev_iommu *param = dev->iommu;
226+
struct iommu_fault_param *fault_param;
235227
const struct iommu_ops *ops = dev_iommu_ops(dev);
236228
bool has_pasid = msg->flags & IOMMU_PAGE_RESP_PASID_VALID;
237229

238230
if (!ops->page_response)
239231
return -ENODEV;
240232

241-
if (!param || !param->fault_param)
233+
mutex_lock(&param->lock);
234+
fault_param = param->fault_param;
235+
if (!fault_param) {
236+
mutex_unlock(&param->lock);
242237
return -EINVAL;
238+
}
243239

244240
/* Only send response if there is a fault report pending */
245-
mutex_lock(&param->fault_param->lock);
246-
if (list_empty(&param->fault_param->faults)) {
241+
mutex_lock(&fault_param->lock);
242+
if (list_empty(&fault_param->faults)) {
247243
dev_warn_ratelimited(dev, "no pending PRQ, drop response\n");
248244
goto done_unlock;
249245
}
250246
/*
251247
* Check if we have a matching page request pending to respond,
252248
* otherwise return -EINVAL
253249
*/
254-
list_for_each_entry(evt, &param->fault_param->faults, list) {
250+
list_for_each_entry(evt, &fault_param->faults, list) {
255251
prm = &evt->fault.prm;
256252
if (prm->grpid != msg->grpid)
257253
continue;
@@ -279,7 +275,8 @@ int iommu_page_response(struct device *dev,
279275
}
280276

281277
done_unlock:
282-
mutex_unlock(&param->fault_param->lock);
278+
mutex_unlock(&fault_param->lock);
279+
mutex_unlock(&param->lock);
283280
return ret;
284281
}
285282
EXPORT_SYMBOL_GPL(iommu_page_response);
@@ -362,11 +359,13 @@ int iopf_queue_discard_partial(struct iopf_queue *queue)
362359

363360
mutex_lock(&queue->lock);
364361
list_for_each_entry(iopf_param, &queue->devices, queue_list) {
362+
mutex_lock(&iopf_param->lock);
365363
list_for_each_entry_safe(iopf, next, &iopf_param->partial,
366364
list) {
367365
list_del(&iopf->list);
368366
kfree(iopf);
369367
}
368+
mutex_unlock(&iopf_param->lock);
370369
}
371370
mutex_unlock(&queue->lock);
372371
return 0;

0 commit comments

Comments
 (0)