diff options
Diffstat (limited to 'drivers/gpu/arm/midgard/mali_kbase_gator_api.c')
-rw-r--r-- | drivers/gpu/arm/midgard/mali_kbase_gator_api.c | 239 |
1 files changed, 116 insertions, 123 deletions
diff --git a/drivers/gpu/arm/midgard/mali_kbase_gator_api.c b/drivers/gpu/arm/midgard/mali_kbase_gator_api.c index 4af3e4815e95..a2174b24ac3c 100644 --- a/drivers/gpu/arm/midgard/mali_kbase_gator_api.c +++ b/drivers/gpu/arm/midgard/mali_kbase_gator_api.c @@ -1,6 +1,6 @@ /* * - * (C) COPYRIGHT 2014-2016 ARM Limited. All rights reserved. + * (C) COPYRIGHT 2014-2015 ARM Limited. All rights reserved. * * This program is free software and is provided to you under the terms of the * GNU General Public License version 2 as published by the Free Software @@ -20,6 +20,7 @@ #include "mali_kbase_mem_linux.h" #include "mali_kbase_gator_api.h" #include "mali_kbase_gator_hwcnt_names.h" +#include "mali_kbase_instr.h" #define MALI_MAX_CORES_PER_GROUP 4 #define MALI_MAX_NUM_BLOCKS_PER_GROUP 8 @@ -27,23 +28,18 @@ #define MALI_BYTES_PER_COUNTER 4 struct kbase_gator_hwcnt_handles { - struct kbase_device *kbdev; - struct kbase_vinstr_client *vinstr_cli; - void *vinstr_buffer; - struct work_struct dump_work; - int dump_complete; - spinlock_t dump_lock; + struct kbase_device *kbdev; + struct kbase_context *kctx; + u64 hwcnt_gpu_va; + void *hwcnt_cpu_va; + struct kbase_vmap_struct hwcnt_map; }; -static void dump_worker(struct work_struct *work); - const char * const *kbase_gator_hwcnt_init_names(uint32_t *total_counters) { + uint32_t gpu_id; const char * const *hardware_counters; struct kbase_device *kbdev; - uint32_t gpu_id; - uint32_t product_id; - uint32_t count; if (!total_counters) return NULL; @@ -54,78 +50,58 @@ const char * const *kbase_gator_hwcnt_init_names(uint32_t *total_counters) return NULL; gpu_id = kbdev->gpu_props.props.core_props.product_id; - product_id = gpu_id & GPU_ID_VERSION_PRODUCT_ID; - product_id >>= GPU_ID_VERSION_PRODUCT_ID_SHIFT; - - if (GPU_ID_IS_NEW_FORMAT(product_id)) { - switch (gpu_id & GPU_ID2_PRODUCT_MODEL) { - case GPU_ID2_PRODUCT_TMIX: - hardware_counters = hardware_counters_mali_tMIx; - count = ARRAY_SIZE(hardware_counters_mali_tMIx); - break; - default: - hardware_counters = NULL; - count = 0; - dev_err(kbdev->dev, "Unrecognized gpu ID: %u\n", - gpu_id); - break; - } - } else { - switch (gpu_id) { - /* If we are using a Mali-T60x device */ - case GPU_ID_PI_T60X: - hardware_counters = hardware_counters_mali_t60x; - count = ARRAY_SIZE(hardware_counters_mali_t60x); - break; - /* If we are using a Mali-T62x device */ - case GPU_ID_PI_T62X: - hardware_counters = hardware_counters_mali_t62x; - count = ARRAY_SIZE(hardware_counters_mali_t62x); - break; - /* If we are using a Mali-T72x device */ - case GPU_ID_PI_T72X: - hardware_counters = hardware_counters_mali_t72x; - count = ARRAY_SIZE(hardware_counters_mali_t72x); - break; - /* If we are using a Mali-T76x device */ - case GPU_ID_PI_T76X: - hardware_counters = hardware_counters_mali_t76x; - count = ARRAY_SIZE(hardware_counters_mali_t76x); - break; - /* If we are using a Mali-T82x device */ - case GPU_ID_PI_T82X: - hardware_counters = hardware_counters_mali_t82x; - count = ARRAY_SIZE(hardware_counters_mali_t82x); - break; - /* If we are using a Mali-T83x device */ - case GPU_ID_PI_T83X: - hardware_counters = hardware_counters_mali_t83x; - count = ARRAY_SIZE(hardware_counters_mali_t83x); - break; - /* If we are using a Mali-T86x device */ - case GPU_ID_PI_T86X: - hardware_counters = hardware_counters_mali_t86x; - count = ARRAY_SIZE(hardware_counters_mali_t86x); - break; - /* If we are using a Mali-T88x device */ - case GPU_ID_PI_TFRX: - hardware_counters = hardware_counters_mali_t88x; - count = ARRAY_SIZE(hardware_counters_mali_t88x); - break; - default: - hardware_counters = NULL; - count = 0; - dev_err(kbdev->dev, "Unrecognized gpu ID: %u\n", - gpu_id); - break; - } + + switch (gpu_id) { + /* If we are using a Mali-T60x device */ + case GPU_ID_PI_T60X: + hardware_counters = hardware_counters_mali_t60x; + *total_counters = ARRAY_SIZE(hardware_counters_mali_t60x); + break; + /* If we are using a Mali-T62x device */ + case GPU_ID_PI_T62X: + hardware_counters = hardware_counters_mali_t62x; + *total_counters = ARRAY_SIZE(hardware_counters_mali_t62x); + break; + /* If we are using a Mali-T72x device */ + case GPU_ID_PI_T72X: + hardware_counters = hardware_counters_mali_t72x; + *total_counters = ARRAY_SIZE(hardware_counters_mali_t72x); + break; + /* If we are using a Mali-T76x device */ + case GPU_ID_PI_T76X: + hardware_counters = hardware_counters_mali_t76x; + *total_counters = ARRAY_SIZE(hardware_counters_mali_t76x); + break; + /* If we are using a Mali-T82x device */ + case GPU_ID_PI_T82X: + hardware_counters = hardware_counters_mali_t82x; + *total_counters = ARRAY_SIZE(hardware_counters_mali_t82x); + break; + /* If we are using a Mali-T83x device */ + case GPU_ID_PI_T83X: + hardware_counters = hardware_counters_mali_t83x; + *total_counters = ARRAY_SIZE(hardware_counters_mali_t83x); + break; + /* If we are using a Mali-T86x device */ + case GPU_ID_PI_T86X: + hardware_counters = hardware_counters_mali_t86x; + *total_counters = ARRAY_SIZE(hardware_counters_mali_t86x); + break; + /* If we are using a Mali-T88x device */ + case GPU_ID_PI_TFRX: + hardware_counters = hardware_counters_mali_t88x; + *total_counters = ARRAY_SIZE(hardware_counters_mali_t88x); + break; + default: + hardware_counters = NULL; + *total_counters = 0; + dev_err(kbdev->dev, "Unrecognized gpu ID: %u\n", gpu_id); + break; } /* Release the kbdev reference. */ kbase_release_device(kbdev); - *total_counters = count; - /* If we return a string array take a reference on the module (or fail). */ if (hardware_counters && !try_module_get(THIS_MODULE)) return NULL; @@ -144,8 +120,13 @@ KBASE_EXPORT_SYMBOL(kbase_gator_hwcnt_term_names); struct kbase_gator_hwcnt_handles *kbase_gator_hwcnt_init(struct kbase_gator_hwcnt_info *in_out_info) { struct kbase_gator_hwcnt_handles *hand; - struct kbase_uk_hwcnt_reader_setup setup; + struct kbase_uk_hwcnt_setup setup; + int err; uint32_t dump_size = 0, i = 0; + struct kbase_va_region *reg; + u64 flags; + u64 nr_pages; + u16 va_alignment = 0; if (!in_out_info) return NULL; @@ -154,19 +135,15 @@ struct kbase_gator_hwcnt_handles *kbase_gator_hwcnt_init(struct kbase_gator_hwcn if (!hand) return NULL; - INIT_WORK(&hand->dump_work, dump_worker); - spin_lock_init(&hand->dump_lock); - /* Get the first device */ hand->kbdev = kbase_find_device(-1); if (!hand->kbdev) goto free_hand; - dump_size = kbase_vinstr_dump_size(hand->kbdev); - hand->vinstr_buffer = kzalloc(dump_size, GFP_KERNEL); - if (!hand->vinstr_buffer) + /* Create a kbase_context */ + hand->kctx = kbase_create_context(hand->kbdev, true); + if (!hand->kctx) goto release_device; - in_out_info->kernel_dump_buffer = hand->vinstr_buffer; in_out_info->nr_cores = hand->kbdev->gpu_props.num_cores; in_out_info->nr_core_groups = hand->kbdev->gpu_props.num_core_groups; @@ -183,7 +160,7 @@ struct kbase_gator_hwcnt_handles *kbase_gator_hwcnt_init(struct kbase_gator_hwcn in_out_info->nr_core_groups, GFP_KERNEL); if (!in_out_info->hwc_layout) - goto free_vinstr_buffer; + goto destroy_context; dump_size = in_out_info->nr_core_groups * MALI_MAX_NUM_BLOCKS_PER_GROUP * @@ -212,23 +189,23 @@ struct kbase_gator_hwcnt_handles *kbase_gator_hwcnt_init(struct kbase_gator_hwcn } /* If we are using any other device */ } else { - uint32_t nr_l2, nr_sc_bits, j; + uint32_t nr_l2, nr_sc, j; uint64_t core_mask; nr_l2 = hand->kbdev->gpu_props.props.l2_props.num_l2_slices; core_mask = hand->kbdev->gpu_props.props.coherency_info.group[0].core_mask; - nr_sc_bits = fls64(core_mask); + nr_sc = hand->kbdev->gpu_props.props.coherency_info.group[0].num_cores; /* The job manager and tiler sets of counters * are always present */ - in_out_info->hwc_layout = kmalloc(sizeof(enum hwc_type) * (2 + nr_sc_bits + nr_l2), GFP_KERNEL); + in_out_info->hwc_layout = kmalloc(sizeof(enum hwc_type) * (2 + nr_sc + nr_l2), GFP_KERNEL); if (!in_out_info->hwc_layout) - goto free_vinstr_buffer; + goto destroy_context; - dump_size = (2 + nr_sc_bits + nr_l2) * MALI_COUNTERS_PER_BLOCK * MALI_BYTES_PER_COUNTER; + dump_size = (2 + nr_sc + nr_l2) * MALI_COUNTERS_PER_BLOCK * MALI_BYTES_PER_COUNTER; in_out_info->hwc_layout[i++] = JM_BLOCK; in_out_info->hwc_layout[i++] = TILER_BLOCK; @@ -246,32 +223,58 @@ struct kbase_gator_hwcnt_handles *kbase_gator_hwcnt_init(struct kbase_gator_hwcn } in_out_info->nr_hwc_blocks = i; + in_out_info->size = dump_size; + flags = BASE_MEM_PROT_CPU_RD | BASE_MEM_PROT_CPU_WR | BASE_MEM_PROT_GPU_WR; + nr_pages = PFN_UP(dump_size); + reg = kbase_mem_alloc(hand->kctx, nr_pages, nr_pages, 0, + &flags, &hand->hwcnt_gpu_va, &va_alignment); + if (!reg) + goto free_layout; + + hand->hwcnt_cpu_va = kbase_vmap(hand->kctx, hand->hwcnt_gpu_va, + dump_size, &hand->hwcnt_map); + + if (!hand->hwcnt_cpu_va) + goto free_buffer; + + in_out_info->kernel_dump_buffer = hand->hwcnt_cpu_va; + memset(in_out_info->kernel_dump_buffer, 0, nr_pages * PAGE_SIZE); + + /*setup.dump_buffer = (uintptr_t)in_out_info->kernel_dump_buffer;*/ + setup.dump_buffer = hand->hwcnt_gpu_va; setup.jm_bm = in_out_info->bitmask[0]; setup.tiler_bm = in_out_info->bitmask[1]; setup.shader_bm = in_out_info->bitmask[2]; setup.mmu_l2_bm = in_out_info->bitmask[3]; - hand->vinstr_cli = kbase_vinstr_hwcnt_kernel_setup(hand->kbdev->vinstr_ctx, - &setup, hand->vinstr_buffer); - if (!hand->vinstr_cli) { - dev_err(hand->kbdev->dev, "Failed to register gator with vinstr core"); - goto free_layout; - } + + err = kbase_instr_hwcnt_enable(hand->kctx, &setup); + if (err) + goto free_unmap; + + kbase_instr_hwcnt_clear(hand->kctx); return hand; +free_unmap: + kbase_vunmap(hand->kctx, &hand->hwcnt_map); + +free_buffer: + kbase_mem_free(hand->kctx, hand->hwcnt_gpu_va); + free_layout: kfree(in_out_info->hwc_layout); -free_vinstr_buffer: - kfree(hand->vinstr_buffer); +destroy_context: + kbase_destroy_context(hand->kctx); release_device: kbase_release_device(hand->kbdev); free_hand: kfree(hand); + return NULL; } KBASE_EXPORT_SYMBOL(kbase_gator_hwcnt_init); @@ -282,39 +285,27 @@ void kbase_gator_hwcnt_term(struct kbase_gator_hwcnt_info *in_out_info, struct k kfree(in_out_info->hwc_layout); if (opaque_handles) { - cancel_work_sync(&opaque_handles->dump_work); - kbase_vinstr_detach_client(opaque_handles->vinstr_cli); - kfree(opaque_handles->vinstr_buffer); + kbase_instr_hwcnt_disable(opaque_handles->kctx); + kbase_vunmap(opaque_handles->kctx, &opaque_handles->hwcnt_map); + kbase_mem_free(opaque_handles->kctx, opaque_handles->hwcnt_gpu_va); + kbase_destroy_context(opaque_handles->kctx); kbase_release_device(opaque_handles->kbdev); kfree(opaque_handles); } } KBASE_EXPORT_SYMBOL(kbase_gator_hwcnt_term); -static void dump_worker(struct work_struct *work) -{ - struct kbase_gator_hwcnt_handles *hand; - - hand = container_of(work, struct kbase_gator_hwcnt_handles, dump_work); - if (!kbase_vinstr_hwc_dump(hand->vinstr_cli, - BASE_HWCNT_READER_EVENT_MANUAL)) { - spin_lock_bh(&hand->dump_lock); - hand->dump_complete = 1; - spin_unlock_bh(&hand->dump_lock); - } else { - schedule_work(&hand->dump_work); - } -} - uint32_t kbase_gator_instr_hwcnt_dump_complete( struct kbase_gator_hwcnt_handles *opaque_handles, uint32_t * const success) { + bool ret_res, success_res; if (opaque_handles && success) { - *success = opaque_handles->dump_complete; - opaque_handles->dump_complete = 0; - return *success; + ret_res = kbase_instr_hwcnt_dump_complete(opaque_handles->kctx, + &success_res); + *success = (uint32_t)success_res; + return (uint32_t)(ret_res != 0); } return 0; } @@ -323,7 +314,9 @@ KBASE_EXPORT_SYMBOL(kbase_gator_instr_hwcnt_dump_complete); uint32_t kbase_gator_instr_hwcnt_dump_irq(struct kbase_gator_hwcnt_handles *opaque_handles) { if (opaque_handles) - schedule_work(&opaque_handles->dump_work); + return (kbase_instr_hwcnt_request_dump( + opaque_handles->kctx) == 0); + return 0; } KBASE_EXPORT_SYMBOL(kbase_gator_instr_hwcnt_dump_irq); |