diff options
Diffstat (limited to 'arch/arm/mach-qcom/scm.c')
-rw-r--r-- | arch/arm/mach-qcom/scm.c | 31 |
1 files changed, 23 insertions, 8 deletions
diff --git a/arch/arm/mach-qcom/scm.c b/arch/arm/mach-qcom/scm.c index c536fd6bf827..820c72165e19 100644 --- a/arch/arm/mach-qcom/scm.c +++ b/arch/arm/mach-qcom/scm.c | |||
@@ -22,6 +22,7 @@ | |||
22 | #include <linux/errno.h> | 22 | #include <linux/errno.h> |
23 | #include <linux/err.h> | 23 | #include <linux/err.h> |
24 | 24 | ||
25 | #include <asm/outercache.h> | ||
25 | #include <asm/cacheflush.h> | 26 | #include <asm/cacheflush.h> |
26 | 27 | ||
27 | #include "scm.h" | 28 | #include "scm.h" |
@@ -203,6 +204,7 @@ static int __scm_call(const struct scm_command *cmd) | |||
203 | * side in the buffer. | 204 | * side in the buffer. |
204 | */ | 205 | */ |
205 | flush_cache_all(); | 206 | flush_cache_all(); |
207 | outer_flush_all(); | ||
206 | ret = smc(cmd_addr); | 208 | ret = smc(cmd_addr); |
207 | if (ret < 0) | 209 | if (ret < 0) |
208 | ret = scm_remap_error(ret); | 210 | ret = scm_remap_error(ret); |
@@ -210,6 +212,20 @@ static int __scm_call(const struct scm_command *cmd) | |||
210 | return ret; | 212 | return ret; |
211 | } | 213 | } |
212 | 214 | ||
215 | static void scm_inv_range(unsigned long start, unsigned long end) | ||
216 | { | ||
217 | start = round_down(start, CACHELINESIZE); | ||
218 | end = round_up(end, CACHELINESIZE); | ||
219 | outer_inv_range(start, end); | ||
220 | while (start < end) { | ||
221 | asm ("mcr p15, 0, %0, c7, c6, 1" : : "r" (start) | ||
222 | : "memory"); | ||
223 | start += CACHELINESIZE; | ||
224 | } | ||
225 | dsb(); | ||
226 | isb(); | ||
227 | } | ||
228 | |||
213 | /** | 229 | /** |
214 | * scm_call() - Send an SCM command | 230 | * scm_call() - Send an SCM command |
215 | * @svc_id: service identifier | 231 | * @svc_id: service identifier |
@@ -227,6 +243,7 @@ int scm_call(u32 svc_id, u32 cmd_id, const void *cmd_buf, size_t cmd_len, | |||
227 | int ret; | 243 | int ret; |
228 | struct scm_command *cmd; | 244 | struct scm_command *cmd; |
229 | struct scm_response *rsp; | 245 | struct scm_response *rsp; |
246 | unsigned long start, end; | ||
230 | 247 | ||
231 | cmd = alloc_scm_command(cmd_len, resp_len); | 248 | cmd = alloc_scm_command(cmd_len, resp_len); |
232 | if (!cmd) | 249 | if (!cmd) |
@@ -243,17 +260,15 @@ int scm_call(u32 svc_id, u32 cmd_id, const void *cmd_buf, size_t cmd_len, | |||
243 | goto out; | 260 | goto out; |
244 | 261 | ||
245 | rsp = scm_command_to_response(cmd); | 262 | rsp = scm_command_to_response(cmd); |
263 | start = (unsigned long)rsp; | ||
264 | |||
246 | do { | 265 | do { |
247 | u32 start = (u32)rsp; | 266 | scm_inv_range(start, start + sizeof(*rsp)); |
248 | u32 end = (u32)scm_get_response_buffer(rsp) + resp_len; | ||
249 | start &= ~(CACHELINESIZE - 1); | ||
250 | while (start < end) { | ||
251 | asm ("mcr p15, 0, %0, c7, c6, 1" : : "r" (start) | ||
252 | : "memory"); | ||
253 | start += CACHELINESIZE; | ||
254 | } | ||
255 | } while (!rsp->is_complete); | 267 | } while (!rsp->is_complete); |
256 | 268 | ||
269 | end = (unsigned long)scm_get_response_buffer(rsp) + resp_len; | ||
270 | scm_inv_range(start, end); | ||
271 | |||
257 | if (resp_buf) | 272 | if (resp_buf) |
258 | memcpy(resp_buf, scm_get_response_buffer(rsp), resp_len); | 273 | memcpy(resp_buf, scm_get_response_buffer(rsp), resp_len); |
259 | out: | 274 | out: |