/* * * (C) COPYRIGHT 2011-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 * Foundation, and any use by you of this program is subject to the terms * of such GNU licence. * * A copy of the licence is included with the program, and can also be obtained * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. * */ /* * Base kernel instrumentation APIs. */ #include #include void kbase_instr_hwcnt_suspend(struct kbase_device *kbdev) { struct kbase_context *kctx; KBASE_DEBUG_ASSERT(kbdev); KBASE_DEBUG_ASSERT(!kbdev->hwcnt.suspended_kctx); kctx = kbdev->hwcnt.kctx; kbdev->hwcnt.suspended_kctx = kctx; /* Relevant state was saved into hwcnt.suspended_state when enabling the * counters */ if (kctx) { KBASE_DEBUG_ASSERT(kctx->jctx.sched_info.ctx.flags & KBASE_CTX_FLAG_PRIVILEGED); kbase_instr_hwcnt_disable(kctx); } } void kbase_instr_hwcnt_resume(struct kbase_device *kbdev) { struct kbase_context *kctx; KBASE_DEBUG_ASSERT(kbdev); kctx = kbdev->hwcnt.suspended_kctx; kbdev->hwcnt.suspended_kctx = NULL; if (kctx) { int err; err = kbase_instr_hwcnt_enable_internal(kbdev, kctx, &kbdev->hwcnt.suspended_state); WARN(err, "Failed to restore instrumented hardware counters on resume\n"); } } int kbase_instr_hwcnt_enable(struct kbase_context *kctx, struct kbase_uk_hwcnt_setup *setup) { struct kbase_device *kbdev; int err; kbdev = kctx->kbdev; /* Mark the context as active so the GPU is kept turned on */ /* A suspend won't happen here, because we're in a syscall from a * userspace thread. */ kbase_pm_context_active(kbdev); /* Schedule the context in */ kbasep_js_schedule_privileged_ctx(kbdev, kctx); err = kbase_instr_hwcnt_enable_internal(kbdev, kctx, setup); if (err) { /* Release the context. This had its own Power Manager Active * reference */ kbasep_js_release_privileged_ctx(kbdev, kctx); /* Also release our Power Manager Active reference */ kbase_pm_context_idle(kbdev); } return err; } KBASE_EXPORT_SYMBOL(kbase_instr_hwcnt_enable); int kbase_instr_hwcnt_disable(struct kbase_context *kctx) { int err = -EINVAL; struct kbase_device *kbdev = kctx->kbdev; err = kbase_instr_hwcnt_disable_internal(kctx); if (err) goto out; /* Release the context. This had its own Power Manager Active reference */ kbasep_js_release_privileged_ctx(kbdev, kctx); /* Also release our Power Manager Active reference */ kbase_pm_context_idle(kbdev); dev_dbg(kbdev->dev, "HW counters dumping disabled for context %p", kctx); out: return err; } KBASE_EXPORT_SYMBOL(kbase_instr_hwcnt_disable); int kbase_instr_hwcnt_dump(struct kbase_context *kctx) { int err; err = kbase_instr_hwcnt_request_dump(kctx); if (err) return err; err = kbase_instr_hwcnt_wait_for_dump(kctx); return err; } KBASE_EXPORT_SYMBOL(kbase_instr_hwcnt_dump);