diff options
Diffstat (limited to 'drivers/gpu/arm/utgard/common/mali_timeline.c')
-rw-r--r-- | drivers/gpu/arm/utgard/common/mali_timeline.c | 95 |
1 files changed, 89 insertions, 6 deletions
diff --git a/drivers/gpu/arm/utgard/common/mali_timeline.c b/drivers/gpu/arm/utgard/common/mali_timeline.c index bba60b4ec71c..5a767b39d56e 100644 --- a/drivers/gpu/arm/utgard/common/mali_timeline.c +++ b/drivers/gpu/arm/utgard/common/mali_timeline.c @@ -1,9 +1,9 @@ /* - * Copyright (C) 2013-2014 ARM Limited. All rights reserved. - * + * Copyright (C) 2013-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. */ @@ -115,6 +115,11 @@ static void mali_timeline_sync_fence_callback(struct sync_fence *sync_fence, str mali_spinlock_reentrant_signal(system->spinlock, tid); + /* + * Older versions of Linux, before 3.5, doesn't support fput() in interrupt + * context. For those older kernels, allocate a list object and put the + * fence object on that and defer the call to sync_fence_put() to a workqueue. + */ #if LINUX_VERSION_CODE < KERNEL_VERSION(3,5,0) { struct mali_deferred_fence_put_entry *obj; @@ -243,7 +248,9 @@ static void mali_timeline_destroy(struct mali_timeline *timeline) _mali_osk_wq_delayed_delete_work_nonflush(timeline->delayed_work); } +#ifndef CONFIG_SYNC _mali_osk_free(timeline); +#endif } } @@ -301,11 +308,19 @@ static struct mali_timeline *mali_timeline_create(struct mali_timeline_system *s return NULL; } + timeline->destroyed = MALI_FALSE; + timeline->sync_tl = mali_sync_timeline_create(timeline, timeline_name); if (NULL == timeline->sync_tl) { mali_timeline_destroy(timeline); return NULL; } + + timeline->spinlock = mali_spinlock_reentrant_init(_MALI_OSK_LOCK_ORDER_TIMELINE_SYSTEM); + if (NULL == timeline->spinlock) { + mali_timeline_destroy(timeline); + return NULL; + } } #endif /* defined(CONFIG_SYNC) */ @@ -642,19 +657,18 @@ static mali_scheduler_mask mali_timeline_tracker_activate(struct mali_timeline_t _mali_osk_atomic_dec(&gp_tracker_count); break; case MALI_TIMELINE_TRACKER_PP: - schedule_mask = mali_scheduler_activate_pp_job((struct mali_pp_job *) tracker->job); - if (mali_pp_job_is_virtual((struct mali_pp_job *)tracker->job)) { _mali_osk_atomic_dec(&virt_pp_tracker_count); } else { _mali_osk_atomic_dec(&phy_pp_tracker_count); } + schedule_mask = mali_scheduler_activate_pp_job((struct mali_pp_job *) tracker->job); break; case MALI_TIMELINE_TRACKER_SOFT: timeline = tracker->timeline; MALI_DEBUG_ASSERT_POINTER(timeline); - mali_soft_job_system_activate_job((struct mali_soft_job *) tracker->job); + schedule_mask |= mali_soft_job_system_activate_job((struct mali_soft_job *) tracker->job); /* Start a soft timer to make sure the soft job be released in a limited time */ mali_spinlock_reentrant_wait(system->spinlock, tid); @@ -898,6 +912,9 @@ void mali_timeline_system_destroy(struct mali_timeline_system *system) { u32 i; struct mali_timeline_waiter *waiter, *next; +#if defined(CONFIG_SYNC) + u32 tid = _mali_osk_get_tid(); +#endif MALI_DEBUG_ASSERT_POINTER(system); MALI_DEBUG_ASSERT_POINTER(system->session); @@ -905,6 +922,7 @@ void mali_timeline_system_destroy(struct mali_timeline_system *system) MALI_DEBUG_PRINT(4, ("Mali Timeline: destroying timeline system\n")); if (NULL != system) { + /* There should be no waiters left on this queue. */ if (NULL != system->wait_queue) { _mali_osk_wait_queue_term(system->wait_queue); @@ -923,6 +941,14 @@ void mali_timeline_system_destroy(struct mali_timeline_system *system) if (NULL != system->signaled_sync_tl) { sync_timeline_destroy(system->signaled_sync_tl); } + + for (i = 0; i < MALI_TIMELINE_MAX; ++i) { + if ((NULL != system->timelines[i]) && (NULL != system->timelines[i]->spinlock)) { + mali_spinlock_reentrant_wait(system->timelines[i]->spinlock, tid); + system->timelines[i]->destroyed = MALI_TRUE; + mali_spinlock_reentrant_signal(system->timelines[i]->spinlock, tid); + } + } #endif /* defined(CONFIG_SYNC) */ for (i = 0; i < MALI_TIMELINE_MAX; ++i) { @@ -930,6 +956,7 @@ void mali_timeline_system_destroy(struct mali_timeline_system *system) mali_timeline_destroy(system->timelines[i]); } } + if (NULL != system->spinlock) { mali_spinlock_reentrant_term(system->spinlock); } @@ -1468,6 +1495,62 @@ void mali_timeline_debug_print_timeline(struct mali_timeline *timeline, _mali_os } } +#if !(LINUX_VERSION_CODE < KERNEL_VERSION(3, 17, 0)) +void mali_timeline_debug_direct_print_tracker(struct mali_timeline_tracker *tracker) +{ + const char *tracker_state = "IWAF"; + char state_char = 'I'; + char tracker_type[32] = {0}; + + MALI_DEBUG_ASSERT_POINTER(tracker); + + state_char = *(tracker_state + mali_timeline_debug_get_tracker_state(tracker)); + _mali_osk_snprintf(tracker_type, sizeof(tracker_type), "%s", timeline_tracker_type_to_string(tracker->type)); + +#if defined(CONFIG_SYNC) + if (0 != tracker->trigger_ref_count) { + MALI_PRINT(("TL: %s %u %c - ref_wait:%u [%s(%u),%s(%u),%s(%u), fd:%d, fence:(0x%08X)] job:(0x%08X)\n", + tracker_type, tracker->point, state_char, tracker->trigger_ref_count, + is_waiting_on_timeline(tracker, MALI_TIMELINE_GP) ? "WaitGP" : " ", tracker->fence.points[0], + is_waiting_on_timeline(tracker, MALI_TIMELINE_PP) ? "WaitPP" : " ", tracker->fence.points[1], + is_waiting_on_timeline(tracker, MALI_TIMELINE_SOFT) ? "WaitSOFT" : " ", tracker->fence.points[2], + tracker->fence.sync_fd, tracker->sync_fence, tracker->job)); + } else { + MALI_PRINT(("TL: %s %u %c fd:%d fence:(0x%08X) job:(0x%08X)\n", + tracker_type, tracker->point, state_char, + tracker->fence.sync_fd, tracker->sync_fence, tracker->job)); + } +#else + if (0 != tracker->trigger_ref_count) { + MALI_PRINT(("TL: %s %u %c - ref_wait:%u [%s(%u),%s(%u),%s(%u)] job:(0x%08X)\n", + tracker_type, tracker->point, state_char, tracker->trigger_ref_count, + is_waiting_on_timeline(tracker, MALI_TIMELINE_GP) ? "WaitGP" : " ", tracker->fence.points[0], + is_waiting_on_timeline(tracker, MALI_TIMELINE_PP) ? "WaitPP" : " ", tracker->fence.points[1], + is_waiting_on_timeline(tracker, MALI_TIMELINE_SOFT) ? "WaitSOFT" : " ", tracker->fence.points[2], + tracker->job)); + } else { + MALI_PRINT(("TL: %s %u %c job:(0x%08X)\n", + tracker_type, tracker->point, state_char, + tracker->job)); + } +#endif +} + +void mali_timeline_debug_direct_print_timeline(struct mali_timeline *timeline) +{ + struct mali_timeline_tracker *tracker = NULL; + + MALI_DEBUG_ASSERT_POINTER(timeline); + + tracker = timeline->tracker_tail; + while (NULL != tracker) { + mali_timeline_debug_direct_print_tracker(tracker); + tracker = tracker->timeline_next; + } +} + +#endif + void mali_timeline_debug_print_system(struct mali_timeline_system *system, _mali_osk_print_ctx *print_ctx) { int i; |