blob: cc073dfa42d91e4c54f4eabbfc97c9ff7a1957ef
1 | /* |
2 | * Copyright (C) 2013 ARM Limited. All rights reserved. |
3 | * |
4 | * Copyright (C) 2008 The Android Open Source Project |
5 | * |
6 | * Licensed under the Apache License, Version 2.0 (the "License"); |
7 | * you may not use this file except in compliance with the License. |
8 | * You may obtain a copy of the License at |
9 | * |
10 | * http://www.apache.org/licenses/LICENSE-2.0 |
11 | * |
12 | * Unless required by applicable law or agreed to in writing, software |
13 | * distributed under the License is distributed on an "AS IS" BASIS, |
14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
15 | * See the License for the specific language governing permissions and |
16 | * limitations under the License. |
17 | */ |
18 | |
19 | #include <string.h> |
20 | #include <errno.h> |
21 | #include <pthread.h> |
22 | |
23 | #include <cutils/log.h> |
24 | #include <cutils/atomic.h> |
25 | #include <hardware/hardware.h> |
26 | #include <hardware/gralloc.h> |
27 | |
28 | #include <sys/ioctl.h> |
29 | |
30 | #include "alloc_device.h" |
31 | #include "gralloc_priv.h" |
32 | #include "gralloc_helper.h" |
33 | #include "framebuffer_device.h" |
34 | |
35 | #include <ump/ump.h> |
36 | #include <ump/ump_ref_drv.h> |
37 | |
38 | #if GRALLOC_SIMULATE_FAILURES |
39 | #include <cutils/properties.h> |
40 | |
41 | /* system property keys for controlling simulated UMP allocation failures */ |
42 | #define PROP_MALI_TEST_GRALLOC_FAIL_FIRST "mali.test.gralloc.fail_first" |
43 | #define PROP_MALI_TEST_GRALLOC_FAIL_INTERVAL "mali.test.gralloc.fail_interval" |
44 | |
45 | static int __ump_alloc_should_fail() |
46 | { |
47 | |
48 | static unsigned int call_count = 0; |
49 | unsigned int first_fail = 0; |
50 | int fail_period = 0; |
51 | int fail = 0; |
52 | |
53 | ++call_count; |
54 | |
55 | /* read the system properties that control failure simulation */ |
56 | { |
57 | char prop_value[PROPERTY_VALUE_MAX]; |
58 | |
59 | if (property_get(PROP_MALI_TEST_GRALLOC_FAIL_FIRST, prop_value, "0") > 0) |
60 | { |
61 | sscanf(prop_value, "%11u", &first_fail); |
62 | } |
63 | |
64 | if (property_get(PROP_MALI_TEST_GRALLOC_FAIL_INTERVAL, prop_value, "0") > 0) |
65 | { |
66 | sscanf(prop_value, "%11u", &fail_period); |
67 | } |
68 | } |
69 | |
70 | /* failure simulation is enabled by setting the first_fail property to non-zero */ |
71 | if (first_fail > 0) |
72 | { |
73 | LOGI("iteration %u (fail=%u, period=%u)\n", call_count, first_fail, fail_period); |
74 | |
75 | fail = (call_count == first_fail) || |
76 | (call_count > first_fail && fail_period > 0 && 0 == (call_count - first_fail) % fail_period); |
77 | |
78 | if (fail) |
79 | { |
80 | AERR("failed ump_ref_drv_allocate on iteration #%d\n", call_count); |
81 | } |
82 | } |
83 | return fail; |
84 | } |
85 | #endif |
86 | |
87 | int alloc_backend_alloc(alloc_device_t* dev, size_t size, int usage, buffer_handle_t* pHandle) |
88 | { |
89 | { |
90 | ump_handle ump_mem_handle; |
91 | void *cpu_ptr; |
92 | ump_secure_id ump_id; |
93 | ump_alloc_constraints constraints; |
94 | |
95 | size = round_up_to_page_size(size); |
96 | |
97 | if ( (usage&GRALLOC_USAGE_SW_READ_MASK) == GRALLOC_USAGE_SW_READ_OFTEN ) |
98 | { |
99 | constraints = UMP_REF_DRV_CONSTRAINT_USE_CACHE; |
100 | } |
101 | else |
102 | { |
103 | constraints = UMP_REF_DRV_CONSTRAINT_NONE; |
104 | } |
105 | |
106 | #ifdef GRALLOC_SIMULATE_FAILURES |
107 | /* if the failure condition matches, fail this iteration */ |
108 | if (__ump_alloc_should_fail()) |
109 | { |
110 | ump_mem_handle = UMP_INVALID_MEMORY_HANDLE; |
111 | } |
112 | else |
113 | #endif |
114 | { |
115 | /* protected memory not supported in UMP */ |
116 | if (!(usage & GRALLOC_USAGE_PROTECTED)) |
117 | { |
118 | ump_mem_handle = ump_ref_drv_allocate(size, constraints); |
119 | |
120 | if (UMP_INVALID_MEMORY_HANDLE != ump_mem_handle) |
121 | { |
122 | cpu_ptr = ump_mapped_pointer_get(ump_mem_handle); |
123 | if (NULL != cpu_ptr) |
124 | { |
125 | ump_id = ump_secure_id_get(ump_mem_handle); |
126 | if (UMP_INVALID_SECURE_ID != ump_id) |
127 | { |
128 | private_handle_t* hnd = new private_handle_t(private_handle_t::PRIV_FLAGS_USES_UMP, |
129 | usage, |
130 | size, |
131 | cpu_ptr, |
132 | private_handle_t::LOCK_STATE_MAPPED, |
133 | ump_id, |
134 | ump_mem_handle); |
135 | |
136 | if (NULL != hnd) |
137 | { |
138 | *pHandle = hnd; |
139 | return 0; |
140 | } |
141 | else |
142 | { |
143 | AERR( "gralloc_alloc_buffer() failed to allocate handle. ump_handle = %p, ump_id = %d", ump_mem_handle, ump_id ); |
144 | } |
145 | } |
146 | else |
147 | { |
148 | AERR( "gralloc_alloc_buffer() failed to retrieve valid secure id. ump_handle = %p", ump_mem_handle ); |
149 | } |
150 | |
151 | ump_mapped_pointer_release(ump_mem_handle); |
152 | } |
153 | else |
154 | { |
155 | AERR( "gralloc_alloc_buffer() failed to map UMP memory. ump_handle = %p", ump_mem_handle ); |
156 | } |
157 | |
158 | ump_reference_release(ump_mem_handle); |
159 | } |
160 | else |
161 | { |
162 | AERR( "gralloc_alloc_buffer() failed to allocate UMP memory. size:%d constraints: %d", size, constraints ); |
163 | } |
164 | } |
165 | else |
166 | { |
167 | AERR( "gralloc_alloc_buffer() protected UMP memory is not supported."); |
168 | } |
169 | } |
170 | return -1; |
171 | } |
172 | } |
173 | |
174 | int alloc_backend_alloc_framebuffer(private_module_t* m, private_handle_t* hnd, uint32_t idx) |
175 | { |
176 | hnd->ump_id = m->framebuffer->ump_id; |
177 | /* create a backing ump memory handle if the framebuffer is exposed as a secure ID */ |
178 | if ( (int)UMP_INVALID_SECURE_ID != hnd->ump_id ) |
179 | { |
180 | hnd->ump_mem_handle = ump_handle_create_from_secure_id( hnd->ump_id ); |
181 | if ( UMP_INVALID_MEMORY_HANDLE == hnd->ump_mem_handle ) |
182 | { |
183 | AERR("unable to create UMP handle from secure ID %i\n", hnd->ump_id); |
184 | return -1; |
185 | } |
186 | } |
187 | |
188 | return 0; |
189 | } |
190 | |
191 | void alloc_backend_alloc_free(private_handle_t const* hnd, private_module_t* m) |
192 | { |
193 | if (hnd->flags & private_handle_t::PRIV_FLAGS_FRAMEBUFFER) |
194 | { |
195 | if ( UMP_INVALID_MEMORY_HANDLE != hnd->ump_mem_handle ) |
196 | { |
197 | ump_reference_release((ump_handle)hnd->ump_mem_handle); |
198 | } |
199 | } |
200 | else if (hnd->flags & private_handle_t::PRIV_FLAGS_USES_UMP) |
201 | { |
202 | /* Buffer might be unregistered so we need to check for invalid ump handle*/ |
203 | if ( UMP_INVALID_MEMORY_HANDLE != hnd->ump_mem_handle ) |
204 | { |
205 | ump_mapped_pointer_release((ump_handle)hnd->ump_mem_handle); |
206 | ump_reference_release((ump_handle)hnd->ump_mem_handle); |
207 | } |
208 | } |
209 | else if ( hnd->flags & private_handle_t::PRIV_FLAGS_USES_ION ) |
210 | { |
211 | AERR( "Can't free dma_buf memory for handle:%p. Not supported.", hnd); |
212 | } |
213 | } |
214 | |
215 | int alloc_backend_open(alloc_device_t *dev) |
216 | { |
217 | ump_result ump_res = ump_open(); |
218 | if (UMP_OK != ump_res) |
219 | { |
220 | AERR( "UMP open failed with %d", ump_res ); |
221 | return -1; |
222 | } |
223 | |
224 | return 0; |
225 | } |
226 | |
227 | int alloc_backend_close(struct hw_device_t *device) |
228 | { |
229 | alloc_device_t* dev = reinterpret_cast<alloc_device_t*>(device); |
230 | if (dev) |
231 | { |
232 | ump_close(); // Our UMP memory refs will be released automatically here... |
233 | } |
234 | return 0; |
235 | } |
236 |