Skip to content

Commit db6038b

Browse files
author
Iouri Tarassov
committed
drivers: hv: dxgkrnl: Implement creation/destruction of GPU allocations/resources
Implemented the following ioctls: - Creation and destruction of GPU accessible allocations: LX_DXCREATEALLOCATION, LX_DXDESTROYALLOCATION2, - LX_DXGETSHAREDRESOURCEADAPTERLUID - LX_DXRENDER At this moment GPU paravirtualization does not support D3DKMTRender API. Signed-off-by: Iouri Tarassov <iourit@linux.microsoft.com>
1 parent 907b5d6 commit db6038b

4 files changed

Lines changed: 1705 additions & 21 deletions

File tree

drivers/hv/dxgkrnl/dxgadapter.c

Lines changed: 294 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -448,6 +448,230 @@ void dxgdevice_remove_context(struct dxgdevice *device,
448448
}
449449
}
450450

451+
void dxgdevice_add_alloc(struct dxgdevice *device, struct dxgallocation *alloc)
452+
{
453+
dxgdevice_acquire_alloc_list_lock(device);
454+
list_add_tail(&alloc->alloc_list_entry, &device->alloc_list_head);
455+
kref_get(&device->device_kref);
456+
alloc->owner.device = device;
457+
dxgdevice_release_alloc_list_lock(device);
458+
}
459+
460+
void dxgdevice_remove_alloc(struct dxgdevice *device,
461+
struct dxgallocation *alloc)
462+
{
463+
if (alloc->alloc_list_entry.next) {
464+
list_del(&alloc->alloc_list_entry);
465+
alloc->alloc_list_entry.next = NULL;
466+
kref_put(&device->device_kref, dxgdevice_release);
467+
}
468+
}
469+
470+
void dxgdevice_remove_alloc_safe(struct dxgdevice *device,
471+
struct dxgallocation *alloc)
472+
{
473+
dxgdevice_acquire_alloc_list_lock(device);
474+
dxgdevice_remove_alloc(device, alloc);
475+
dxgdevice_release_alloc_list_lock(device);
476+
}
477+
478+
void dxgdevice_add_resource(struct dxgdevice *device, struct dxgresource *res)
479+
{
480+
dxgdevice_acquire_alloc_list_lock(device);
481+
list_add_tail(&res->resource_list_entry, &device->resource_list_head);
482+
kref_get(&device->device_kref);
483+
dxgdevice_release_alloc_list_lock(device);
484+
}
485+
486+
void dxgdevice_remove_resource(struct dxgdevice *device,
487+
struct dxgresource *res)
488+
{
489+
if (res->resource_list_entry.next) {
490+
list_del(&res->resource_list_entry);
491+
res->resource_list_entry.next = NULL;
492+
kref_put(&device->device_kref, dxgdevice_release);
493+
}
494+
}
495+
496+
struct dxgsharedresource *dxgsharedresource_create(struct dxgadapter *adapter)
497+
{
498+
struct dxgsharedresource *resource;
499+
500+
resource = vzalloc(sizeof(*resource));
501+
if (resource) {
502+
INIT_LIST_HEAD(&resource->resource_list_head);
503+
kref_init(&resource->sresource_kref);
504+
mutex_init(&resource->fd_mutex);
505+
resource->adapter = adapter;
506+
}
507+
return resource;
508+
}
509+
510+
void dxgsharedresource_destroy(struct kref *refcount)
511+
{
512+
struct dxgsharedresource *resource;
513+
514+
resource = container_of(refcount, struct dxgsharedresource,
515+
sresource_kref);
516+
if (resource->runtime_private_data)
517+
vfree(resource->runtime_private_data);
518+
if (resource->resource_private_data)
519+
vfree(resource->resource_private_data);
520+
if (resource->alloc_private_data_sizes)
521+
vfree(resource->alloc_private_data_sizes);
522+
if (resource->alloc_private_data)
523+
vfree(resource->alloc_private_data);
524+
vfree(resource);
525+
}
526+
527+
void dxgsharedresource_add_resource(struct dxgsharedresource *shared_resource,
528+
struct dxgresource *resource)
529+
{
530+
down_write(&shared_resource->adapter->shared_resource_list_lock);
531+
dev_dbg(dxgglobaldev, "%s: %p %p", __func__, shared_resource, resource);
532+
list_add_tail(&resource->shared_resource_list_entry,
533+
&shared_resource->resource_list_head);
534+
kref_get(&shared_resource->sresource_kref);
535+
kref_get(&resource->resource_kref);
536+
resource->shared_owner = shared_resource;
537+
up_write(&shared_resource->adapter->shared_resource_list_lock);
538+
}
539+
540+
void dxgsharedresource_remove_resource(struct dxgsharedresource
541+
*shared_resource,
542+
struct dxgresource *resource)
543+
{
544+
struct dxgadapter *adapter = shared_resource->adapter;
545+
546+
down_write(&adapter->shared_resource_list_lock);
547+
dev_dbg(dxgglobaldev, "%s: %p %p", __func__, shared_resource, resource);
548+
if (resource->shared_resource_list_entry.next) {
549+
list_del(&resource->shared_resource_list_entry);
550+
resource->shared_resource_list_entry.next = NULL;
551+
kref_put(&shared_resource->sresource_kref,
552+
dxgsharedresource_destroy);
553+
resource->shared_owner = NULL;
554+
kref_put(&resource->resource_kref, dxgresource_release);
555+
}
556+
up_write(&adapter->shared_resource_list_lock);
557+
}
558+
559+
struct dxgresource *dxgresource_create(struct dxgdevice *device)
560+
{
561+
struct dxgresource *resource = vzalloc(sizeof(struct dxgresource));
562+
563+
if (resource) {
564+
kref_init(&resource->resource_kref);
565+
resource->device = device;
566+
resource->process = device->process;
567+
resource->object_state = DXGOBJECTSTATE_ACTIVE;
568+
mutex_init(&resource->resource_mutex);
569+
INIT_LIST_HEAD(&resource->alloc_list_head);
570+
dxgdevice_add_resource(device, resource);
571+
}
572+
return resource;
573+
}
574+
575+
void dxgresource_free_handle(struct dxgresource *resource)
576+
{
577+
struct dxgallocation *alloc;
578+
struct dxgprocess *process;
579+
580+
if (resource->handle_valid) {
581+
process = resource->device->process;
582+
hmgrtable_free_handle_safe(&process->handle_table,
583+
HMGRENTRY_TYPE_DXGRESOURCE,
584+
resource->handle);
585+
resource->handle_valid = 0;
586+
}
587+
list_for_each_entry(alloc, &resource->alloc_list_head,
588+
alloc_list_entry) {
589+
dxgallocation_free_handle(alloc);
590+
}
591+
}
592+
593+
void dxgresource_destroy(struct dxgresource *resource)
594+
{
595+
/* device->alloc_list_lock is held */
596+
struct dxgallocation *alloc;
597+
struct dxgallocation *tmp;
598+
struct d3dkmt_destroyallocation2 args = { };
599+
int destroyed = test_and_set_bit(0, &resource->flags);
600+
struct dxgdevice *device = resource->device;
601+
struct dxgsharedresource *shared_resource;
602+
603+
if (!destroyed) {
604+
dxgresource_free_handle(resource);
605+
if (resource->handle.v) {
606+
args.device = device->handle;
607+
args.resource = resource->handle;
608+
dxgvmb_send_destroy_allocation(device->process,
609+
device, &args, NULL);
610+
resource->handle.v = 0;
611+
}
612+
list_for_each_entry_safe(alloc, tmp, &resource->alloc_list_head,
613+
alloc_list_entry) {
614+
dxgallocation_destroy(alloc);
615+
}
616+
dxgdevice_remove_resource(device, resource);
617+
shared_resource = resource->shared_owner;
618+
if (shared_resource) {
619+
dxgsharedresource_remove_resource(shared_resource,
620+
resource);
621+
resource->shared_owner = NULL;
622+
}
623+
}
624+
kref_put(&resource->resource_kref, dxgresource_release);
625+
}
626+
627+
void dxgresource_release(struct kref *refcount)
628+
{
629+
struct dxgresource *resource;
630+
631+
resource = container_of(refcount, struct dxgresource, resource_kref);
632+
vfree(resource);
633+
}
634+
635+
bool dxgresource_is_active(struct dxgresource *resource)
636+
{
637+
return resource->object_state == DXGOBJECTSTATE_ACTIVE;
638+
}
639+
640+
int dxgresource_add_alloc(struct dxgresource *resource,
641+
struct dxgallocation *alloc)
642+
{
643+
int ret = -ENODEV;
644+
struct dxgdevice *device = resource->device;
645+
646+
dxgdevice_acquire_alloc_list_lock(device);
647+
if (dxgresource_is_active(resource)) {
648+
list_add_tail(&alloc->alloc_list_entry,
649+
&resource->alloc_list_head);
650+
alloc->owner.resource = resource;
651+
ret = 0;
652+
}
653+
alloc->resource_owner = 1;
654+
dxgdevice_release_alloc_list_lock(device);
655+
return ret;
656+
}
657+
658+
void dxgresource_remove_alloc(struct dxgresource *resource,
659+
struct dxgallocation *alloc)
660+
{
661+
if (alloc->alloc_list_entry.next) {
662+
list_del(&alloc->alloc_list_entry);
663+
alloc->alloc_list_entry.next = NULL;
664+
}
665+
}
666+
667+
void dxgresource_remove_alloc_safe(struct dxgresource *resource,
668+
struct dxgallocation *alloc)
669+
{
670+
dxgdevice_acquire_alloc_list_lock(resource->device);
671+
dxgresource_remove_alloc(resource, alloc);
672+
dxgdevice_release_alloc_list_lock(resource->device);
673+
}
674+
451675
void dxgdevice_release(struct kref *refcount)
452676
{
453677
struct dxgdevice *device;
@@ -523,6 +747,76 @@ void dxgcontext_release(struct kref *refcount)
523747
vfree(context);
524748
}
525749

750+
struct dxgallocation *dxgallocation_create(struct dxgprocess *process)
751+
{
752+
struct dxgallocation *alloc = vzalloc(sizeof(struct dxgallocation));
753+
754+
if (alloc)
755+
alloc->process = process;
756+
return alloc;
757+
}
758+
759+
void dxgallocation_stop(struct dxgallocation *alloc)
760+
{
761+
if (alloc->pages) {
762+
release_pages(alloc->pages, alloc->num_pages);
763+
vfree(alloc->pages);
764+
alloc->pages = NULL;
765+
}
766+
dxgprocess_ht_lock_exclusive_down(alloc->process);
767+
if (alloc->cpu_address_mapped) {
768+
dxg_unmap_iospace(alloc->cpu_address,
769+
alloc->num_pages << PAGE_SHIFT);
770+
alloc->cpu_address_mapped = false;
771+
alloc->cpu_address = NULL;
772+
alloc->cpu_address_refcount = 0;
773+
}
774+
dxgprocess_ht_lock_exclusive_up(alloc->process);
775+
}
776+
777+
void dxgallocation_free_handle(struct dxgallocation *alloc)
778+
{
779+
dxgprocess_ht_lock_exclusive_down(alloc->process);
780+
if (alloc->handle_valid) {
781+
hmgrtable_free_handle(&alloc->process->handle_table,
782+
HMGRENTRY_TYPE_DXGALLOCATION,
783+
alloc->alloc_handle);
784+
alloc->handle_valid = 0;
785+
}
786+
dxgprocess_ht_lock_exclusive_up(alloc->process);
787+
}
788+
789+
void dxgallocation_destroy(struct dxgallocation *alloc)
790+
{
791+
struct dxgprocess *process = alloc->process;
792+
struct d3dkmt_destroyallocation2 args = { };
793+
794+
dxgallocation_stop(alloc);
795+
if (alloc->resource_owner)
796+
dxgresource_remove_alloc(alloc->owner.resource, alloc);
797+
else if (alloc->owner.device)
798+
dxgdevice_remove_alloc(alloc->owner.device, alloc);
799+
dxgallocation_free_handle(alloc);
800+
if (alloc->alloc_handle.v && !alloc->resource_owner) {
801+
args.device = alloc->owner.device->handle;
802+
args.alloc_count = 1;
803+
dxgvmb_send_destroy_allocation(process,
804+
alloc->owner.device,
805+
&args, &alloc->alloc_handle);
806+
}
807+
if (alloc->gpadl) {
808+
dev_dbg(dxgglobaldev, "Teardown gpadl %d", alloc->gpadl);
809+
vmbus_teardown_gpadl(dxgglobal_get_vmbus(), alloc->gpadl);
810+
dev_dbg(dxgglobaldev, "Teardown gpadl end");
811+
alloc->gpadl = 0;
812+
}
813+
if (alloc->priv_drv_data)
814+
vfree(alloc->priv_drv_data);
815+
if (alloc->cpu_address_mapped)
816+
pr_err("Alloc IO space is mapped: %p", alloc);
817+
vfree(alloc);
818+
}
819+
526820
struct dxgprocess_adapter *dxgprocess_adapter_create(struct dxgprocess *process,
527821
struct dxgadapter *adapter)
528822
{
@@ -656,21 +950,6 @@ void dxgpagingqueue_stop(struct dxgpagingqueue *pqueue)
656950
/* Placeholder */
657951
}
658952

659-
void dxgallocation_destroy(struct dxgallocation *alloc)
660-
{
661-
/* Placeholder */
662-
}
663-
664-
void dxgallocation_stop(struct dxgallocation *alloc)
665-
{
666-
/* Placeholder */
667-
}
668-
669-
void dxgresource_destroy(struct dxgresource *resource)
670-
{
671-
/* Placeholder */
672-
}
673-
674953
void dxgsyncobject_destroy(struct dxgprocess *process,
675954
struct dxgsyncobject *syncobj)
676955
{

0 commit comments

Comments
 (0)