2 * Copyright (c) 2012-2014 NVIDIA Corporation. All rights reserved.
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
9 * This program is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
14 * You should have received a copy of the GNU General Public License along
15 * with this program; if not, write to the Free Software Foundation, Inc.,
16 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
19 #include <linux/atomic.h>
20 #include <linux/uaccess.h>
21 #include <linux/module.h>
22 #include <linux/slab.h>
24 #include <linux/printk.h>
25 #include <linux/ioctl.h>
26 #include <linux/sched.h>
28 #include <linux/pagemap.h>
29 #include <asm/smp_plat.h>
31 #include "ote_protocol.h"
34 core_param(verbose_smc, verbose_smc, bool, 0644);
36 #define SET_RESULT(req, r, ro) { req->result = r; req->result_origin = ro; }
38 static int te_pin_user_pages(void *buffer, size_t size,
39 unsigned long *pages_ptr, uint32_t buf_type)
42 unsigned int nr_pages;
43 struct page **pages = NULL;
46 nr_pages = (((uintptr_t)buffer & (PAGE_SIZE - 1)) +
47 (size + PAGE_SIZE - 1)) >> PAGE_SHIFT;
49 pages = kzalloc(nr_pages * sizeof(struct page *), GFP_KERNEL);
53 writable = (buf_type == TE_PARAM_TYPE_MEM_RW ||
54 buf_type == TE_PARAM_TYPE_PERSIST_MEM_RW);
56 down_read(¤t->mm->mmap_sem);
57 ret = get_user_pages(current, current->mm, (unsigned long)buffer,
61 up_read(¤t->mm->mmap_sem);
63 *pages_ptr = (unsigned long) pages;
68 static int te_prep_mem_buffer(uint32_t session_id,
69 void *buffer, size_t size, uint32_t buf_type,
70 struct tlk_context *context)
72 unsigned long pages = 0;
73 struct te_shmem_desc *shmem_desc = NULL;
74 int ret = 0, nr_pages = 0;
76 /* allocate new shmem descriptor */
77 shmem_desc = kzalloc(sizeof(struct te_shmem_desc), GFP_KERNEL);
79 pr_err("%s: te_add_shmem_desc failed\n", __func__);
80 ret = OTE_ERROR_OUT_OF_MEMORY;
85 nr_pages = te_pin_user_pages(buffer, size, &pages, buf_type);
87 pr_err("%s: te_pin_user_pages failed (%d)\n", __func__,
89 ret = OTE_ERROR_OUT_OF_MEMORY;
94 /* initialize shmem descriptor */
95 INIT_LIST_HEAD(&(shmem_desc->list));
96 shmem_desc->active = false;
97 shmem_desc->buffer = buffer;
98 shmem_desc->size = size;
99 shmem_desc->nr_pages = nr_pages;
100 shmem_desc->pages = (struct page **)(uintptr_t)pages;
102 /* add shmem descriptor to proper list */
103 if ((buf_type == TE_PARAM_TYPE_MEM_RO) ||
104 (buf_type == TE_PARAM_TYPE_MEM_RW))
105 list_add_tail(&shmem_desc->list, &context->temp_shmem_list);
107 list_add_tail(&shmem_desc->list, &context->persist_shmem_list);
115 static int te_prep_mem_buffers(struct te_request *request,
116 struct tlk_context *context)
119 int ret = OTE_SUCCESS;
120 struct te_oper_param *params = request->params;
122 for (i = 0; i < request->params_size; i++) {
123 switch (params[i].type) {
124 case TE_PARAM_TYPE_NONE:
125 case TE_PARAM_TYPE_INT_RO:
126 case TE_PARAM_TYPE_INT_RW:
128 case TE_PARAM_TYPE_MEM_RO:
129 case TE_PARAM_TYPE_MEM_RW:
130 case TE_PARAM_TYPE_PERSIST_MEM_RO:
131 case TE_PARAM_TYPE_PERSIST_MEM_RW:
132 ret = te_prep_mem_buffer(request->session_id,
133 params[i].u.Mem.base,
138 pr_err("%s failed with err (%d)\n",
140 ret = OTE_ERROR_BAD_PARAMETERS;
145 pr_err("%s: OTE_ERROR_BAD_PARAMETERS\n", __func__);
146 ret = OTE_ERROR_BAD_PARAMETERS;
153 static int te_prep_mem_buffers_compat(struct te_request_compat *request,
154 struct tlk_context *context)
157 int ret = OTE_SUCCESS;
158 struct te_oper_param_compat *params;
160 params = (struct te_oper_param_compat *)(uintptr_t)request->params;
161 for (i = 0; i < request->params_size; i++) {
162 switch (params[i].type) {
163 case TE_PARAM_TYPE_NONE:
164 case TE_PARAM_TYPE_INT_RO:
165 case TE_PARAM_TYPE_INT_RW:
167 case TE_PARAM_TYPE_MEM_RO:
168 case TE_PARAM_TYPE_MEM_RW:
169 case TE_PARAM_TYPE_PERSIST_MEM_RO:
170 case TE_PARAM_TYPE_PERSIST_MEM_RW:
171 ret = te_prep_mem_buffer(request->session_id,
172 (void *)(uintptr_t)params[i].u.Mem.base,
177 pr_err("%s failed with err (%d)\n",
179 ret = OTE_ERROR_BAD_PARAMETERS;
184 pr_err("%s: OTE_ERROR_BAD_PARAMETERS\n", __func__);
185 ret = OTE_ERROR_BAD_PARAMETERS;
192 static void te_release_mem_buffer(struct te_shmem_desc *shmem_desc)
196 list_del(&shmem_desc->list);
197 for (i = 0; i < shmem_desc->nr_pages; i++) {
198 if ((shmem_desc->type == TE_PARAM_TYPE_MEM_RW) ||
199 (shmem_desc->type == TE_PARAM_TYPE_PERSIST_MEM_RW))
200 set_page_dirty_lock(shmem_desc->pages[i]);
201 page_cache_release(shmem_desc->pages[i]);
203 kfree(shmem_desc->pages);
207 static void te_release_temp_mem_buffers(struct tlk_context *context)
209 struct te_shmem_desc *shmem_desc, *tmp_shmem_desc;
211 if (list_empty(&context->temp_shmem_list))
214 list_for_each_entry_safe(shmem_desc, tmp_shmem_desc,
215 &context->temp_shmem_list, list) {
216 te_release_mem_buffer(shmem_desc);
220 static void te_release_persist_mem_buffers(uint32_t session_id,
221 struct tlk_context *context)
223 struct te_shmem_desc *shmem_desc, *tmp_shmem_desc;
225 if (list_empty(&context->persist_shmem_list))
229 * Release any persistent mem buffers that either belong to
230 * the specified session_id or are not currently marked active
231 * (i.e. because the associated open_session or launch_operation
234 list_for_each_entry_safe(shmem_desc, tmp_shmem_desc,
235 &context->persist_shmem_list, list) {
236 if ((shmem_desc->session_id == session_id) ||
237 (!shmem_desc->active))
238 te_release_mem_buffer(shmem_desc);
242 static void te_update_persist_mem_buffers(uint32_t session_id,
243 struct tlk_context *context)
245 struct te_shmem_desc *shmem_desc, *tmp_shmem_desc;
248 * Assumes any entries that have yet to be marked active belong
249 * to the session associated with the session_id that has been
252 list_for_each_entry_safe(shmem_desc, tmp_shmem_desc,
253 &context->persist_shmem_list, list) {
255 if (!shmem_desc->active) {
256 shmem_desc->session_id = session_id;
257 shmem_desc->active = true;
263 cpumask_t saved_cpu_mask;
264 static void switch_cpumask_to_cpu0(void)
267 cpumask_t local_cpu_mask = CPU_MASK_NONE;
269 cpu_set(0, local_cpu_mask);
270 cpumask_copy(&saved_cpu_mask, tsk_cpus_allowed(current));
271 ret = sched_setaffinity(0, &local_cpu_mask);
273 pr_err("%s: sched_setaffinity #1 -> 0x%lX", __func__, ret);
276 static void restore_cpumask(void)
278 long ret = sched_setaffinity(0, &saved_cpu_mask);
280 pr_err("%s: sched_setaffinity #2 -> 0x%lX", __func__, ret);
283 static inline void switch_cpumask_to_cpu0(void) {};
284 static inline void restore_cpumask(void) {};
287 uint32_t tlk_generic_smc(uint32_t arg0, uintptr_t arg1, uintptr_t arg2)
291 switch_cpumask_to_cpu0();
293 retval = _tlk_generic_smc(arg0, arg1, arg2);
294 while (retval == TE_ERROR_PREEMPT_BY_IRQ ||
295 retval == TE_ERROR_PREEMPT_BY_FS) {
296 if (retval == TE_ERROR_PREEMPT_BY_FS)
298 retval = _tlk_generic_smc(TE_SMC_RESTART, 0, 0);
306 uint32_t tlk_extended_smc(uintptr_t *regs)
310 switch_cpumask_to_cpu0();
312 retval = _tlk_extended_smc(regs);
313 while (retval == TE_ERROR_PREEMPT_BY_IRQ)
314 retval = _tlk_generic_smc(TE_SMC_RESTART, 0, 0);
324 static void do_smc(struct te_request *request, struct tlk_device *dev)
327 uint32_t smc_params = 0;
329 if (dev->req_param_buf) {
330 smc_args = (char *)request - dev->req_param_buf;
332 smc_params = (char *)request->params -
335 smc_args = (uint32_t)virt_to_phys(request);
337 smc_params = (uint32_t)virt_to_phys(request->params);
340 tlk_generic_smc(request->type, smc_args, smc_params);
343 * Check to see if there are any logs in written by TLK.
344 * If there are, print them out.
349 struct tlk_smc_work_args {
355 static long tlk_generic_smc_on_cpu0(void *args)
357 struct tlk_smc_work_args *work;
358 int cpu = cpu_logical_map(smp_processor_id());
363 work = (struct tlk_smc_work_args *)args;
364 retval = _tlk_generic_smc(work->arg0, work->arg1, work->arg2);
365 while (retval == TE_ERROR_PREEMPT_BY_IRQ)
366 retval = _tlk_generic_smc(TE_SMC_RESTART, 0, 0);
373 static void do_smc_compat(struct te_request_compat *request,
374 struct tlk_device *dev)
377 uint32_t smc_params = 0;
379 smc_args = (char *)request - dev->req_param_buf;
380 if (request->params) {
382 (char *)(uintptr_t)request->params - dev->req_param_buf;
385 tlk_generic_smc(request->type, smc_args, smc_params);
388 * Check to see if there are any logs in written by TLK.
389 * If there are, print them out.
395 * VPR programming SMC
397 * This routine is called both from normal threads and worker threads.
398 * The worker threads are per-cpu and have PF_NO_SETAFFINITY set, so
399 * any calls to sched_setaffinity will fail.
401 * If it's a worker thread on CPU0, just invoke the SMC directly. If
402 * it's running on a non-CPU0, use work_on_cpu() to schedule the SMC
405 int te_set_vpr_params(void *vpr_base, size_t vpr_size)
409 /* Share the same lock used when request is send from user side */
410 mutex_lock(&smc_lock);
413 (PF_WQ_WORKER | PF_NO_SETAFFINITY | PF_KTHREAD)) {
414 struct tlk_smc_work_args work_args;
415 int cpu = cpu_logical_map(smp_processor_id());
417 work_args.arg0 = TE_SMC_PROGRAM_VPR;
418 work_args.arg1 = (uintptr_t)vpr_base;
419 work_args.arg2 = vpr_size;
421 /* workers don't change CPU. depending on the CPU, execute
422 * directly or sched work */
423 if (cpu == 0 && (current->flags & PF_WQ_WORKER))
424 retval = tlk_generic_smc_on_cpu0(&work_args);
426 retval = work_on_cpu(0,
427 tlk_generic_smc_on_cpu0, &work_args);
429 retval = tlk_generic_smc(TE_SMC_PROGRAM_VPR,
430 (uintptr_t)vpr_base, vpr_size);
433 mutex_unlock(&smc_lock);
435 if (retval != OTE_SUCCESS) {
436 pr_err("%s: smc failed err (0x%x)\n", __func__, retval);
441 EXPORT_SYMBOL(te_set_vpr_params);
445 * Open session SMC (supporting client-based te_open_session() calls)
447 void te_open_session(struct te_opensession *cmd,
448 struct te_request *request,
449 struct tlk_context *context)
453 request->type = TE_SMC_OPEN_SESSION;
455 ret = te_prep_mem_buffers(request, context);
456 if (ret != OTE_SUCCESS) {
457 pr_err("%s: te_prep_mem_buffers failed err (0x%x)\n",
459 SET_RESULT(request, ret, OTE_RESULT_ORIGIN_API);
463 memcpy(&request->dest_uuid,
465 sizeof(struct te_service_id));
467 pr_info("OPEN_CLIENT_SESSION: 0x%x 0x%x 0x%x 0x%x\n",
468 request->dest_uuid[0],
469 request->dest_uuid[1],
470 request->dest_uuid[2],
471 request->dest_uuid[3]);
473 do_smc(request, context->dev);
475 if (request->result) {
476 /* release any persistent mem buffers if we failed */
477 te_release_persist_mem_buffers(request->session_id, context);
479 /* mark active any persistent mem buffers */
480 te_update_persist_mem_buffers(request->session_id, context);
483 te_release_temp_mem_buffers(context);
487 * Close session SMC (supporting client-based te_close_session() calls)
489 void te_close_session(struct te_closesession *cmd,
490 struct te_request *request,
491 struct tlk_context *context)
493 request->session_id = cmd->session_id;
494 request->type = TE_SMC_CLOSE_SESSION;
496 do_smc(request, context->dev);
498 pr_info("%s: error closing session: %08x\n",
499 __func__, request->result);
501 /* release any peristent mem buffers */
502 te_release_persist_mem_buffers(request->session_id, context);
506 * Launch operation SMC (supporting client-based te_launch_operation() calls)
508 void te_launch_operation(struct te_launchop *cmd,
509 struct te_request *request,
510 struct tlk_context *context)
514 request->session_id = cmd->session_id;
515 request->command_id = cmd->operation.command;
516 request->type = TE_SMC_LAUNCH_OPERATION;
518 ret = te_prep_mem_buffers(request, context);
519 if (ret != OTE_SUCCESS) {
520 pr_err("%s: te_prep_mem_buffers failed err (0x%x)\n",
522 SET_RESULT(request, ret, OTE_RESULT_ORIGIN_API);
526 do_smc(request, context->dev);
528 if (request->result) {
529 /* release any persistent mem buffers if we failed */
530 te_release_persist_mem_buffers(request->session_id, context);
532 /* mark active any persistent mem buffers */
533 te_update_persist_mem_buffers(request->session_id, context);
536 te_release_temp_mem_buffers(context);
540 * Open session SMC (supporting client-based te_open_session() calls)
542 void te_open_session_compat(struct te_opensession_compat *cmd,
543 struct te_request_compat *request,
544 struct tlk_context *context)
548 request->type = TE_SMC_OPEN_SESSION;
550 ret = te_prep_mem_buffers_compat(request, context);
551 if (ret != OTE_SUCCESS) {
552 pr_err("%s: te_prep_mem_buffers failed err (0x%x)\n",
554 SET_RESULT(request, ret, OTE_RESULT_ORIGIN_API);
558 memcpy(&request->dest_uuid,
560 sizeof(struct te_service_id));
562 pr_info("OPEN_CLIENT_SESSION_COMPAT: 0x%x 0x%x 0x%x 0x%x\n",
563 request->dest_uuid[0],
564 request->dest_uuid[1],
565 request->dest_uuid[2],
566 request->dest_uuid[3]);
568 do_smc_compat(request, context->dev);
570 if (request->result) {
571 /* release any persistent mem buffers if we failed */
572 te_release_persist_mem_buffers(request->session_id, context);
574 /* mark active any persistent mem buffers */
575 te_update_persist_mem_buffers(request->session_id, context);
578 te_release_temp_mem_buffers(context);
582 * Close session SMC (supporting client-based te_close_session() calls)
584 void te_close_session_compat(struct te_closesession_compat *cmd,
585 struct te_request_compat *request,
586 struct tlk_context *context)
588 request->session_id = cmd->session_id;
589 request->type = TE_SMC_CLOSE_SESSION;
591 do_smc_compat(request, context->dev);
593 pr_info("%s: error closing session: %08x\n",
594 __func__, request->result);
596 /* release any peristent mem buffers */
597 te_release_persist_mem_buffers(request->session_id, context);
601 * Launch operation SMC (supporting client-based te_launch_operation() calls)
603 void te_launch_operation_compat(struct te_launchop_compat *cmd,
604 struct te_request_compat *request,
605 struct tlk_context *context)
609 request->session_id = cmd->session_id;
610 request->command_id = cmd->operation.command;
611 request->type = TE_SMC_LAUNCH_OPERATION;
613 ret = te_prep_mem_buffers_compat(request, context);
614 if (ret != OTE_SUCCESS) {
615 pr_err("%s: te_prep_mem_buffers failed err (0x%x)\n",
617 SET_RESULT(request, ret, OTE_RESULT_ORIGIN_API);
621 do_smc_compat(request, context->dev);
623 if (request->result) {
624 /* release any persistent mem buffers if we failed */
625 te_release_persist_mem_buffers(request->session_id, context);
627 /* mark active any persistent mem buffers */
628 te_update_persist_mem_buffers(request->session_id, context);
631 te_release_temp_mem_buffers(context);