26
26
27
27
static irqreturn_t prq_event_thread (int irq , void * d );
28
28
29
- static DEFINE_XARRAY_ALLOC (pasid_private_array );
30
- static int pasid_private_add (ioasid_t pasid , void * priv )
31
- {
32
- return xa_alloc (& pasid_private_array , & pasid , priv ,
33
- XA_LIMIT (pasid , pasid ), GFP_ATOMIC );
34
- }
35
-
36
- static void pasid_private_remove (ioasid_t pasid )
37
- {
38
- xa_erase (& pasid_private_array , pasid );
39
- }
40
-
41
- static void * pasid_private_find (ioasid_t pasid )
42
- {
43
- return xa_load (& pasid_private_array , pasid );
44
- }
45
-
46
29
int intel_svm_enable_prq (struct intel_iommu * iommu )
47
30
{
48
31
struct iopf_queue * iopfq ;
@@ -156,10 +139,9 @@ static void intel_arch_invalidate_secondary_tlbs(struct mmu_notifier *mn,
156
139
struct mm_struct * mm ,
157
140
unsigned long start , unsigned long end )
158
141
{
159
- struct intel_svm * svm = container_of (mn , struct intel_svm , notifier );
160
- struct dmar_domain * domain = svm -> domain ;
142
+ struct dmar_domain * domain = container_of (mn , struct dmar_domain , notifier );
161
143
162
- if (start == 0 && end == -1UL ) {
144
+ if (start == 0 && end == ULONG_MAX ) {
163
145
cache_tag_flush_all (domain );
164
146
return ;
165
147
}
@@ -174,8 +156,7 @@ static void intel_arch_invalidate_secondary_tlbs(struct mmu_notifier *mn,
174
156
175
157
static void intel_mm_release (struct mmu_notifier * mn , struct mm_struct * mm )
176
158
{
177
- struct intel_svm * svm = container_of (mn , struct intel_svm , notifier );
178
- struct dmar_domain * domain = svm -> domain ;
159
+ struct dmar_domain * domain = container_of (mn , struct dmar_domain , notifier );
179
160
struct dev_pasid_info * dev_pasid ;
180
161
struct device_domain_info * info ;
181
162
unsigned long flags ;
@@ -202,9 +183,15 @@ static void intel_mm_release(struct mmu_notifier *mn, struct mm_struct *mm)
202
183
203
184
}
204
185
186
+ static void intel_mm_free_notifier (struct mmu_notifier * mn )
187
+ {
188
+ kfree (container_of (mn , struct dmar_domain , notifier ));
189
+ }
190
+
205
191
static const struct mmu_notifier_ops intel_mmuops = {
206
192
.release = intel_mm_release ,
207
193
.arch_invalidate_secondary_tlbs = intel_arch_invalidate_secondary_tlbs ,
194
+ .free_notifier = intel_mm_free_notifier ,
208
195
};
209
196
210
197
static int intel_svm_set_dev_pasid (struct iommu_domain * domain ,
@@ -215,40 +202,13 @@ static int intel_svm_set_dev_pasid(struct iommu_domain *domain,
215
202
struct intel_iommu * iommu = info -> iommu ;
216
203
struct mm_struct * mm = domain -> mm ;
217
204
struct dev_pasid_info * dev_pasid ;
218
- struct intel_svm * svm ;
219
205
unsigned long sflags ;
220
206
unsigned long flags ;
221
207
int ret = 0 ;
222
208
223
- svm = pasid_private_find (pasid );
224
- if (!svm ) {
225
- svm = kzalloc (sizeof (* svm ), GFP_KERNEL );
226
- if (!svm )
227
- return - ENOMEM ;
228
-
229
- svm -> pasid = pasid ;
230
- svm -> mm = mm ;
231
-
232
- svm -> notifier .ops = & intel_mmuops ;
233
- svm -> domain = to_dmar_domain (domain );
234
- ret = mmu_notifier_register (& svm -> notifier , mm );
235
- if (ret ) {
236
- kfree (svm );
237
- return ret ;
238
- }
239
-
240
- ret = pasid_private_add (svm -> pasid , svm );
241
- if (ret ) {
242
- mmu_notifier_unregister (& svm -> notifier , mm );
243
- kfree (svm );
244
- return ret ;
245
- }
246
- }
247
-
248
- dmar_domain -> svm = svm ;
249
209
dev_pasid = kzalloc (sizeof (* dev_pasid ), GFP_KERNEL );
250
210
if (!dev_pasid )
251
- goto free_svm ;
211
+ return - ENOMEM ;
252
212
253
213
dev_pasid -> dev = dev ;
254
214
dev_pasid -> pasid = pasid ;
@@ -274,30 +234,10 @@ static int intel_svm_set_dev_pasid(struct iommu_domain *domain,
274
234
cache_tag_unassign_domain (to_dmar_domain (domain ), dev , pasid );
275
235
free_dev_pasid :
276
236
kfree (dev_pasid );
277
- free_svm :
278
- if (list_empty (& dmar_domain -> dev_pasids )) {
279
- mmu_notifier_unregister (& svm -> notifier , mm );
280
- pasid_private_remove (pasid );
281
- kfree (svm );
282
- }
283
237
284
238
return ret ;
285
239
}
286
240
287
- void intel_svm_remove_dev_pasid (struct iommu_domain * domain )
288
- {
289
- struct dmar_domain * dmar_domain = to_dmar_domain (domain );
290
- struct intel_svm * svm = dmar_domain -> svm ;
291
- struct mm_struct * mm = domain -> mm ;
292
-
293
- if (list_empty (& dmar_domain -> dev_pasids )) {
294
- if (svm -> notifier .ops )
295
- mmu_notifier_unregister (& svm -> notifier , mm );
296
- pasid_private_remove (svm -> pasid );
297
- kfree (svm );
298
- }
299
- }
300
-
301
241
/* Page request queue descriptor */
302
242
struct page_req_dsc {
303
243
union {
@@ -611,27 +551,40 @@ void intel_svm_page_response(struct device *dev, struct iopf_fault *evt,
611
551
612
552
static void intel_svm_domain_free (struct iommu_domain * domain )
613
553
{
614
- kfree (to_dmar_domain (domain ));
554
+ struct dmar_domain * dmar_domain = to_dmar_domain (domain );
555
+
556
+ /* dmar_domain free is deferred to the mmu free_notifier callback. */
557
+ mmu_notifier_put (& dmar_domain -> notifier );
615
558
}
616
559
617
560
static const struct iommu_domain_ops intel_svm_domain_ops = {
618
561
.set_dev_pasid = intel_svm_set_dev_pasid ,
619
562
.free = intel_svm_domain_free
620
563
};
621
564
622
- struct iommu_domain * intel_svm_domain_alloc (void )
565
+ struct iommu_domain * intel_svm_domain_alloc (struct device * dev ,
566
+ struct mm_struct * mm )
623
567
{
624
568
struct dmar_domain * domain ;
569
+ int ret ;
625
570
626
571
domain = kzalloc (sizeof (* domain ), GFP_KERNEL );
627
572
if (!domain )
628
- return NULL ;
573
+ return ERR_PTR (- ENOMEM );
574
+
629
575
domain -> domain .ops = & intel_svm_domain_ops ;
630
576
domain -> use_first_level = true;
631
577
INIT_LIST_HEAD (& domain -> dev_pasids );
632
578
INIT_LIST_HEAD (& domain -> cache_tags );
633
579
spin_lock_init (& domain -> cache_lock );
634
580
spin_lock_init (& domain -> lock );
635
581
582
+ domain -> notifier .ops = & intel_mmuops ;
583
+ ret = mmu_notifier_register (& domain -> notifier , mm );
584
+ if (ret ) {
585
+ kfree (domain );
586
+ return ERR_PTR (ret );
587
+ }
588
+
636
589
return & domain -> domain ;
637
590
}
0 commit comments