6
6
#include <linux/firmware.h>
7
7
#include <linux/module.h>
8
8
#include <linux/pci.h>
9
+ #include <linux/pm_runtime.h>
9
10
10
11
#include <drm/drm_accel.h>
11
12
#include <drm/drm_file.h>
17
18
#include "ivpu_debugfs.h"
18
19
#include "ivpu_drv.h"
19
20
#include "ivpu_fw.h"
21
+ #include "ivpu_fw_log.h"
20
22
#include "ivpu_gem.h"
21
23
#include "ivpu_hw.h"
22
24
#include "ivpu_ipc.h"
@@ -65,36 +67,36 @@ struct ivpu_file_priv *ivpu_file_priv_get(struct ivpu_file_priv *file_priv)
65
67
return file_priv ;
66
68
}
67
69
68
- struct ivpu_file_priv * ivpu_file_priv_get_by_ctx_id (struct ivpu_device * vdev , unsigned long id )
70
+ static void file_priv_unbind (struct ivpu_device * vdev , struct ivpu_file_priv * file_priv )
69
71
{
70
- struct ivpu_file_priv * file_priv ;
71
-
72
- xa_lock_irq (& vdev -> context_xa );
73
- file_priv = xa_load (& vdev -> context_xa , id );
74
- /* file_priv may still be in context_xa during file_priv_release() */
75
- if (file_priv && !kref_get_unless_zero (& file_priv -> ref ))
76
- file_priv = NULL ;
77
- xa_unlock_irq (& vdev -> context_xa );
78
-
79
- if (file_priv )
80
- ivpu_dbg (vdev , KREF , "file_priv get by id: ctx %u refcount %u\n" ,
81
- file_priv -> ctx .id , kref_read (& file_priv -> ref ));
82
-
83
- return file_priv ;
72
+ mutex_lock (& file_priv -> lock );
73
+ if (file_priv -> bound ) {
74
+ ivpu_dbg (vdev , FILE , "file_priv unbind: ctx %u\n" , file_priv -> ctx .id );
75
+
76
+ ivpu_cmdq_release_all_locked (file_priv );
77
+ ivpu_jsm_context_release (vdev , file_priv -> ctx .id );
78
+ ivpu_bo_unbind_all_bos_from_context (vdev , & file_priv -> ctx );
79
+ ivpu_mmu_user_context_fini (vdev , & file_priv -> ctx );
80
+ file_priv -> bound = false;
81
+ drm_WARN_ON (& vdev -> drm , !xa_erase_irq (& vdev -> context_xa , file_priv -> ctx .id ));
82
+ }
83
+ mutex_unlock (& file_priv -> lock );
84
84
}
85
85
86
86
static void file_priv_release (struct kref * ref )
87
87
{
88
88
struct ivpu_file_priv * file_priv = container_of (ref , struct ivpu_file_priv , ref );
89
89
struct ivpu_device * vdev = file_priv -> vdev ;
90
90
91
- ivpu_dbg (vdev , FILE , "file_priv release: ctx %u\n" , file_priv -> ctx .id );
91
+ ivpu_dbg (vdev , FILE , "file_priv release: ctx %u bound %d\n" ,
92
+ file_priv -> ctx .id , (bool )file_priv -> bound );
93
+
94
+ pm_runtime_get_sync (vdev -> drm .dev );
95
+ mutex_lock (& vdev -> context_list_lock );
96
+ file_priv_unbind (vdev , file_priv );
97
+ mutex_unlock (& vdev -> context_list_lock );
98
+ pm_runtime_put_autosuspend (vdev -> drm .dev );
92
99
93
- ivpu_cmdq_release_all (file_priv );
94
- ivpu_jsm_context_release (vdev , file_priv -> ctx .id );
95
- ivpu_bo_remove_all_bos_from_context (vdev , & file_priv -> ctx );
96
- ivpu_mmu_user_context_fini (vdev , & file_priv -> ctx );
97
- drm_WARN_ON (& vdev -> drm , xa_erase_irq (& vdev -> context_xa , file_priv -> ctx .id ) != file_priv );
98
100
mutex_destroy (& file_priv -> lock );
99
101
kfree (file_priv );
100
102
}
@@ -176,9 +178,6 @@ static int ivpu_get_param_ioctl(struct drm_device *dev, void *data, struct drm_f
176
178
case DRM_IVPU_PARAM_CONTEXT_BASE_ADDRESS :
177
179
args -> value = vdev -> hw -> ranges .user .start ;
178
180
break ;
179
- case DRM_IVPU_PARAM_CONTEXT_PRIORITY :
180
- args -> value = file_priv -> priority ;
181
- break ;
182
181
case DRM_IVPU_PARAM_CONTEXT_ID :
183
182
args -> value = file_priv -> ctx .id ;
184
183
break ;
@@ -218,17 +217,10 @@ static int ivpu_get_param_ioctl(struct drm_device *dev, void *data, struct drm_f
218
217
219
218
static int ivpu_set_param_ioctl (struct drm_device * dev , void * data , struct drm_file * file )
220
219
{
221
- struct ivpu_file_priv * file_priv = file -> driver_priv ;
222
220
struct drm_ivpu_param * args = data ;
223
221
int ret = 0 ;
224
222
225
223
switch (args -> param ) {
226
- case DRM_IVPU_PARAM_CONTEXT_PRIORITY :
227
- if (args -> value <= DRM_IVPU_CONTEXT_PRIORITY_REALTIME )
228
- file_priv -> priority = args -> value ;
229
- else
230
- ret = - EINVAL ;
231
- break ;
232
224
default :
233
225
ret = - EINVAL ;
234
226
}
@@ -241,50 +233,53 @@ static int ivpu_open(struct drm_device *dev, struct drm_file *file)
241
233
struct ivpu_device * vdev = to_ivpu_device (dev );
242
234
struct ivpu_file_priv * file_priv ;
243
235
u32 ctx_id ;
244
- void * old ;
245
- int ret ;
236
+ int idx , ret ;
246
237
247
- ret = xa_alloc_irq (& vdev -> context_xa , & ctx_id , NULL , vdev -> context_xa_limit , GFP_KERNEL );
248
- if (ret ) {
249
- ivpu_err (vdev , "Failed to allocate context id: %d\n" , ret );
250
- return ret ;
251
- }
238
+ if (!drm_dev_enter (dev , & idx ))
239
+ return - ENODEV ;
252
240
253
241
file_priv = kzalloc (sizeof (* file_priv ), GFP_KERNEL );
254
242
if (!file_priv ) {
255
243
ret = - ENOMEM ;
256
- goto err_xa_erase ;
244
+ goto err_dev_exit ;
257
245
}
258
246
259
247
file_priv -> vdev = vdev ;
260
- file_priv -> priority = DRM_IVPU_CONTEXT_PRIORITY_NORMAL ;
248
+ file_priv -> bound = true ;
261
249
kref_init (& file_priv -> ref );
262
250
mutex_init (& file_priv -> lock );
263
251
252
+ mutex_lock (& vdev -> context_list_lock );
253
+
254
+ ret = xa_alloc_irq (& vdev -> context_xa , & ctx_id , file_priv ,
255
+ vdev -> context_xa_limit , GFP_KERNEL );
256
+ if (ret ) {
257
+ ivpu_err (vdev , "Failed to allocate context id: %d\n" , ret );
258
+ goto err_unlock ;
259
+ }
260
+
264
261
ret = ivpu_mmu_user_context_init (vdev , & file_priv -> ctx , ctx_id );
265
262
if (ret )
266
- goto err_mutex_destroy ;
263
+ goto err_xa_erase ;
267
264
268
- old = xa_store_irq (& vdev -> context_xa , ctx_id , file_priv , GFP_KERNEL );
269
- if (xa_is_err (old )) {
270
- ret = xa_err (old );
271
- ivpu_err (vdev , "Failed to store context %u: %d\n" , ctx_id , ret );
272
- goto err_ctx_fini ;
273
- }
265
+ mutex_unlock (& vdev -> context_list_lock );
266
+ drm_dev_exit (idx );
267
+
268
+ file -> driver_priv = file_priv ;
274
269
275
270
ivpu_dbg (vdev , FILE , "file_priv create: ctx %u process %s pid %d\n" ,
276
271
ctx_id , current -> comm , task_pid_nr (current ));
277
272
278
- file -> driver_priv = file_priv ;
279
273
return 0 ;
280
274
281
- err_ctx_fini :
282
- ivpu_mmu_user_context_fini (vdev , & file_priv -> ctx );
283
- err_mutex_destroy :
284
- mutex_destroy (& file_priv -> lock );
285
- kfree (file_priv );
286
275
err_xa_erase :
287
276
xa_erase_irq (& vdev -> context_xa , ctx_id );
277
+ err_unlock :
278
+ mutex_unlock (& vdev -> context_list_lock );
279
+ mutex_destroy (& file_priv -> lock );
280
+ kfree (file_priv );
281
+ err_dev_exit :
282
+ drm_dev_exit (idx );
288
283
return ret ;
289
284
}
290
285
@@ -340,8 +335,6 @@ static int ivpu_wait_for_ready(struct ivpu_device *vdev)
340
335
341
336
if (!ret )
342
337
ivpu_dbg (vdev , PM , "VPU ready message received successfully\n" );
343
- else
344
- ivpu_hw_diagnose_failure (vdev );
345
338
346
339
return ret ;
347
340
}
@@ -369,6 +362,9 @@ int ivpu_boot(struct ivpu_device *vdev)
369
362
ret = ivpu_wait_for_ready (vdev );
370
363
if (ret ) {
371
364
ivpu_err (vdev , "Failed to boot the firmware: %d\n" , ret );
365
+ ivpu_hw_diagnose_failure (vdev );
366
+ ivpu_mmu_evtq_dump (vdev );
367
+ ivpu_fw_log_dump (vdev );
372
368
return ret ;
373
369
}
374
370
@@ -540,6 +536,10 @@ static int ivpu_dev_init(struct ivpu_device *vdev)
540
536
lockdep_set_class (& vdev -> submitted_jobs_xa .xa_lock , & submitted_jobs_xa_lock_class_key );
541
537
INIT_LIST_HEAD (& vdev -> bo_list );
542
538
539
+ ret = drmm_mutex_init (& vdev -> drm , & vdev -> context_list_lock );
540
+ if (ret )
541
+ goto err_xa_destroy ;
542
+
543
543
ret = drmm_mutex_init (& vdev -> drm , & vdev -> bo_list_lock );
544
544
if (ret )
545
545
goto err_xa_destroy ;
@@ -611,14 +611,30 @@ static int ivpu_dev_init(struct ivpu_device *vdev)
611
611
return ret ;
612
612
}
613
613
614
+ static void ivpu_bo_unbind_all_user_contexts (struct ivpu_device * vdev )
615
+ {
616
+ struct ivpu_file_priv * file_priv ;
617
+ unsigned long ctx_id ;
618
+
619
+ mutex_lock (& vdev -> context_list_lock );
620
+
621
+ xa_for_each (& vdev -> context_xa , ctx_id , file_priv )
622
+ file_priv_unbind (vdev , file_priv );
623
+
624
+ mutex_unlock (& vdev -> context_list_lock );
625
+ }
626
+
614
627
static void ivpu_dev_fini (struct ivpu_device * vdev )
615
628
{
616
629
ivpu_pm_disable (vdev );
617
630
ivpu_shutdown (vdev );
618
631
if (IVPU_WA (d3hot_after_power_off ))
619
632
pci_set_power_state (to_pci_dev (vdev -> drm .dev ), PCI_D3hot );
633
+
634
+ ivpu_jobs_abort_all (vdev );
620
635
ivpu_job_done_consumer_fini (vdev );
621
636
ivpu_pm_cancel_recovery (vdev );
637
+ ivpu_bo_unbind_all_user_contexts (vdev );
622
638
623
639
ivpu_ipc_fini (vdev );
624
640
ivpu_fw_fini (vdev );
0 commit comments