@@ -23,6 +23,13 @@ struct idxd_cdev_context {
23
23
struct ida minor_ida ;
24
24
};
25
25
26
+ /*
27
+ * Since user file names are global in DSA devices, define their ida's as
28
+ * global to avoid conflict file names.
29
+ */
30
+ static DEFINE_IDA (file_ida );
31
+ static DEFINE_MUTEX (ida_lock );
32
+
26
33
/*
27
34
* ictx is an array based off of accelerator types. enum idxd_type
28
35
* is used as index
@@ -39,7 +46,60 @@ struct idxd_user_context {
39
46
struct mm_struct * mm ;
40
47
unsigned int flags ;
41
48
struct iommu_sva * sva ;
49
+ struct idxd_dev idxd_dev ;
42
50
u64 counters [COUNTER_MAX ];
51
+ int id ;
52
+ };
53
+
54
+ static void idxd_cdev_evl_drain_pasid (struct idxd_wq * wq , u32 pasid );
55
+ static void idxd_xa_pasid_remove (struct idxd_user_context * ctx );
56
+
57
+ static inline struct idxd_user_context * dev_to_uctx (struct device * dev )
58
+ {
59
+ struct idxd_dev * idxd_dev = confdev_to_idxd_dev (dev );
60
+
61
+ return container_of (idxd_dev , struct idxd_user_context , idxd_dev );
62
+ }
63
+
64
+ static void idxd_file_dev_release (struct device * dev )
65
+ {
66
+ struct idxd_user_context * ctx = dev_to_uctx (dev );
67
+ struct idxd_wq * wq = ctx -> wq ;
68
+ struct idxd_device * idxd = wq -> idxd ;
69
+ int rc ;
70
+
71
+ mutex_lock (& ida_lock );
72
+ ida_free (& file_ida , ctx -> id );
73
+ mutex_unlock (& ida_lock );
74
+
75
+ /* Wait for in-flight operations to complete. */
76
+ if (wq_shared (wq )) {
77
+ idxd_device_drain_pasid (idxd , ctx -> pasid );
78
+ } else {
79
+ if (device_user_pasid_enabled (idxd )) {
80
+ /* The wq disable in the disable pasid function will drain the wq */
81
+ rc = idxd_wq_disable_pasid (wq );
82
+ if (rc < 0 )
83
+ dev_err (dev , "wq disable pasid failed.\n" );
84
+ } else {
85
+ idxd_wq_drain (wq );
86
+ }
87
+ }
88
+
89
+ if (ctx -> sva ) {
90
+ idxd_cdev_evl_drain_pasid (wq , ctx -> pasid );
91
+ iommu_sva_unbind_device (ctx -> sva );
92
+ idxd_xa_pasid_remove (ctx );
93
+ }
94
+ kfree (ctx );
95
+ mutex_lock (& wq -> wq_lock );
96
+ idxd_wq_put (wq );
97
+ mutex_unlock (& wq -> wq_lock );
98
+ }
99
+
100
+ static struct device_type idxd_cdev_file_type = {
101
+ .name = "idxd_file" ,
102
+ .release = idxd_file_dev_release ,
43
103
};
44
104
45
105
static void idxd_cdev_dev_release (struct device * dev )
@@ -107,10 +167,11 @@ static int idxd_cdev_open(struct inode *inode, struct file *filp)
107
167
struct idxd_user_context * ctx ;
108
168
struct idxd_device * idxd ;
109
169
struct idxd_wq * wq ;
110
- struct device * dev ;
170
+ struct device * dev , * fdev ;
111
171
int rc = 0 ;
112
172
struct iommu_sva * sva ;
113
173
unsigned int pasid ;
174
+ struct idxd_cdev * idxd_cdev ;
114
175
115
176
wq = inode_wq (inode );
116
177
idxd = wq -> idxd ;
@@ -166,10 +227,41 @@ static int idxd_cdev_open(struct inode *inode, struct file *filp)
166
227
}
167
228
}
168
229
230
+ idxd_cdev = wq -> idxd_cdev ;
231
+ mutex_lock (& ida_lock );
232
+ ctx -> id = ida_alloc (& file_ida , GFP_KERNEL );
233
+ mutex_unlock (& ida_lock );
234
+ if (ctx -> id < 0 ) {
235
+ dev_warn (dev , "ida alloc failure\n" );
236
+ goto failed_ida ;
237
+ }
238
+ ctx -> idxd_dev .type = IDXD_DEV_CDEV_FILE ;
239
+ fdev = user_ctx_dev (ctx );
240
+ device_initialize (fdev );
241
+ fdev -> parent = cdev_dev (idxd_cdev );
242
+ fdev -> bus = & dsa_bus_type ;
243
+ fdev -> type = & idxd_cdev_file_type ;
244
+
245
+ rc = dev_set_name (fdev , "file%d" , ctx -> id );
246
+ if (rc < 0 ) {
247
+ dev_warn (dev , "set name failure\n" );
248
+ goto failed_dev_name ;
249
+ }
250
+
251
+ rc = device_add (fdev );
252
+ if (rc < 0 ) {
253
+ dev_warn (dev , "file device add failure\n" );
254
+ goto failed_dev_add ;
255
+ }
256
+
169
257
idxd_wq_get (wq );
170
258
mutex_unlock (& wq -> wq_lock );
171
259
return 0 ;
172
260
261
+ failed_dev_add :
262
+ failed_dev_name :
263
+ put_device (fdev );
264
+ failed_ida :
173
265
failed_set_pasid :
174
266
if (device_user_pasid_enabled (idxd ))
175
267
idxd_xa_pasid_remove (ctx );
@@ -217,34 +309,12 @@ static int idxd_cdev_release(struct inode *node, struct file *filep)
217
309
struct idxd_wq * wq = ctx -> wq ;
218
310
struct idxd_device * idxd = wq -> idxd ;
219
311
struct device * dev = & idxd -> pdev -> dev ;
220
- int rc ;
221
312
222
313
dev_dbg (dev , "%s called\n" , __func__ );
223
314
filep -> private_data = NULL ;
224
315
225
- /* Wait for in-flight operations to complete. */
226
- if (wq_shared (wq )) {
227
- idxd_device_drain_pasid (idxd , ctx -> pasid );
228
- } else {
229
- if (device_user_pasid_enabled (idxd )) {
230
- /* The wq disable in the disable pasid function will drain the wq */
231
- rc = idxd_wq_disable_pasid (wq );
232
- if (rc < 0 )
233
- dev_err (dev , "wq disable pasid failed.\n" );
234
- } else {
235
- idxd_wq_drain (wq );
236
- }
237
- }
316
+ device_unregister (user_ctx_dev (ctx ));
238
317
239
- if (ctx -> sva ) {
240
- idxd_cdev_evl_drain_pasid (wq , ctx -> pasid );
241
- iommu_sva_unbind_device (ctx -> sva );
242
- idxd_xa_pasid_remove (ctx );
243
- }
244
- kfree (ctx );
245
- mutex_lock (& wq -> wq_lock );
246
- idxd_wq_put (wq );
247
- mutex_unlock (& wq -> wq_lock );
248
318
return 0 ;
249
319
}
250
320
@@ -375,6 +445,7 @@ void idxd_wq_del_cdev(struct idxd_wq *wq)
375
445
struct idxd_cdev * idxd_cdev ;
376
446
377
447
idxd_cdev = wq -> idxd_cdev ;
448
+ ida_destroy (& file_ida );
378
449
wq -> idxd_cdev = NULL ;
379
450
cdev_device_del (& idxd_cdev -> cdev , cdev_dev (idxd_cdev ));
380
451
put_device (cdev_dev (idxd_cdev ));
0 commit comments