Skip to content

Commit 909d70f

Browse files
author
Iouri Tarassov
committed
drivers: hv: dxgkrnl: Implement creation/destruction of GPU allocations/resources
Implemented the following ioctls: LX_DXCREATEALLOCATION, LX_DXDESTROYALLOCATION2, LX_DXGETSHAREDRESOURCEADAPTERLUID, LX_DXRENDER. Signed-off-by: Iouri Tarassov <iourit@linux.microsoft.com>
1 parent 01ee7b8 commit 909d70f

3 files changed

Lines changed: 1704 additions & 15 deletions

File tree

drivers/hv/dxgkrnl/dxgadapter.c

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

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

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

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

0 commit comments

Comments
 (0)