summaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/tegra/vic.c
diff options
context:
space:
mode:
authorMikko Perttunen <mperttunen@nvidia.com>2022-06-27 17:19:54 +0300
committerThierry Reding <treding@nvidia.com>2022-07-08 16:27:52 +0200
commitbf0297ac77f3c3187a79a612082ce7ddb64c1e4b (patch)
treea956991a61dea2dab00d0899187e97837b4c120c /drivers/gpu/drm/tegra/vic.c
parente09db97889ec647ad373f7a7422c83099c6120c5 (diff)
downloadlinux-bf0297ac77f3c3187a79a612082ce7ddb64c1e4b.tar.bz2
drm/tegra: Implement stream ID related callbacks on engines
Implement the get_streamid_offset and can_use_memory_ctx callbacks required for supporting context isolation. Since old firmware on VIC cannot support context isolation without hacks that we don't want to implement, check the firmware binary to see if context isolation should be enabled. Signed-off-by: Mikko Perttunen <mperttunen@nvidia.com> Signed-off-by: Thierry Reding <treding@nvidia.com>
Diffstat (limited to 'drivers/gpu/drm/tegra/vic.c')
-rw-r--r--drivers/gpu/drm/tegra/vic.c67
1 files changed, 59 insertions, 8 deletions
diff --git a/drivers/gpu/drm/tegra/vic.c b/drivers/gpu/drm/tegra/vic.c
index f56f5921a8c2..c5526bda88d6 100644
--- a/drivers/gpu/drm/tegra/vic.c
+++ b/drivers/gpu/drm/tegra/vic.c
@@ -38,6 +38,8 @@ struct vic {
struct clk *clk;
struct reset_control *rst;
+ bool can_use_context;
+
/* Platform configuration */
const struct vic_config *config;
};
@@ -229,28 +231,38 @@ static int vic_load_firmware(struct vic *vic)
{
struct host1x_client *client = &vic->client.base;
struct tegra_drm *tegra = vic->client.drm;
+ static DEFINE_MUTEX(lock);
+ u32 fce_bin_data_offset;
dma_addr_t iova;
size_t size;
void *virt;
int err;
- if (vic->falcon.firmware.virt)
- return 0;
+ mutex_lock(&lock);
+
+ if (vic->falcon.firmware.virt) {
+ err = 0;
+ goto unlock;
+ }
err = falcon_read_firmware(&vic->falcon, vic->config->firmware);
if (err < 0)
- return err;
+ goto unlock;
size = vic->falcon.firmware.size;
if (!client->group) {
virt = dma_alloc_coherent(vic->dev, size, &iova, GFP_KERNEL);
- if (!virt)
- return -ENOMEM;
+ if (!virt) {
+ err = -ENOMEM;
+ goto unlock;
+ }
} else {
virt = tegra_drm_alloc(tegra, size, &iova);
- if (IS_ERR(virt))
- return PTR_ERR(virt);
+ if (IS_ERR(virt)) {
+ err = PTR_ERR(virt);
+ goto unlock;
+ }
}
vic->falcon.firmware.virt = virt;
@@ -277,7 +289,28 @@ static int vic_load_firmware(struct vic *vic)
vic->falcon.firmware.phys = phys;
}
- return 0;
+ /*
+ * Check if firmware is new enough to not require mapping firmware
+ * to data buffer domains.
+ */
+ fce_bin_data_offset = *(u32 *)(virt + VIC_UCODE_FCE_DATA_OFFSET);
+
+ if (!vic->config->supports_sid) {
+ vic->can_use_context = false;
+ } else if (fce_bin_data_offset != 0x0 && fce_bin_data_offset != 0xa5a5a5a5) {
+ /*
+ * Firmware will access FCE through STREAMID0, so context
+ * isolation cannot be used.
+ */
+ vic->can_use_context = false;
+ dev_warn_once(vic->dev, "context isolation disabled due to old firmware\n");
+ } else {
+ vic->can_use_context = true;
+ }
+
+unlock:
+ mutex_unlock(&lock);
+ return err;
cleanup:
if (!client->group)
@@ -285,6 +318,7 @@ cleanup:
else
tegra_drm_free(tegra, size, virt, iova);
+ mutex_unlock(&lock);
return err;
}
@@ -358,10 +392,27 @@ static void vic_close_channel(struct tegra_drm_context *context)
host1x_channel_put(context->channel);
}
+static int vic_can_use_memory_ctx(struct tegra_drm_client *client, bool *supported)
+{
+ struct vic *vic = to_vic(client);
+ int err;
+
+ /* This doesn't access HW so it's safe to call without powering up. */
+ err = vic_load_firmware(vic);
+ if (err < 0)
+ return err;
+
+ *supported = vic->can_use_context;
+
+ return 0;
+}
+
static const struct tegra_drm_client_ops vic_ops = {
.open_channel = vic_open_channel,
.close_channel = vic_close_channel,
.submit = tegra_drm_submit,
+ .get_streamid_offset = tegra_drm_get_streamid_offset_thi,
+ .can_use_memory_ctx = vic_can_use_memory_ctx,
};
#define NVIDIA_TEGRA_124_VIC_FIRMWARE "nvidia/tegra124/vic03_ucode.bin"