@@ -207,8 +207,11 @@ struct dxgdevice *dxgdevice_create(struct dxgadapter *adapter,
207207 device -> process = process ;
208208 kref_get (& adapter -> adapter_kref );
209209 INIT_LIST_HEAD (& device -> context_list_head );
210+ INIT_LIST_HEAD (& device -> alloc_list_head );
211+ INIT_LIST_HEAD (& device -> resource_list_head );
210212 init_rwsem (& device -> device_lock );
211213 init_rwsem (& device -> context_list_lock );
214+ init_rwsem (& device -> alloc_list_lock );
212215 INIT_LIST_HEAD (& device -> pqueue_list_head );
213216 device -> object_state = DXGOBJECTSTATE_CREATED ;
214217 device -> execution_state = _D3DKMT_DEVICEEXECUTION_ACTIVE ;
@@ -224,6 +227,14 @@ struct dxgdevice *dxgdevice_create(struct dxgadapter *adapter,
224227
225228void dxgdevice_stop (struct dxgdevice * device )
226229{
230+ struct dxgallocation * alloc ;
231+
232+ DXG_TRACE ("Destroying device: %p" , device );
233+ dxgdevice_acquire_alloc_list_lock (device );
234+ list_for_each_entry (alloc , & device -> alloc_list_head , alloc_list_entry ) {
235+ dxgallocation_stop (alloc );
236+ }
237+ dxgdevice_release_alloc_list_lock (device );
227238}
228239
229240void dxgdevice_mark_destroyed (struct dxgdevice * device )
@@ -250,6 +261,33 @@ void dxgdevice_destroy(struct dxgdevice *device)
250261
251262 dxgdevice_stop (device );
252263
264+ dxgdevice_acquire_alloc_list_lock (device );
265+
266+ {
267+ struct dxgallocation * alloc ;
268+ struct dxgallocation * tmp ;
269+
270+ DXG_TRACE ("destroying allocations" );
271+ list_for_each_entry_safe (alloc , tmp , & device -> alloc_list_head ,
272+ alloc_list_entry ) {
273+ dxgallocation_destroy (alloc );
274+ }
275+ }
276+
277+ {
278+ struct dxgresource * resource ;
279+ struct dxgresource * tmp ;
280+
281+ DXG_TRACE ("destroying resources" );
282+ list_for_each_entry_safe (resource , tmp ,
283+ & device -> resource_list_head ,
284+ resource_list_entry ) {
285+ dxgresource_destroy (resource );
286+ }
287+ }
288+
289+ dxgdevice_release_alloc_list_lock (device );
290+
253291 {
254292 struct dxgcontext * context ;
255293 struct dxgcontext * tmp ;
@@ -328,6 +366,26 @@ void dxgdevice_release_context_list_lock(struct dxgdevice *device)
328366 up_write (& device -> context_list_lock );
329367}
330368
369+ void dxgdevice_acquire_alloc_list_lock (struct dxgdevice * device )
370+ {
371+ down_write (& device -> alloc_list_lock );
372+ }
373+
374+ void dxgdevice_release_alloc_list_lock (struct dxgdevice * device )
375+ {
376+ up_write (& device -> alloc_list_lock );
377+ }
378+
379+ void dxgdevice_acquire_alloc_list_lock_shared (struct dxgdevice * device )
380+ {
381+ down_read (& device -> alloc_list_lock );
382+ }
383+
384+ void dxgdevice_release_alloc_list_lock_shared (struct dxgdevice * device )
385+ {
386+ up_read (& device -> alloc_list_lock );
387+ }
388+
331389void dxgdevice_add_context (struct dxgdevice * device , struct dxgcontext * context )
332390{
333391 down_write (& device -> context_list_lock );
@@ -344,6 +402,161 @@ void dxgdevice_remove_context(struct dxgdevice *device,
344402 }
345403}
346404
405+ void dxgdevice_add_alloc (struct dxgdevice * device , struct dxgallocation * alloc )
406+ {
407+ dxgdevice_acquire_alloc_list_lock (device );
408+ list_add_tail (& alloc -> alloc_list_entry , & device -> alloc_list_head );
409+ kref_get (& device -> device_kref );
410+ alloc -> owner .device = device ;
411+ dxgdevice_release_alloc_list_lock (device );
412+ }
413+
414+ void dxgdevice_remove_alloc (struct dxgdevice * device ,
415+ struct dxgallocation * alloc )
416+ {
417+ if (alloc -> alloc_list_entry .next ) {
418+ list_del (& alloc -> alloc_list_entry );
419+ alloc -> alloc_list_entry .next = NULL ;
420+ kref_put (& device -> device_kref , dxgdevice_release );
421+ }
422+ }
423+
424+ void dxgdevice_remove_alloc_safe (struct dxgdevice * device ,
425+ struct dxgallocation * alloc )
426+ {
427+ dxgdevice_acquire_alloc_list_lock (device );
428+ dxgdevice_remove_alloc (device , alloc );
429+ dxgdevice_release_alloc_list_lock (device );
430+ }
431+
432+ void dxgdevice_add_resource (struct dxgdevice * device , struct dxgresource * res )
433+ {
434+ dxgdevice_acquire_alloc_list_lock (device );
435+ list_add_tail (& res -> resource_list_entry , & device -> resource_list_head );
436+ kref_get (& device -> device_kref );
437+ dxgdevice_release_alloc_list_lock (device );
438+ }
439+
440+ void dxgdevice_remove_resource (struct dxgdevice * device ,
441+ struct dxgresource * res )
442+ {
443+ if (res -> resource_list_entry .next ) {
444+ list_del (& res -> resource_list_entry );
445+ res -> resource_list_entry .next = NULL ;
446+ kref_put (& device -> device_kref , dxgdevice_release );
447+ }
448+ }
449+
450+ struct dxgresource * dxgresource_create (struct dxgdevice * device )
451+ {
452+ struct dxgresource * resource ;
453+
454+ resource = kzalloc (sizeof (struct dxgresource ), GFP_KERNEL );
455+ if (resource ) {
456+ kref_init (& resource -> resource_kref );
457+ resource -> device = device ;
458+ resource -> process = device -> process ;
459+ resource -> object_state = DXGOBJECTSTATE_ACTIVE ;
460+ mutex_init (& resource -> resource_mutex );
461+ INIT_LIST_HEAD (& resource -> alloc_list_head );
462+ dxgdevice_add_resource (device , resource );
463+ }
464+ return resource ;
465+ }
466+
467+ void dxgresource_free_handle (struct dxgresource * resource )
468+ {
469+ struct dxgallocation * alloc ;
470+ struct dxgprocess * process ;
471+
472+ if (resource -> handle_valid ) {
473+ process = resource -> device -> process ;
474+ hmgrtable_free_handle_safe (& process -> handle_table ,
475+ HMGRENTRY_TYPE_DXGRESOURCE ,
476+ resource -> handle );
477+ resource -> handle_valid = 0 ;
478+ }
479+ list_for_each_entry (alloc , & resource -> alloc_list_head ,
480+ alloc_list_entry ) {
481+ dxgallocation_free_handle (alloc );
482+ }
483+ }
484+
485+ void dxgresource_destroy (struct dxgresource * resource )
486+ {
487+ /* device->alloc_list_lock is held */
488+ struct dxgallocation * alloc ;
489+ struct dxgallocation * tmp ;
490+ struct d3dkmt_destroyallocation2 args = { };
491+ int destroyed = test_and_set_bit (0 , & resource -> flags );
492+ struct dxgdevice * device = resource -> device ;
493+
494+ if (!destroyed ) {
495+ dxgresource_free_handle (resource );
496+ if (resource -> handle .v ) {
497+ args .device = device -> handle ;
498+ args .resource = resource -> handle ;
499+ dxgvmb_send_destroy_allocation (device -> process ,
500+ device , & args , NULL );
501+ resource -> handle .v = 0 ;
502+ }
503+ list_for_each_entry_safe (alloc , tmp , & resource -> alloc_list_head ,
504+ alloc_list_entry ) {
505+ dxgallocation_destroy (alloc );
506+ }
507+ dxgdevice_remove_resource (device , resource );
508+ }
509+ kref_put (& resource -> resource_kref , dxgresource_release );
510+ }
511+
512+ void dxgresource_release (struct kref * refcount )
513+ {
514+ struct dxgresource * resource ;
515+
516+ resource = container_of (refcount , struct dxgresource , resource_kref );
517+ kfree (resource );
518+ }
519+
520+ bool dxgresource_is_active (struct dxgresource * resource )
521+ {
522+ return resource -> object_state == DXGOBJECTSTATE_ACTIVE ;
523+ }
524+
525+ int dxgresource_add_alloc (struct dxgresource * resource ,
526+ struct dxgallocation * alloc )
527+ {
528+ int ret = - ENODEV ;
529+ struct dxgdevice * device = resource -> device ;
530+
531+ dxgdevice_acquire_alloc_list_lock (device );
532+ if (dxgresource_is_active (resource )) {
533+ list_add_tail (& alloc -> alloc_list_entry ,
534+ & resource -> alloc_list_head );
535+ alloc -> owner .resource = resource ;
536+ ret = 0 ;
537+ }
538+ alloc -> resource_owner = 1 ;
539+ dxgdevice_release_alloc_list_lock (device );
540+ return ret ;
541+ }
542+
543+ void dxgresource_remove_alloc (struct dxgresource * resource ,
544+ struct dxgallocation * alloc )
545+ {
546+ if (alloc -> alloc_list_entry .next ) {
547+ list_del (& alloc -> alloc_list_entry );
548+ alloc -> alloc_list_entry .next = NULL ;
549+ }
550+ }
551+
552+ void dxgresource_remove_alloc_safe (struct dxgresource * resource ,
553+ struct dxgallocation * alloc )
554+ {
555+ dxgdevice_acquire_alloc_list_lock (resource -> device );
556+ dxgresource_remove_alloc (resource , alloc );
557+ dxgdevice_release_alloc_list_lock (resource -> device );
558+ }
559+
347560void dxgdevice_release (struct kref * refcount )
348561{
349562 struct dxgdevice * device ;
@@ -413,6 +626,75 @@ void dxgcontext_release(struct kref *refcount)
413626 kfree (context );
414627}
415628
629+ struct dxgallocation * dxgallocation_create (struct dxgprocess * process )
630+ {
631+ struct dxgallocation * alloc ;
632+
633+ alloc = kzalloc (sizeof (struct dxgallocation ), GFP_KERNEL );
634+ if (alloc )
635+ alloc -> process = process ;
636+ return alloc ;
637+ }
638+
639+ void dxgallocation_stop (struct dxgallocation * alloc )
640+ {
641+ if (alloc -> pages ) {
642+ release_pages (alloc -> pages , alloc -> num_pages );
643+ vfree (alloc -> pages );
644+ alloc -> pages = NULL ;
645+ }
646+ }
647+
648+ void dxgallocation_free_handle (struct dxgallocation * alloc )
649+ {
650+ dxgprocess_ht_lock_exclusive_down (alloc -> process );
651+ if (alloc -> handle_valid ) {
652+ hmgrtable_free_handle (& alloc -> process -> handle_table ,
653+ HMGRENTRY_TYPE_DXGALLOCATION ,
654+ alloc -> alloc_handle );
655+ alloc -> handle_valid = 0 ;
656+ }
657+ dxgprocess_ht_lock_exclusive_up (alloc -> process );
658+ }
659+
660+ void dxgallocation_destroy (struct dxgallocation * alloc )
661+ {
662+ struct dxgprocess * process = alloc -> process ;
663+ struct d3dkmt_destroyallocation2 args = { };
664+
665+ dxgallocation_stop (alloc );
666+ if (alloc -> resource_owner )
667+ dxgresource_remove_alloc (alloc -> owner .resource , alloc );
668+ else if (alloc -> owner .device )
669+ dxgdevice_remove_alloc (alloc -> owner .device , alloc );
670+ dxgallocation_free_handle (alloc );
671+ if (alloc -> alloc_handle .v && !alloc -> resource_owner ) {
672+ args .device = alloc -> owner .device -> handle ;
673+ args .alloc_count = 1 ;
674+ dxgvmb_send_destroy_allocation (process ,
675+ alloc -> owner .device ,
676+ & args , & alloc -> alloc_handle );
677+ }
678+ #ifdef _MAIN_KERNEL_
679+ if (alloc -> gpadl .gpadl_handle ) {
680+ DXG_TRACE ("Teardown gpadl %d" ,
681+ alloc -> gpadl .gpadl_handle );
682+ vmbus_teardown_gpadl (dxgglobal_get_vmbus (), & alloc -> gpadl );
683+ alloc -> gpadl .gpadl_handle = 0 ;
684+ }
685+ else
686+ if (alloc -> gpadl ) {
687+ DXG_TRACE ("Teardown gpadl %d" ,
688+ alloc -> gpadl );
689+ vmbus_teardown_gpadl (dxgglobal_get_vmbus (), alloc -> gpadl );
690+ alloc -> gpadl = 0 ;
691+ }
692+ #endif
693+ if (alloc -> priv_drv_data )
694+ vfree (alloc -> priv_drv_data );
695+ kfree (alloc );
696+ }
697+
416698struct dxgprocess_adapter * dxgprocess_adapter_create (struct dxgprocess * process ,
417699 struct dxgadapter * adapter )
418700{
0 commit comments