From 48207af92a119b50ff4bc6f4596f7573465b51da Mon Sep 17 00:00:00 2001 From: Felix Kuehling Date: Fri, 28 Oct 2016 18:48:44 -0400 Subject: [PATCH] Make doorbell-size ASIC specific This is in preparation for gfx900, which uses 64-bit doorbells. We maintain the same number of doorbells per process by making the doorbell page size bigger. KFD will need to implement the same rule. Change-Id: I3c4110869b191b83943b5a390a48edfc94d941d8 --- src/queues.c | 64 +++++++++++++++++++++++++++++++++++----------------- 1 file changed, 43 insertions(+), 21 deletions(-) diff --git a/src/queues.c b/src/queues.c index 5a17dfc950..186c6cad28 100644 --- a/src/queues.c +++ b/src/queues.c @@ -35,8 +35,11 @@ #include #include -/* 1024 doorbells, 4 bytes each doorbell */ -#define DOORBELLS_PAGE_SIZE 1024 * 4 +/* 1024 doorbells, 4 or 8 bytes each doorbell depending on ASIC generation */ +#define DOORBELL_SIZE_GFX7 4 +#define DOORBELL_SIZE_GFX8 4 +#define DOORBELL_SIZE_GFX9 8 +#define DOORBELLS_PAGE_SIZE(ds) (1024 * (ds)) enum asic_family_type { CHIP_KAVERI = 0, @@ -60,46 +63,55 @@ struct device_info { enum asic_family_type asic_family; uint32_t eop_buffer_size; + uint32_t doorbell_size; }; struct device_info kaveri_device_info = { .asic_family = CHIP_KAVERI, .eop_buffer_size = 0, + .doorbell_size = DOORBELL_SIZE_GFX7, }; struct device_info hawaii_device_info = { .asic_family = CHIP_HAWAII, .eop_buffer_size = 0, + .doorbell_size = DOORBELL_SIZE_GFX7, }; struct device_info carrizo_device_info = { .asic_family = CHIP_CARRIZO, .eop_buffer_size = 4096, + .doorbell_size = DOORBELL_SIZE_GFX8, }; struct device_info tonga_device_info = { .asic_family = CHIP_TONGA, .eop_buffer_size = TONGA_PAGE_SIZE, + .doorbell_size = DOORBELL_SIZE_GFX8, }; struct device_info fiji_device_info = { .asic_family = CHIP_FIJI, .eop_buffer_size = TONGA_PAGE_SIZE, + .doorbell_size = DOORBELL_SIZE_GFX8, }; struct device_info polaris10_device_info = { .asic_family = CHIP_POLARIS10, .eop_buffer_size = TONGA_PAGE_SIZE, + .doorbell_size = DOORBELL_SIZE_GFX8, }; struct device_info polaris11_device_info = { .asic_family = CHIP_POLARIS11, .eop_buffer_size = TONGA_PAGE_SIZE, + .doorbell_size = DOORBELL_SIZE_GFX8, }; struct device_info vega10_device_info = { .asic_family = CHIP_VEGA10, .eop_buffer_size = 4096, + .doorbell_size = DOORBELL_SIZE_GFX9, }; struct device_id @@ -199,7 +211,8 @@ struct queue struct process_doorbells { - bool need_mmap; + bool use_gpuvm; + uint32_t size; void* doorbells; pthread_mutex_t doorbells_mutex; }; @@ -219,7 +232,8 @@ HSAKMT_STATUS init_process_doorbells(unsigned int NumNodes) return HSAKMT_STATUS_NO_MEMORY; for (i = 0; i < NumNodes; i++) { - doorbells[i].need_mmap = true; + doorbells[i].use_gpuvm = false; + doorbells[i].size = 0; doorbells[i].doorbells = NULL; pthread_mutex_init(&doorbells[i].doorbells_mutex, NULL); } @@ -242,7 +256,8 @@ static struct device_info *get_device_info_by_dev_id(uint16_t dev_id) return NULL; } -static bool use_gpuvm_doorbell(uint16_t dev_id) +static void get_doorbell_map_info(uint16_t dev_id, + struct process_doorbells *doorbell) { struct device_info *dev_info; @@ -252,8 +267,9 @@ static bool use_gpuvm_doorbell(uint16_t dev_id) * GPUVM doorbell on Tonga requires a workaround for VM TLB ACTIVE bit * lookup bug. Remove ASIC check when this is implemented in amdgpu. */ - return (topology_is_dgpu(dev_id) && - dev_info->asic_family != CHIP_TONGA); + doorbell->use_gpuvm = (topology_is_dgpu(dev_id) && + dev_info->asic_family != CHIP_TONGA); + doorbell->size = DOORBELLS_PAGE_SIZE(dev_info->doorbell_size); } void destroy_process_doorbells(void) @@ -264,14 +280,14 @@ void destroy_process_doorbells(void) return; for (i = 0; i < num_doorbells; i++) { - if (doorbells[i].need_mmap) + if (!doorbells[i].size) continue; - if (use_gpuvm_doorbell(get_device_id_by_node(i))) { + if (doorbells[i].use_gpuvm) { fmm_unmap_from_gpu(doorbells[i].doorbells); fmm_release(doorbells[i].doorbells); } else - munmap(doorbells[i].doorbells, DOORBELLS_PAGE_SIZE); + munmap(doorbells[i].doorbells, doorbells[i].size); } free(doorbells); @@ -290,11 +306,11 @@ void clear_process_doorbells(void) return; for (i = 0; i < num_doorbells; i++) { - if (doorbells[i].need_mmap) + if (!doorbells[i].size) continue; - if (!use_gpuvm_doorbell(get_device_id_by_node(i))) - munmap(doorbells[i].doorbells, DOORBELLS_PAGE_SIZE); + if (!doorbells[i].use_gpuvm) + munmap(doorbells[i].doorbells, doorbells[i].size); } free(doorbells); @@ -307,13 +323,12 @@ static HSAKMT_STATUS map_doorbell_apu(HSAuint32 NodeId, HSAuint32 gpu_id, { void *ptr; - ptr = mmap(0, DOORBELLS_PAGE_SIZE, PROT_READ|PROT_WRITE, + ptr = mmap(0, doorbells[NodeId].size, PROT_READ|PROT_WRITE, MAP_SHARED, kfd_fd, doorbell_offset); if (ptr == MAP_FAILED) return HSAKMT_STATUS_ERROR; - doorbells[NodeId].need_mmap = false; doorbells[NodeId].doorbells = ptr; return HSAKMT_STATUS_SUCCESS; @@ -324,19 +339,18 @@ static HSAKMT_STATUS map_doorbell_dgpu(HSAuint32 NodeId, HSAuint32 gpu_id, { void *ptr; - ptr = fmm_allocate_doorbell(gpu_id, DOORBELLS_PAGE_SIZE, + ptr = fmm_allocate_doorbell(gpu_id, doorbells[NodeId].size, doorbell_offset); if (ptr == NULL) return HSAKMT_STATUS_ERROR; /* map for GPU access */ - if (fmm_map_to_gpu(ptr, DOORBELLS_PAGE_SIZE, NULL)) { + if (fmm_map_to_gpu(ptr, doorbells[NodeId].size, NULL)) { fmm_release(ptr); return HSAKMT_STATUS_ERROR; } - doorbells[NodeId].need_mmap = false; doorbells[NodeId].doorbells = ptr; return HSAKMT_STATUS_SUCCESS; @@ -348,16 +362,22 @@ static HSAKMT_STATUS map_doorbell(HSAuint32 NodeId, HSAuint32 gpu_id, HSAKMT_STATUS status = HSAKMT_STATUS_SUCCESS; pthread_mutex_lock(&doorbells[NodeId].doorbells_mutex); - if (!doorbells[NodeId].need_mmap) { + if (doorbells[NodeId].size) { pthread_mutex_unlock(&doorbells[NodeId].doorbells_mutex); return HSAKMT_STATUS_SUCCESS; } - if (use_gpuvm_doorbell(get_device_id_by_node(NodeId))) + get_doorbell_map_info(get_device_id_by_node(NodeId), + &doorbells[NodeId]); + + if (doorbells[NodeId].use_gpuvm) status = map_doorbell_dgpu(NodeId, gpu_id, doorbell_offset); else status = map_doorbell_apu(NodeId, gpu_id, doorbell_offset); + if (status != HSAKMT_STATUS_SUCCESS) + doorbells[NodeId].size = 0; + pthread_mutex_unlock(&doorbells[NodeId].doorbells_mutex); return status; @@ -619,7 +639,9 @@ hsaKmtCreateQueue( } QueueResource->QueueId = PORT_VPTR_TO_UINT64(q); - QueueResource->Queue_DoorBell = VOID_PTR_ADD32(doorbells[NodeId].doorbells, q->queue_id); + QueueResource->Queue_DoorBell = VOID_PTR_ADD(doorbells[NodeId].doorbells, + (q->queue_id * + dev_info->doorbell_size)); return HSAKMT_STATUS_SUCCESS; }