b4e4dd39b6
Add suspend and resume callbacks to all secure heaps. All hyp-assigned memory which HLOS does not have access cannot be saved during hibernation, so free all such memory back to the system from secure pools. Abort hibernation if clients have not freed such memory by tracking all the allocations. Change-Id: I8a3ba617fef5ea3fdbc60a72412af90564d75052 Signed-off-by: Vivek Kumar <quic_vivekuma@quicinc.com> Signed-off-by: Shreyas K K <quic_shrekk@quicinc.com> Signed-off-by: Auditya Bhattaram <quic_audityab@quicinc.com>
149 lines
3.6 KiB
C
149 lines
3.6 KiB
C
// SPDX-License-Identifier: GPL-2.0-only
|
|
/*
|
|
* Copyright (c) 2020-2021, The Linux Foundation. All rights reserved.
|
|
*/
|
|
|
|
#include <linux/module.h>
|
|
#include <linux/of_platform.h>
|
|
#include <linux/platform_device.h>
|
|
#include <linux/err.h>
|
|
|
|
#include <linux/qcom_dma_heap.h>
|
|
#include "qcom_cma_heap.h"
|
|
#include "qcom_dt_parser.h"
|
|
#include "qcom_system_heap.h"
|
|
#include "qcom_carveout_heap.h"
|
|
#include "qcom_secure_system_heap.h"
|
|
#include "qcom_bitstream_contig_heap.h"
|
|
|
|
static int qcom_dma_heap_probe(struct platform_device *pdev)
|
|
{
|
|
int ret = 0;
|
|
int i;
|
|
struct platform_data *heaps;
|
|
|
|
qcom_system_heap_create("qcom,system", "system", false);
|
|
#ifdef CONFIG_QCOM_DMABUF_HEAPS_SYSTEM_UNCACHED
|
|
qcom_system_heap_create("qcom,system-uncached", NULL, true);
|
|
#endif
|
|
qcom_secure_system_heap_create("qcom,secure-pixel", NULL,
|
|
QCOM_DMA_HEAP_FLAG_CP_PIXEL);
|
|
qcom_secure_system_heap_create("qcom,secure-non-pixel", NULL,
|
|
QCOM_DMA_HEAP_FLAG_CP_NON_PIXEL);
|
|
|
|
heaps = parse_heap_dt(pdev);
|
|
if (IS_ERR_OR_NULL(heaps))
|
|
return PTR_ERR(heaps);
|
|
|
|
for (i = 0; i < heaps->nr; i++) {
|
|
struct platform_heap *heap_data = &heaps->heaps[i];
|
|
|
|
switch (heap_data->type) {
|
|
case HEAP_TYPE_SECURE_CARVEOUT:
|
|
ret = qcom_secure_carveout_heap_create(heap_data);
|
|
if (ret < 0)
|
|
pr_err("%s: DMA-BUF Heap: Failed to create %s, error is %d\n",
|
|
__func__, heap_data->name, ret);
|
|
else if (!ret)
|
|
pr_info("%s: DMA-BUF Heap: Created %s\n", __func__,
|
|
heap_data->name);
|
|
break;
|
|
case HEAP_TYPE_CARVEOUT:
|
|
ret = qcom_carveout_heap_create(heap_data);
|
|
if (ret < 0)
|
|
pr_err("%s: DMA-BUF Heap: Failed to create %s, error is %d\n",
|
|
__func__, heap_data->name, ret);
|
|
else if (!ret)
|
|
pr_info("%s: DMA-BUF Heap: Created %s\n", __func__,
|
|
heap_data->name);
|
|
break;
|
|
case HEAP_TYPE_CMA:
|
|
ret = qcom_add_cma_heap(heap_data);
|
|
if (ret < 0)
|
|
pr_err("%s: DMA-BUF Heap: Failed to create %s, error is %d\n",
|
|
__func__, heap_data->name, ret);
|
|
else if (!ret)
|
|
pr_info("%s: DMA-BUF Heap: Created %s\n", __func__,
|
|
heap_data->name);
|
|
break;
|
|
default:
|
|
pr_err("%s: Unknown heap type %u\n", __func__, heap_data->type);
|
|
break;
|
|
}
|
|
}
|
|
|
|
qcom_add_bitstream_contig_heap("system-secure");
|
|
|
|
free_pdata(heaps);
|
|
|
|
return ret;
|
|
}
|
|
|
|
static int qcom_dma_heaps_freeze(struct device *dev)
|
|
{
|
|
int ret;
|
|
|
|
ret = qcom_secure_carveout_freeze();
|
|
if (ret) {
|
|
pr_err("Failed to freeze secure carveout heap: %d\n", ret);
|
|
return ret;
|
|
}
|
|
|
|
ret = qcom_secure_system_freeze();
|
|
if (ret) {
|
|
pr_err("Failed to freeze secure system heap: %d\n", ret);
|
|
goto err;
|
|
}
|
|
|
|
return 0;
|
|
err:
|
|
ret = qcom_secure_carveout_restore();
|
|
if (ret) {
|
|
pr_err("Failed to restore secure carveout heap: %d\n", ret);
|
|
return ret;
|
|
}
|
|
return -EBUSY;
|
|
}
|
|
|
|
static int qcom_dma_heaps_restore(struct device *dev)
|
|
{
|
|
int ret;
|
|
|
|
ret = qcom_secure_carveout_restore();
|
|
if (ret)
|
|
pr_err("Failed to restore secure carveout heap: %d\n", ret);
|
|
|
|
ret = qcom_secure_system_restore();
|
|
if (ret)
|
|
pr_err("Failed to restore secure system heap: %d\n", ret);
|
|
|
|
return ret;
|
|
}
|
|
|
|
static const struct dev_pm_ops qcom_dma_heaps_pm_ops = {
|
|
.freeze = qcom_dma_heaps_freeze,
|
|
.restore = qcom_dma_heaps_restore,
|
|
};
|
|
|
|
static const struct of_device_id qcom_dma_heap_match_table[] = {
|
|
{.compatible = "qcom,dma-heaps"},
|
|
{},
|
|
};
|
|
|
|
static struct platform_driver qcom_dma_heap_driver = {
|
|
.probe = qcom_dma_heap_probe,
|
|
.driver = {
|
|
.name = "qcom-dma-heap",
|
|
.of_match_table = qcom_dma_heap_match_table,
|
|
.pm = &qcom_dma_heaps_pm_ops,
|
|
},
|
|
};
|
|
|
|
static int __init init_heap_driver(void)
|
|
{
|
|
return platform_driver_register(&qcom_dma_heap_driver);
|
|
}
|
|
module_init(init_heap_driver);
|
|
|
|
MODULE_LICENSE("GPL v2");
|