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: Support context isolation

For engines that support context isolation, allocate a context when
opening a channel, and set up stream ID offset and context fields
when submitting a job.

As of this commit, the stream ID offset and fallback stream ID
are not used when context isolation is disabled. However, with
upcoming patches that enable a full featured job opcode sequence,
these will be necessary.

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
e09db978 88c0292f

+91 -3
+3
drivers/gpu/drm/tegra/drm.h
··· 80 80 81 81 /* Only used by new UAPI. */ 82 82 struct xarray mappings; 83 + struct host1x_memory_context *memory_context; 83 84 }; 84 85 85 86 struct tegra_drm_client_ops { ··· 92 91 int (*submit)(struct tegra_drm_context *context, 93 92 struct drm_tegra_submit *args, struct drm_device *drm, 94 93 struct drm_file *file); 94 + int (*get_streamid_offset)(struct tegra_drm_client *client, u32 *offset); 95 + int (*can_use_memory_ctx)(struct tegra_drm_client *client, bool *supported); 95 96 }; 96 97 97 98 int tegra_drm_submit(struct tegra_drm_context *context,
+47 -1
drivers/gpu/drm/tegra/submit.c
··· 498 498 struct tegra_drm_submit_data *job_data = job->user_data; 499 499 u32 i; 500 500 501 + if (job->memory_context) 502 + host1x_memory_context_put(job->memory_context); 503 + 501 504 for (i = 0; i < job_data->num_used_mappings; i++) 502 505 tegra_drm_mapping_put(job_data->used_mappings[i].mapping); 503 506 ··· 591 588 goto put_job; 592 589 } 593 590 591 + if (context->client->ops->get_streamid_offset) { 592 + err = context->client->ops->get_streamid_offset( 593 + context->client, &job->engine_streamid_offset); 594 + if (err) { 595 + SUBMIT_ERR(context, "failed to get streamid offset: %d", err); 596 + goto unpin_job; 597 + } 598 + } 599 + 600 + if (context->memory_context && context->client->ops->can_use_memory_ctx) { 601 + bool supported; 602 + 603 + err = context->client->ops->can_use_memory_ctx(context->client, &supported); 604 + if (err) { 605 + SUBMIT_ERR(context, "failed to detect if engine can use memory context: %d", err); 606 + goto unpin_job; 607 + } 608 + 609 + if (supported) { 610 + job->memory_context = context->memory_context; 611 + host1x_memory_context_get(job->memory_context); 612 + } 613 + } else if (context->client->ops->get_streamid_offset) { 614 + #ifdef CONFIG_IOMMU_API 615 + struct iommu_fwspec *spec; 616 + 617 + /* 618 + * Job submission will need to temporarily change stream ID, 619 + * so need to tell it what to change it back to. 620 + */ 621 + spec = dev_iommu_fwspec_get(context->client->base.dev); 622 + if (spec && spec->num_ids > 0) 623 + job->engine_fallback_streamid = spec->ids[0] & 0xffff; 624 + else 625 + job->engine_fallback_streamid = 0x7f; 626 + #else 627 + job->engine_fallback_streamid = 0x7f; 628 + #endif 629 + } 630 + 594 631 /* Boot engine. */ 595 632 err = pm_runtime_resume_and_get(context->client->base.dev); 596 633 if (err < 0) { 597 634 SUBMIT_ERR(context, "could not power up engine: %d", err); 598 - goto unpin_job; 635 + goto put_memory_context; 599 636 } 600 637 601 638 job->user_data = job_data; ··· 670 627 671 628 goto put_job; 672 629 630 + put_memory_context: 631 + if (job->memory_context) 632 + host1x_memory_context_put(job->memory_context); 673 633 unpin_job: 674 634 host1x_job_unpin(job); 675 635 put_job:
+41 -2
drivers/gpu/drm/tegra/uapi.c
··· 33 33 struct tegra_drm_mapping *mapping; 34 34 unsigned long id; 35 35 36 + if (context->memory_context) 37 + host1x_memory_context_put(context->memory_context); 38 + 36 39 xa_for_each(&context->mappings, id, mapping) 37 40 tegra_drm_mapping_put(mapping); 38 41 ··· 75 72 76 73 int tegra_drm_ioctl_channel_open(struct drm_device *drm, void *data, struct drm_file *file) 77 74 { 75 + struct host1x *host = tegra_drm_to_host1x(drm->dev_private); 78 76 struct tegra_drm_file *fpriv = file->driver_priv; 79 77 struct tegra_drm *tegra = drm->dev_private; 80 78 struct drm_tegra_channel_open *args = data; ··· 106 102 } 107 103 } 108 104 105 + /* Only allocate context if the engine supports context isolation. */ 106 + if (device_iommu_mapped(client->base.dev) && client->ops->can_use_memory_ctx) { 107 + bool supported; 108 + 109 + err = client->ops->can_use_memory_ctx(client, &supported); 110 + if (err) 111 + goto put_channel; 112 + 113 + if (supported) 114 + context->memory_context = host1x_memory_context_alloc( 115 + host, get_task_pid(current, PIDTYPE_TGID)); 116 + 117 + if (IS_ERR(context->memory_context)) { 118 + if (PTR_ERR(context->memory_context) != -EOPNOTSUPP) { 119 + err = PTR_ERR(context->memory_context); 120 + goto put_channel; 121 + } else { 122 + /* 123 + * OK, HW does not support contexts or contexts 124 + * are disabled. 125 + */ 126 + context->memory_context = NULL; 127 + } 128 + } 129 + } 130 + 109 131 err = xa_alloc(&fpriv->contexts, &args->context, context, XA_LIMIT(1, U32_MAX), 110 132 GFP_KERNEL); 111 133 if (err < 0) 112 - goto put_channel; 134 + goto put_memctx; 113 135 114 136 context->client = client; 115 137 xa_init_flags(&context->mappings, XA_FLAGS_ALLOC1); ··· 148 118 149 119 return 0; 150 120 121 + put_memctx: 122 + if (context->memory_context) 123 + host1x_memory_context_put(context->memory_context); 151 124 put_channel: 152 125 host1x_channel_put(context->channel); 153 126 free: ··· 189 156 struct tegra_drm_mapping *mapping; 190 157 struct tegra_drm_context *context; 191 158 enum dma_data_direction direction; 159 + struct device *mapping_dev; 192 160 int err = 0; 193 161 194 162 if (args->flags & ~DRM_TEGRA_CHANNEL_MAP_READ_WRITE) ··· 210 176 } 211 177 212 178 kref_init(&mapping->ref); 179 + 180 + if (context->memory_context) 181 + mapping_dev = &context->memory_context->dev; 182 + else 183 + mapping_dev = context->client->base.dev; 213 184 214 185 mapping->bo = tegra_gem_lookup(file, args->handle); 215 186 if (!mapping->bo) { ··· 240 201 goto put_gem; 241 202 } 242 203 243 - mapping->map = host1x_bo_pin(context->client->base.dev, mapping->bo, direction, NULL); 204 + mapping->map = host1x_bo_pin(mapping_dev, mapping->bo, direction, NULL); 244 205 if (IS_ERR(mapping->map)) { 245 206 err = PTR_ERR(mapping->map); 246 207 goto put_gem;