in optee/ffa_abi.c [792:886]
static int optee_ffa_probe(struct ffa_device *ffa_dev)
{
const struct ffa_dev_ops *ffa_ops;
unsigned int rpc_arg_count;
struct tee_device *teedev;
struct optee *optee;
int rc;
ffa_ops = ffa_dev_ops_get(ffa_dev);
if (!ffa_ops) {
pr_warn("failed \"method\" init: ffa\n");
return -ENOENT;
}
if (!optee_ffa_api_is_compatbile(ffa_dev, ffa_ops))
return -EINVAL;
if (!optee_ffa_exchange_caps(ffa_dev, ffa_ops, &rpc_arg_count))
return -EINVAL;
optee = kzalloc(sizeof(*optee), GFP_KERNEL);
if (!optee)
return -ENOMEM;
optee->pool = optee_ffa_config_dyn_shm();
if (IS_ERR(optee->pool)) {
rc = PTR_ERR(optee->pool);
optee->pool = NULL;
goto err;
}
optee->ops = &optee_ffa_ops;
optee->ffa.ffa_dev = ffa_dev;
optee->ffa.ffa_ops = ffa_ops;
optee->rpc_arg_count = rpc_arg_count;
teedev = tee_device_alloc(&optee_ffa_clnt_desc, NULL, optee->pool,
optee);
if (IS_ERR(teedev)) {
rc = PTR_ERR(teedev);
goto err;
}
optee->teedev = teedev;
teedev = tee_device_alloc(&optee_ffa_supp_desc, NULL, optee->pool,
optee);
if (IS_ERR(teedev)) {
rc = PTR_ERR(teedev);
goto err;
}
optee->supp_teedev = teedev;
rc = tee_device_register(optee->teedev);
if (rc)
goto err;
rc = tee_device_register(optee->supp_teedev);
if (rc)
goto err;
rc = rhashtable_init(&optee->ffa.global_ids, &shm_rhash_params);
if (rc)
goto err;
mutex_init(&optee->ffa.mutex);
mutex_init(&optee->call_queue.mutex);
INIT_LIST_HEAD(&optee->call_queue.waiters);
optee_supp_init(&optee->supp);
ffa_dev_set_drvdata(ffa_dev, optee);
rc = optee_notif_init(optee, OPTEE_DEFAULT_MAX_NOTIF_VALUE);
if (rc) {
optee_ffa_remove(ffa_dev);
return rc;
}
rc = optee_enumerate_devices(PTA_CMD_GET_DEVICES);
if (rc) {
optee_ffa_remove(ffa_dev);
return rc;
}
pr_info("initialized driver\n");
return 0;
err:
/*
* tee_device_unregister() is safe to call even if the
* devices hasn't been registered with
* tee_device_register() yet.
*/
tee_device_unregister(optee->supp_teedev);
tee_device_unregister(optee->teedev);
if (optee->pool)
tee_shm_pool_free(optee->pool);
kfree(optee);
return rc;
}