void kbase_pm_do_poweroff(kbase_device *kbdev) { unsigned long flags; mali_bool cores_are_available; lockdep_assert_held(&kbdev->pm.lock); spin_lock_irqsave(&kbdev->pm.power_change_lock, flags); /* Force all cores off */ kbdev->pm.desired_shader_state = 0; /* Force all cores to be unavailable, in the situation where * transitions are in progress for some cores but not others, * and kbase_pm_check_transitions_nolock can not immediately * power off the cores */ kbdev->shader_available_bitmap = 0; kbdev->tiler_available_bitmap = 0; kbdev->l2_available_bitmap = 0; KBASE_TIMELINE_PM_CHECKTRANS(kbdev, SW_FLOW_PM_CHECKTRANS_PM_DO_POWEROFF_START); cores_are_available = kbase_pm_check_transitions_nolock(kbdev); KBASE_TIMELINE_PM_CHECKTRANS(kbdev, SW_FLOW_PM_CHECKTRANS_PM_DO_POWEROFF_END); /* Don't need 'cores_are_available', because we don't return anything */ CSTD_UNUSED(cores_are_available); spin_unlock_irqrestore(&kbdev->pm.power_change_lock, flags); /* NOTE: We won't wait to reach the core's desired state, even if we're * powering off the GPU itself too. It's safe to cut the power whilst * they're transitioning to off, because the cores should be idle and all * cache flushes should already have occurred */ /* Consume any change-state events */ kbase_timeline_pm_check_handle_event(kbdev, KBASE_TIMELINE_PM_EVENT_GPU_STATE_CHANGED); /* Disable interrupts and turn the clock off */ kbase_pm_clock_off(kbdev); }
/** Check whether a state change has finished, and trace it as completed */ STATIC void kbase_pm_trace_check_and_finish_state_change(kbase_device *kbdev) { if ((kbdev->shader_available_bitmap & kbdev->pm.desired_shader_state) == kbdev->pm.desired_shader_state && (kbdev->tiler_available_bitmap & kbdev->pm.desired_tiler_state) == kbdev->pm.desired_tiler_state) kbase_timeline_pm_check_handle_event(kbdev, KBASE_TIMELINE_PM_EVENT_GPU_STATE_CHANGED); }