Skip to content

Commit c8872d0

Browse files
authored
Merge pull request #275 from gouravk-qualcomm/iris-driver-kvm
FROMLIST: media: iris: Enable Secure PAS support with IOMMU managed b…
2 parents ce41f35 + 257523d commit c8872d0

4 files changed

Lines changed: 134 additions & 11 deletions

File tree

drivers/media/platform/qcom/iris/iris_core.c

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ void iris_core_deinit(struct iris_core *core)
1818
if (core->state != IRIS_CORE_DEINIT) {
1919
iris_fw_unload(core);
2020
iris_vpu_power_off(core);
21+
iris_fw_deinit(core);
2122
iris_hfi_queues_deinit(core);
2223
core->state = IRIS_CORE_DEINIT;
2324
}
@@ -67,10 +68,14 @@ int iris_core_init(struct iris_core *core)
6768
if (ret)
6869
goto error_queue_deinit;
6970

70-
ret = iris_fw_load(core);
71+
ret = iris_fw_init(core);
7172
if (ret)
7273
goto error_power_off;
7374

75+
ret = iris_fw_load(core);
76+
if (ret)
77+
goto error_firmware_deinit;
78+
7479
ret = iris_vpu_boot_firmware(core);
7580
if (ret)
7681
goto error_unload_fw;
@@ -85,6 +90,8 @@ int iris_core_init(struct iris_core *core)
8590

8691
error_unload_fw:
8792
iris_fw_unload(core);
93+
error_firmware_deinit:
94+
iris_fw_deinit(core);
8895
error_power_off:
8996
iris_vpu_power_off(core);
9097
error_queue_deinit:

drivers/media/platform/qcom/iris/iris_core.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,11 @@ struct iris_core {
8282
struct v4l2_device v4l2_dev;
8383
struct video_device *vdev_dec;
8484
struct video_device *vdev_enc;
85+
struct video_firmware {
86+
struct device *dev;
87+
struct qcom_scm_pas_context *ctx;
88+
struct iommu_domain *iommu_domain;
89+
} fw;
8590
const struct v4l2_file_operations *iris_v4l2_file_ops;
8691
const struct v4l2_ioctl_ops *iris_v4l2_ioctl_ops_dec;
8792
const struct v4l2_ioctl_ops *iris_v4l2_ioctl_ops_enc;

drivers/media/platform/qcom/iris/iris_firmware.c

Lines changed: 119 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,15 @@
33
* Copyright (c) 2022-2024 Qualcomm Innovation Center, Inc. All rights reserved.
44
*/
55

6+
#include <linux/device.h>
67
#include <linux/firmware.h>
78
#include <linux/firmware/qcom/qcom_scm.h>
9+
#include <linux/iommu.h>
10+
#include <linux/of.h>
811
#include <linux/of_address.h>
12+
#include <linux/of_device.h>
913
#include <linux/of_reserved_mem.h>
14+
#include <linux/platform_device.h>
1015
#include <linux/soc/qcom/mdt_loader.h>
1116

1217
#include "iris_core.h"
@@ -17,6 +22,7 @@
1722
static int iris_load_fw_to_memory(struct iris_core *core, const char *fw_name)
1823
{
1924
u32 pas_id = core->iris_platform_data->pas_id;
25+
struct qcom_scm_pas_context *ctx;
2026
const struct firmware *firmware = NULL;
2127
struct device *dev = core->dev;
2228
struct reserved_mem *rmem;
@@ -42,6 +48,14 @@ static int iris_load_fw_to_memory(struct iris_core *core, const char *fw_name)
4248
mem_phys = rmem->base;
4349
res_size = rmem->size;
4450

51+
dev = core->fw.dev ? : core->dev;
52+
53+
ctx = devm_qcom_scm_pas_context_alloc(dev, pas_id, mem_phys, res_size);
54+
if (!ctx)
55+
return -ENOMEM;
56+
57+
ctx->use_tzmem = core->fw.dev;
58+
4559
ret = request_firmware(&firmware, fw_name, dev);
4660
if (ret)
4761
return ret;
@@ -58,9 +72,29 @@ static int iris_load_fw_to_memory(struct iris_core *core, const char *fw_name)
5872
goto err_release_fw;
5973
}
6074

61-
ret = qcom_mdt_load(dev, firmware, fw_name,
62-
pas_id, mem_virt, mem_phys, res_size, NULL);
75+
ret = qcom_mdt_pas_load(ctx, firmware, fw_name, mem_virt, NULL);
76+
qcom_scm_pas_metadata_release(ctx);
77+
if (ret)
78+
goto err_mem_unmap;
79+
80+
if (core->fw.iommu_domain) {
81+
ret = iommu_map(core->fw.iommu_domain, 0, mem_phys, res_size,
82+
IOMMU_READ | IOMMU_WRITE | IOMMU_PRIV, GFP_KERNEL);
83+
if (ret)
84+
goto err_mem_unmap;
85+
}
6386

87+
ret = qcom_scm_pas_prepare_and_auth_reset(ctx);
88+
if (ret)
89+
goto err_iommu_unmap;
90+
91+
core->fw.ctx = ctx;
92+
93+
return ret;
94+
95+
err_iommu_unmap:
96+
iommu_unmap(core->fw.iommu_domain, 0, res_size);
97+
err_mem_unmap:
6498
memunmap(mem_virt);
6599
err_release_fw:
66100
release_firmware(firmware);
@@ -85,19 +119,13 @@ int iris_fw_load(struct iris_core *core)
85119
return -ENOMEM;
86120
}
87121

88-
ret = qcom_scm_pas_auth_and_reset(core->iris_platform_data->pas_id);
89-
if (ret) {
90-
dev_err(core->dev, "auth and reset failed: %d\n", ret);
91-
return ret;
92-
}
93-
94122
ret = qcom_scm_mem_protect_video_var(cp_config->cp_start,
95123
cp_config->cp_size,
96124
cp_config->cp_nonpixel_start,
97125
cp_config->cp_nonpixel_size);
98126
if (ret) {
99127
dev_err(core->dev, "protect memory failed\n");
100-
qcom_scm_pas_shutdown(core->iris_platform_data->pas_id);
128+
iris_fw_unload(core);
101129
return ret;
102130
}
103131

@@ -106,10 +134,91 @@ int iris_fw_load(struct iris_core *core)
106134

107135
int iris_fw_unload(struct iris_core *core)
108136
{
109-
return qcom_scm_pas_shutdown(core->iris_platform_data->pas_id);
137+
struct qcom_scm_pas_context *ctx = core->fw.ctx;
138+
int ret;
139+
140+
if (!ctx)
141+
return -EINVAL;
142+
143+
ret = qcom_scm_pas_shutdown(ctx->pas_id);
144+
if (core->fw.iommu_domain)
145+
iommu_unmap(core->fw.iommu_domain, 0, ctx->mem_size);
146+
147+
core->fw.ctx = NULL;
148+
return ret;
110149
}
111150

112151
int iris_set_hw_state(struct iris_core *core, bool resume)
113152
{
114153
return qcom_scm_set_remote_state(resume, 0);
115154
}
155+
156+
int iris_fw_init(struct iris_core *core)
157+
{
158+
struct platform_device_info info;
159+
struct iommu_domain *iommu_dom;
160+
struct platform_device *pdev;
161+
struct device_node *np;
162+
int ret;
163+
164+
np = of_get_child_by_name(core->dev->of_node, "video-firmware");
165+
if (!np)
166+
return 0;
167+
168+
memset(&info, 0, sizeof(info));
169+
info.fwnode = &np->fwnode;
170+
info.parent = core->dev;
171+
info.name = np->name;
172+
info.dma_mask = DMA_BIT_MASK(32);
173+
174+
pdev = platform_device_register_full(&info);
175+
if (IS_ERR(pdev)) {
176+
of_node_put(np);
177+
return PTR_ERR(pdev);
178+
}
179+
180+
pdev->dev.of_node = np;
181+
182+
ret = of_dma_configure(&pdev->dev, np, true);
183+
if (ret)
184+
goto err_unregister;
185+
186+
core->fw.dev = &pdev->dev;
187+
188+
iommu_dom = iommu_get_domain_for_dev(core->fw.dev);
189+
if (!iommu_dom) {
190+
ret = -EINVAL;
191+
goto err_unset_fw_dev;
192+
}
193+
194+
ret = iommu_attach_device(iommu_dom, core->fw.dev);
195+
if (ret)
196+
goto err_unset_fw_dev;
197+
198+
core->fw.iommu_domain = iommu_dom;
199+
200+
of_node_put(np);
201+
202+
return 0;
203+
204+
err_unset_fw_dev:
205+
core->fw.dev = NULL;
206+
err_unregister:
207+
platform_device_unregister(pdev);
208+
of_node_put(np);
209+
return ret;
210+
}
211+
212+
void iris_fw_deinit(struct iris_core *core)
213+
{
214+
if (!core->fw.dev)
215+
return;
216+
217+
if (core->fw.iommu_domain) {
218+
iommu_detach_device(core->fw.iommu_domain, core->fw.dev);
219+
core->fw.iommu_domain = NULL;
220+
}
221+
222+
platform_device_unregister(to_platform_device(core->fw.dev));
223+
core->fw.dev = NULL;
224+
}

drivers/media/platform/qcom/iris/iris_firmware.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,5 +11,7 @@ struct iris_core;
1111
int iris_fw_load(struct iris_core *core);
1212
int iris_fw_unload(struct iris_core *core);
1313
int iris_set_hw_state(struct iris_core *core, bool resume);
14+
int iris_fw_init(struct iris_core *core);
15+
void iris_fw_deinit(struct iris_core *core);
1416

1517
#endif

0 commit comments

Comments
 (0)