1 // SPDX-License-Identifier: GPL-2.0-only
3 * Copyright (c) 2015-2021, Linaro Limited
4 * Copyright (c) 2016, EPAM Systems
7 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
9 #include <linux/crash_dump.h>
10 #include <linux/errno.h>
13 #include <linux/module.h>
14 #include <linux/slab.h>
15 #include <linux/string.h>
16 #include <linux/tee_drv.h>
17 #include <linux/types.h>
18 #include <linux/workqueue.h>
19 #include "optee_private.h"
21 int optee_pool_op_alloc_helper(struct tee_shm_pool_mgr *poolm,
22 struct tee_shm *shm, size_t size,
23 int (*shm_register)(struct tee_context *ctx,
29 unsigned int order = get_order(size);
33 page = alloc_pages(GFP_KERNEL | __GFP_ZERO, order);
37 shm->kaddr = page_address(page);
38 shm->paddr = page_to_phys(page);
39 shm->size = PAGE_SIZE << order;
42 unsigned int nr_pages = 1 << order, i;
45 pages = kcalloc(nr_pages, sizeof(*pages), GFP_KERNEL);
51 for (i = 0; i < nr_pages; i++)
54 shm->flags |= TEE_SHM_REGISTER;
55 rc = shm_register(shm->ctx, shm, pages, nr_pages,
56 (unsigned long)shm->kaddr);
65 __free_pages(page, order);
69 static void optee_bus_scan(struct work_struct *work)
71 WARN_ON(optee_enumerate_devices(PTA_CMD_GET_DEVICES_SUPP));
74 int optee_open(struct tee_context *ctx, bool cap_memref_null)
76 struct optee_context_data *ctxdata;
77 struct tee_device *teedev = ctx->teedev;
78 struct optee *optee = tee_get_drvdata(teedev);
80 ctxdata = kzalloc(sizeof(*ctxdata), GFP_KERNEL);
84 if (teedev == optee->supp_teedev) {
87 mutex_lock(&optee->supp.mutex);
88 if (!optee->supp.ctx) {
90 optee->supp.ctx = ctx;
92 mutex_unlock(&optee->supp.mutex);
98 if (!optee->scan_bus_done) {
99 INIT_WORK(&optee->scan_bus_work, optee_bus_scan);
100 optee->scan_bus_wq = create_workqueue("optee_bus_scan");
101 if (!optee->scan_bus_wq) {
105 queue_work(optee->scan_bus_wq, &optee->scan_bus_work);
106 optee->scan_bus_done = true;
109 mutex_init(&ctxdata->mutex);
110 INIT_LIST_HEAD(&ctxdata->sess_list);
112 ctx->cap_memref_null = cap_memref_null;
117 static void optee_release_helper(struct tee_context *ctx,
118 int (*close_session)(struct tee_context *ctx,
121 struct optee_context_data *ctxdata = ctx->data;
122 struct optee_session *sess;
123 struct optee_session *sess_tmp;
128 list_for_each_entry_safe(sess, sess_tmp, &ctxdata->sess_list,
130 list_del(&sess->list_node);
131 close_session(ctx, sess->session_id);
138 void optee_release(struct tee_context *ctx)
140 optee_release_helper(ctx, optee_close_session_helper);
143 void optee_release_supp(struct tee_context *ctx)
145 struct optee *optee = tee_get_drvdata(ctx->teedev);
147 optee_release_helper(ctx, optee_close_session_helper);
148 if (optee->scan_bus_wq) {
149 destroy_workqueue(optee->scan_bus_wq);
150 optee->scan_bus_wq = NULL;
152 optee_supp_release(&optee->supp);
155 void optee_remove_common(struct optee *optee)
157 /* Unregister OP-TEE specific client devices on TEE bus */
158 optee_unregister_devices();
160 optee_notif_uninit(optee);
162 * The two devices have to be unregistered before we can free the
165 tee_device_unregister(optee->supp_teedev);
166 tee_device_unregister(optee->teedev);
168 tee_shm_pool_free(optee->pool);
169 optee_supp_uninit(&optee->supp);
170 mutex_destroy(&optee->call_queue.mutex);
173 static int smc_abi_rc;
174 static int ffa_abi_rc;
176 static int optee_core_init(void)
179 * The kernel may have crashed at the same time that all available
180 * secure world threads were suspended and we cannot reschedule the
181 * suspended threads without access to the crashed kernel's wait_queue.
182 * Therefore, we cannot reliably initialize the OP-TEE driver in the
185 if (is_kdump_kernel())
188 smc_abi_rc = optee_smc_abi_register();
189 ffa_abi_rc = optee_ffa_abi_register();
191 /* If both failed there's no point with this module */
192 if (smc_abi_rc && ffa_abi_rc)
196 module_init(optee_core_init);
198 static void optee_core_exit(void)
201 optee_smc_abi_unregister();
203 optee_ffa_abi_unregister();
205 module_exit(optee_core_exit);
207 MODULE_AUTHOR("Linaro");
208 MODULE_DESCRIPTION("OP-TEE driver");
209 MODULE_VERSION("1.0");
210 MODULE_LICENSE("GPL v2");
211 MODULE_ALIAS("platform:optee");