}
#endif
+static struct tee_protmem_pool *static_protmem_pool_init(struct optee *optee)
+{
+#if IS_ENABLED(CONFIG_OPTEE_STATIC_PROTMEM_POOL)
+ union {
+ struct arm_smccc_res smccc;
+ struct optee_smc_get_protmem_config_result result;
+ } res;
+ struct tee_protmem_pool *pool;
+ void *p;
+ int rc;
+
+ optee->smc.invoke_fn(OPTEE_SMC_GET_PROTMEM_CONFIG, 0, 0, 0, 0,
+ 0, 0, 0, &res.smccc);
+ if (res.result.status != OPTEE_SMC_RETURN_OK)
+ return ERR_PTR(-EINVAL);
+
+ rc = optee_set_dma_mask(optee, res.result.pa_width);
+ if (rc)
+ return ERR_PTR(rc);
+
+ /*
+ * Map the memory as uncached to make sure the kernel can work with
+ * __pfn_to_page() and friends since that's needed when passing the
+ * protected DMA-buf to a device. The memory should otherwise not
+ * be touched by the kernel since it's likely to cause an external
+ * abort due to the protection status.
+ */
+ p = devm_memremap(&optee->teedev->dev, res.result.start,
+ res.result.size, MEMREMAP_WC);
+ if (IS_ERR(p))
+ return p;
+
+ pool = tee_protmem_static_pool_alloc(res.result.start, res.result.size);
+ if (IS_ERR(pool))
+ devm_memunmap(&optee->teedev->dev, p);
+
+ return pool;
+#else
+ return ERR_PTR(-EINVAL);
+#endif
+}
+
+static int optee_protmem_pool_init(struct optee *optee)
+{
+ enum tee_dma_heap_id heap_id = TEE_DMA_HEAP_SECURE_VIDEO_PLAY;
+ struct tee_protmem_pool *pool = ERR_PTR(-EINVAL);
+ int rc;
+
+ if (!(optee->smc.sec_caps & OPTEE_SMC_SEC_CAP_PROTMEM))
+ return 0;
+
+ pool = static_protmem_pool_init(optee);
+ if (IS_ERR(pool))
+ return PTR_ERR(pool);
+
+ rc = tee_device_register_dma_heap(optee->teedev, heap_id, pool);
+ if (rc)
+ pool->ops->destroy_pool(pool);
+
+ return rc;
+}
+
static int optee_probe(struct platform_device *pdev)
{
optee_invoke_fn *invoke_fn;
optee = kzalloc(sizeof(*optee), GFP_KERNEL);
if (!optee) {
rc = -ENOMEM;
- goto err_free_pool;
+ goto err_free_shm_pool;
}
optee->ops = &optee_ops;
pr_info("Asynchronous notifications enabled\n");
}
+ if (optee_protmem_pool_init(optee))
+ pr_info("Protected memory service not available\n");
+
/*
* Ensure that there are no pre-existing shm objects before enabling
* the shm cache so that there's no chance of receiving an invalid
tee_device_unregister(optee->teedev);
err_free_optee:
kfree(optee);
-err_free_pool:
+err_free_shm_pool:
tee_shm_pool_free(pool);
if (memremaped_shm)
memunmap(memremaped_shm);