4b903cca020b736eea3fcab8fc2fbcca330b4b01
[firefly-linux-kernel-4.4.55.git] / drivers / gpu / arm / midgard / backend / gpu / mali_kbase_pm_ca.c
1 /*
2  *
3  * (C) COPYRIGHT 2013-2015 ARM Limited. All rights reserved.
4  *
5  * This program is free software and is provided to you under the terms of the
6  * GNU General Public License version 2 as published by the Free Software
7  * Foundation, and any use by you of this program is subject to the terms
8  * of such GNU licence.
9  *
10  * A copy of the licence is included with the program, and can also be obtained
11  * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
12  * Boston, MA  02110-1301, USA.
13  *
14  */
15
16
17
18 /*
19  * Base kernel core availability APIs
20  */
21
22 #include <mali_kbase.h>
23 #include <mali_kbase_pm.h>
24 #include <backend/gpu/mali_kbase_pm_internal.h>
25
26 static const struct kbase_pm_ca_policy *const policy_list[] = {
27         &kbase_pm_ca_fixed_policy_ops,
28 #if !MALI_CUSTOMER_RELEASE
29         &kbase_pm_ca_random_policy_ops
30 #endif
31 };
32
33 /**
34  * POLICY_COUNT - The number of policies available in the system.
35  *
36  * This is derived from the number of functions listed in policy_list.
37  */
38 #define POLICY_COUNT (sizeof(policy_list)/sizeof(*policy_list))
39
40 int kbase_pm_ca_init(struct kbase_device *kbdev)
41 {
42         KBASE_DEBUG_ASSERT(kbdev != NULL);
43
44         kbdev->pm.backend.ca_current_policy = policy_list[0];
45
46         kbdev->pm.backend.ca_current_policy->init(kbdev);
47
48         return 0;
49 }
50
51 void kbase_pm_ca_term(struct kbase_device *kbdev)
52 {
53         kbdev->pm.backend.ca_current_policy->term(kbdev);
54 }
55
56 int kbase_pm_ca_list_policies(const struct kbase_pm_ca_policy * const **list)
57 {
58         if (!list)
59                 return POLICY_COUNT;
60
61         *list = policy_list;
62
63         return POLICY_COUNT;
64 }
65
66 KBASE_EXPORT_TEST_API(kbase_pm_ca_list_policies);
67
68 const struct kbase_pm_ca_policy
69 *kbase_pm_ca_get_policy(struct kbase_device *kbdev)
70 {
71         KBASE_DEBUG_ASSERT(kbdev != NULL);
72
73         return kbdev->pm.backend.ca_current_policy;
74 }
75
76 KBASE_EXPORT_TEST_API(kbase_pm_ca_get_policy);
77
78 void kbase_pm_ca_set_policy(struct kbase_device *kbdev,
79                                 const struct kbase_pm_ca_policy *new_policy)
80 {
81         const struct kbase_pm_ca_policy *old_policy;
82         unsigned long flags;
83
84         KBASE_DEBUG_ASSERT(kbdev != NULL);
85         KBASE_DEBUG_ASSERT(new_policy != NULL);
86
87         KBASE_TRACE_ADD(kbdev, PM_CA_SET_POLICY, NULL, NULL, 0u,
88                                                                 new_policy->id);
89
90         /* During a policy change we pretend the GPU is active */
91         /* A suspend won't happen here, because we're in a syscall from a
92          * userspace thread */
93         kbase_pm_context_active(kbdev);
94
95         mutex_lock(&kbdev->pm.lock);
96
97         /* Remove the policy to prevent IRQ handlers from working on it */
98         spin_lock_irqsave(&kbdev->pm.power_change_lock, flags);
99         old_policy = kbdev->pm.backend.ca_current_policy;
100         kbdev->pm.backend.ca_current_policy = NULL;
101         spin_unlock_irqrestore(&kbdev->pm.power_change_lock, flags);
102
103         if (old_policy->term)
104                 old_policy->term(kbdev);
105
106         if (new_policy->init)
107                 new_policy->init(kbdev);
108
109         spin_lock_irqsave(&kbdev->pm.power_change_lock, flags);
110         kbdev->pm.backend.ca_current_policy = new_policy;
111
112         /* If any core power state changes were previously attempted, but
113          * couldn't be made because the policy was changing (current_policy was
114          * NULL), then re-try them here. */
115         kbase_pm_update_cores_state_nolock(kbdev);
116
117         kbdev->pm.backend.ca_current_policy->update_core_status(kbdev,
118                                         kbdev->shader_ready_bitmap,
119                                         kbdev->shader_transitioning_bitmap);
120
121         spin_unlock_irqrestore(&kbdev->pm.power_change_lock, flags);
122
123         mutex_unlock(&kbdev->pm.lock);
124
125         /* Now the policy change is finished, we release our fake context active
126          * reference */
127         kbase_pm_context_idle(kbdev);
128 }
129
130 KBASE_EXPORT_TEST_API(kbase_pm_ca_set_policy);
131
132 u64 kbase_pm_ca_get_core_mask(struct kbase_device *kbdev)
133 {
134         lockdep_assert_held(&kbdev->pm.power_change_lock);
135
136         /* All cores must be enabled when instrumentation is in use */
137         if (kbdev->pm.backend.instr_enabled)
138                 return kbdev->gpu_props.props.raw_props.shader_present &
139                                 kbdev->pm.debug_core_mask_all;
140
141         if (kbdev->pm.backend.ca_current_policy == NULL)
142                 return kbdev->gpu_props.props.raw_props.shader_present &
143                                 kbdev->pm.debug_core_mask_all;
144
145         return kbdev->pm.backend.ca_current_policy->get_core_mask(kbdev) &
146                                                 kbdev->pm.debug_core_mask_all;
147 }
148
149 KBASE_EXPORT_TEST_API(kbase_pm_ca_get_core_mask);
150
151 void kbase_pm_ca_update_core_status(struct kbase_device *kbdev, u64 cores_ready,
152                                                         u64 cores_transitioning)
153 {
154         lockdep_assert_held(&kbdev->pm.power_change_lock);
155
156         if (kbdev->pm.backend.ca_current_policy != NULL)
157                 kbdev->pm.backend.ca_current_policy->update_core_status(kbdev,
158                                                         cores_ready,
159                                                         cores_transitioning);
160 }
161
162 void kbase_pm_ca_instr_enable(struct kbase_device *kbdev)
163 {
164         unsigned long flags;
165
166         spin_lock_irqsave(&kbdev->pm.power_change_lock, flags);
167         kbdev->pm.backend.instr_enabled = true;
168
169         kbase_pm_update_cores_state_nolock(kbdev);
170         spin_unlock_irqrestore(&kbdev->pm.power_change_lock, flags);
171 }
172
173 void kbase_pm_ca_instr_disable(struct kbase_device *kbdev)
174 {
175         unsigned long flags;
176
177         spin_lock_irqsave(&kbdev->pm.power_change_lock, flags);
178         kbdev->pm.backend.instr_enabled = false;
179
180         kbase_pm_update_cores_state_nolock(kbdev);
181         spin_unlock_irqrestore(&kbdev->pm.power_change_lock, flags);
182 }