Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

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>

authored by

Mikko Perttunen and committed by
Thierry Reding
bf0297ac e09db978

+76 -8
+8
drivers/gpu/drm/tegra/drm.h
··· 100 100 struct drm_tegra_submit *args, struct drm_device *drm, 101 101 struct drm_file *file); 102 102 103 + static inline int 104 + tegra_drm_get_streamid_offset_thi(struct tegra_drm_client *client, u32 *offset) 105 + { 106 + *offset = 0x30; 107 + 108 + return 0; 109 + } 110 + 103 111 struct tegra_drm_client { 104 112 struct host1x_client base; 105 113 struct list_head list;
+9
drivers/gpu/drm/tegra/nvdec.c
··· 306 306 host1x_channel_put(context->channel); 307 307 } 308 308 309 + static int nvdec_can_use_memory_ctx(struct tegra_drm_client *client, bool *supported) 310 + { 311 + *supported = true; 312 + 313 + return 0; 314 + } 315 + 309 316 static const struct tegra_drm_client_ops nvdec_ops = { 310 317 .open_channel = nvdec_open_channel, 311 318 .close_channel = nvdec_close_channel, 312 319 .submit = tegra_drm_submit, 320 + .get_streamid_offset = tegra_drm_get_streamid_offset_thi, 321 + .can_use_memory_ctx = nvdec_can_use_memory_ctx, 313 322 }; 314 323 315 324 #define NVIDIA_TEGRA_210_NVDEC_FIRMWARE "nvidia/tegra210/nvdec.bin"
+59 -8
drivers/gpu/drm/tegra/vic.c
··· 38 38 struct clk *clk; 39 39 struct reset_control *rst; 40 40 41 + bool can_use_context; 42 + 41 43 /* Platform configuration */ 42 44 const struct vic_config *config; 43 45 }; ··· 231 229 { 232 230 struct host1x_client *client = &vic->client.base; 233 231 struct tegra_drm *tegra = vic->client.drm; 232 + static DEFINE_MUTEX(lock); 233 + u32 fce_bin_data_offset; 234 234 dma_addr_t iova; 235 235 size_t size; 236 236 void *virt; 237 237 int err; 238 238 239 - if (vic->falcon.firmware.virt) 240 - return 0; 239 + mutex_lock(&lock); 240 + 241 + if (vic->falcon.firmware.virt) { 242 + err = 0; 243 + goto unlock; 244 + } 241 245 242 246 err = falcon_read_firmware(&vic->falcon, vic->config->firmware); 243 247 if (err < 0) 244 - return err; 248 + goto unlock; 245 249 246 250 size = vic->falcon.firmware.size; 247 251 248 252 if (!client->group) { 249 253 virt = dma_alloc_coherent(vic->dev, size, &iova, GFP_KERNEL); 250 - if (!virt) 251 - return -ENOMEM; 254 + if (!virt) { 255 + err = -ENOMEM; 256 + goto unlock; 257 + } 252 258 } else { 253 259 virt = tegra_drm_alloc(tegra, size, &iova); 254 - if (IS_ERR(virt)) 255 - return PTR_ERR(virt); 260 + if (IS_ERR(virt)) { 261 + err = PTR_ERR(virt); 262 + goto unlock; 263 + } 256 264 } 257 265 258 266 vic->falcon.firmware.virt = virt; ··· 289 277 vic->falcon.firmware.phys = phys; 290 278 } 291 279 292 - return 0; 280 + /* 281 + * Check if firmware is new enough to not require mapping firmware 282 + * to data buffer domains. 283 + */ 284 + fce_bin_data_offset = *(u32 *)(virt + VIC_UCODE_FCE_DATA_OFFSET); 285 + 286 + if (!vic->config->supports_sid) { 287 + vic->can_use_context = false; 288 + } else if (fce_bin_data_offset != 0x0 && fce_bin_data_offset != 0xa5a5a5a5) { 289 + /* 290 + * Firmware will access FCE through STREAMID0, so context 291 + * isolation cannot be used. 292 + */ 293 + vic->can_use_context = false; 294 + dev_warn_once(vic->dev, "context isolation disabled due to old firmware\n"); 295 + } else { 296 + vic->can_use_context = true; 297 + } 298 + 299 + unlock: 300 + mutex_unlock(&lock); 301 + return err; 293 302 294 303 cleanup: 295 304 if (!client->group) ··· 318 285 else 319 286 tegra_drm_free(tegra, size, virt, iova); 320 287 288 + mutex_unlock(&lock); 321 289 return err; 322 290 } 323 291 ··· 392 358 host1x_channel_put(context->channel); 393 359 } 394 360 361 + static int vic_can_use_memory_ctx(struct tegra_drm_client *client, bool *supported) 362 + { 363 + struct vic *vic = to_vic(client); 364 + int err; 365 + 366 + /* This doesn't access HW so it's safe to call without powering up. */ 367 + err = vic_load_firmware(vic); 368 + if (err < 0) 369 + return err; 370 + 371 + *supported = vic->can_use_context; 372 + 373 + return 0; 374 + } 375 + 395 376 static const struct tegra_drm_client_ops vic_ops = { 396 377 .open_channel = vic_open_channel, 397 378 .close_channel = vic_close_channel, 398 379 .submit = tegra_drm_submit, 380 + .get_streamid_offset = tegra_drm_get_streamid_offset_thi, 381 + .can_use_memory_ctx = vic_can_use_memory_ctx, 399 382 }; 400 383 401 384 #define NVIDIA_TEGRA_124_VIC_FIRMWARE "nvidia/tegra124/vic03_ucode.bin"