1717
1818#include <drm/drm_auth.h>
1919#include <drm/drm_managed.h>
20+
21+ #include <linux/bug.h>
2022#include <linux/errno.h>
2123#include <linux/kernel.h>
24+ #include <linux/list.h>
2225#include <linux/sched.h>
2326#include <linux/slab.h>
27+ #include <linux/spinlock.h>
2428#include <linux/string.h>
2529#include <linux/types.h>
2630#include <linux/xarray.h>
@@ -354,6 +358,10 @@ int pvr_context_create(struct pvr_file *pvr_file, struct drm_pvr_ioctl_create_co
354358 return err ;
355359 }
356360
361+ spin_lock (& pvr_dev -> ctx_list_lock );
362+ list_add_tail (& ctx -> file_link , & pvr_file -> contexts );
363+ spin_unlock (& pvr_dev -> ctx_list_lock );
364+
357365 return 0 ;
358366
359367err_destroy_fw_obj :
@@ -380,6 +388,11 @@ pvr_context_release(struct kref *ref_count)
380388 container_of (ref_count , struct pvr_context , ref_count );
381389 struct pvr_device * pvr_dev = ctx -> pvr_dev ;
382390
391+ WARN_ON (in_interrupt ());
392+ spin_lock (& pvr_dev -> ctx_list_lock );
393+ list_del (& ctx -> file_link );
394+ spin_unlock (& pvr_dev -> ctx_list_lock );
395+
383396 xa_erase (& pvr_dev -> ctx_ids , ctx -> ctx_id );
384397 pvr_context_destroy_queues (ctx );
385398 pvr_fw_object_destroy (ctx -> fw_obj );
@@ -437,11 +450,30 @@ pvr_context_destroy(struct pvr_file *pvr_file, u32 handle)
437450 */
438451void pvr_destroy_contexts_for_file (struct pvr_file * pvr_file )
439452{
453+ struct pvr_device * pvr_dev = pvr_file -> pvr_dev ;
440454 struct pvr_context * ctx ;
441455 unsigned long handle ;
442456
443457 xa_for_each (& pvr_file -> ctx_handles , handle , ctx )
444458 pvr_context_destroy (pvr_file , handle );
459+
460+ spin_lock (& pvr_dev -> ctx_list_lock );
461+ ctx = list_first_entry (& pvr_file -> contexts , struct pvr_context , file_link );
462+
463+ while (!list_entry_is_head (ctx , & pvr_file -> contexts , file_link )) {
464+ list_del_init (& ctx -> file_link );
465+
466+ if (pvr_context_get_if_referenced (ctx )) {
467+ spin_unlock (& pvr_dev -> ctx_list_lock );
468+
469+ pvr_vm_unmap_all (ctx -> vm_ctx );
470+
471+ pvr_context_put (ctx );
472+ spin_lock (& pvr_dev -> ctx_list_lock );
473+ }
474+ ctx = list_first_entry (& pvr_file -> contexts , struct pvr_context , file_link );
475+ }
476+ spin_unlock (& pvr_dev -> ctx_list_lock );
445477}
446478
447479/**
@@ -451,6 +483,7 @@ void pvr_destroy_contexts_for_file(struct pvr_file *pvr_file)
451483void pvr_context_device_init (struct pvr_device * pvr_dev )
452484{
453485 xa_init_flags (& pvr_dev -> ctx_ids , XA_FLAGS_ALLOC1 );
486+ spin_lock_init (& pvr_dev -> ctx_list_lock );
454487}
455488
456489/**
0 commit comments