66#include <linux/firmware.h>
77#include <linux/module.h>
88#include <linux/pci.h>
9+ #include <linux/pm_runtime.h>
910
1011#include <drm/drm_accel.h>
1112#include <drm/drm_file.h>
1718#include "ivpu_debugfs.h"
1819#include "ivpu_drv.h"
1920#include "ivpu_fw.h"
21+ #include "ivpu_fw_log.h"
2022#include "ivpu_gem.h"
2123#include "ivpu_hw.h"
2224#include "ivpu_ipc.h"
@@ -65,36 +67,36 @@ struct ivpu_file_priv *ivpu_file_priv_get(struct ivpu_file_priv *file_priv)
6567 return file_priv ;
6668}
6769
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 )
6971{
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 );
8484}
8585
8686static void file_priv_release (struct kref * ref )
8787{
8888 struct ivpu_file_priv * file_priv = container_of (ref , struct ivpu_file_priv , ref );
8989 struct ivpu_device * vdev = file_priv -> vdev ;
9090
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 );
9299
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 );
98100 mutex_destroy (& file_priv -> lock );
99101 kfree (file_priv );
100102}
@@ -176,9 +178,6 @@ static int ivpu_get_param_ioctl(struct drm_device *dev, void *data, struct drm_f
176178 case DRM_IVPU_PARAM_CONTEXT_BASE_ADDRESS :
177179 args -> value = vdev -> hw -> ranges .user .start ;
178180 break ;
179- case DRM_IVPU_PARAM_CONTEXT_PRIORITY :
180- args -> value = file_priv -> priority ;
181- break ;
182181 case DRM_IVPU_PARAM_CONTEXT_ID :
183182 args -> value = file_priv -> ctx .id ;
184183 break ;
@@ -218,17 +217,10 @@ static int ivpu_get_param_ioctl(struct drm_device *dev, void *data, struct drm_f
218217
219218static int ivpu_set_param_ioctl (struct drm_device * dev , void * data , struct drm_file * file )
220219{
221- struct ivpu_file_priv * file_priv = file -> driver_priv ;
222220 struct drm_ivpu_param * args = data ;
223221 int ret = 0 ;
224222
225223 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 ;
232224 default :
233225 ret = - EINVAL ;
234226 }
@@ -241,50 +233,53 @@ static int ivpu_open(struct drm_device *dev, struct drm_file *file)
241233 struct ivpu_device * vdev = to_ivpu_device (dev );
242234 struct ivpu_file_priv * file_priv ;
243235 u32 ctx_id ;
244- void * old ;
245- int ret ;
236+ int idx , ret ;
246237
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 ;
252240
253241 file_priv = kzalloc (sizeof (* file_priv ), GFP_KERNEL );
254242 if (!file_priv ) {
255243 ret = - ENOMEM ;
256- goto err_xa_erase ;
244+ goto err_dev_exit ;
257245 }
258246
259247 file_priv -> vdev = vdev ;
260- file_priv -> priority = DRM_IVPU_CONTEXT_PRIORITY_NORMAL ;
248+ file_priv -> bound = true ;
261249 kref_init (& file_priv -> ref );
262250 mutex_init (& file_priv -> lock );
263251
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+
264261 ret = ivpu_mmu_user_context_init (vdev , & file_priv -> ctx , ctx_id );
265262 if (ret )
266- goto err_mutex_destroy ;
263+ goto err_xa_erase ;
267264
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 ;
274269
275270 ivpu_dbg (vdev , FILE , "file_priv create: ctx %u process %s pid %d\n" ,
276271 ctx_id , current -> comm , task_pid_nr (current ));
277272
278- file -> driver_priv = file_priv ;
279273 return 0 ;
280274
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 );
286275err_xa_erase :
287276 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 );
288283 return ret ;
289284}
290285
@@ -340,8 +335,6 @@ static int ivpu_wait_for_ready(struct ivpu_device *vdev)
340335
341336 if (!ret )
342337 ivpu_dbg (vdev , PM , "VPU ready message received successfully\n" );
343- else
344- ivpu_hw_diagnose_failure (vdev );
345338
346339 return ret ;
347340}
@@ -369,6 +362,9 @@ int ivpu_boot(struct ivpu_device *vdev)
369362 ret = ivpu_wait_for_ready (vdev );
370363 if (ret ) {
371364 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 );
372368 return ret ;
373369 }
374370
@@ -540,6 +536,10 @@ static int ivpu_dev_init(struct ivpu_device *vdev)
540536 lockdep_set_class (& vdev -> submitted_jobs_xa .xa_lock , & submitted_jobs_xa_lock_class_key );
541537 INIT_LIST_HEAD (& vdev -> bo_list );
542538
539+ ret = drmm_mutex_init (& vdev -> drm , & vdev -> context_list_lock );
540+ if (ret )
541+ goto err_xa_destroy ;
542+
543543 ret = drmm_mutex_init (& vdev -> drm , & vdev -> bo_list_lock );
544544 if (ret )
545545 goto err_xa_destroy ;
@@ -611,14 +611,30 @@ static int ivpu_dev_init(struct ivpu_device *vdev)
611611 return ret ;
612612}
613613
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+
614627static void ivpu_dev_fini (struct ivpu_device * vdev )
615628{
616629 ivpu_pm_disable (vdev );
617630 ivpu_shutdown (vdev );
618631 if (IVPU_WA (d3hot_after_power_off ))
619632 pci_set_power_state (to_pci_dev (vdev -> drm .dev ), PCI_D3hot );
633+
634+ ivpu_jobs_abort_all (vdev );
620635 ivpu_job_done_consumer_fini (vdev );
621636 ivpu_pm_cancel_recovery (vdev );
637+ ivpu_bo_unbind_all_user_contexts (vdev );
622638
623639 ivpu_ipc_fini (vdev );
624640 ivpu_fw_fini (vdev );
0 commit comments