lkml.org 
[lkml]   [2021]   [Sep]   [16]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH v2 8/8] drm/tegra: Support context isolation
    Date
    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.

    Signed-off-by: Mikko Perttunen <mperttunen@nvidia.com>
    ---
    drivers/gpu/drm/tegra/drm.h | 2 ++
    drivers/gpu/drm/tegra/submit.c | 13 +++++++++++++
    drivers/gpu/drm/tegra/uapi.c | 34 ++++++++++++++++++++++++++++++++--
    3 files changed, 47 insertions(+), 2 deletions(-)

    diff --git a/drivers/gpu/drm/tegra/drm.h b/drivers/gpu/drm/tegra/drm.h
    index fc0a19554eac..717e9f81ee1f 100644
    --- a/drivers/gpu/drm/tegra/drm.h
    +++ b/drivers/gpu/drm/tegra/drm.h
    @@ -80,6 +80,7 @@ struct tegra_drm_context {

    /* Only used by new UAPI. */
    struct xarray mappings;
    + struct host1x_context *memory_context;
    };

    struct tegra_drm_client_ops {
    @@ -91,6 +92,7 @@ struct tegra_drm_client_ops {
    int (*submit)(struct tegra_drm_context *context,
    struct drm_tegra_submit *args, struct drm_device *drm,
    struct drm_file *file);
    + int (*get_streamid_offset)(struct tegra_drm_client *client);
    };

    int tegra_drm_submit(struct tegra_drm_context *context,
    diff --git a/drivers/gpu/drm/tegra/submit.c b/drivers/gpu/drm/tegra/submit.c
    index 776f825df52f..b6008246bebe 100644
    --- a/drivers/gpu/drm/tegra/submit.c
    +++ b/drivers/gpu/drm/tegra/submit.c
    @@ -469,6 +469,9 @@ static void release_job(struct host1x_job *job)
    struct tegra_drm_submit_data *job_data = job->user_data;
    u32 i;

    + if (job->context)
    + host1x_context_put(job->context);
    +
    for (i = 0; i < job_data->num_used_mappings; i++)
    tegra_drm_mapping_put(job_data->used_mappings[i].mapping);

    @@ -572,6 +575,16 @@ int tegra_drm_ioctl_channel_submit(struct drm_device *drm, void *data,
    job->release = release_job;
    job->timeout = 10000;

    + if (context->memory_context && context->client->ops->get_streamid_offset) {
    + int offset = context->client->ops->get_streamid_offset(context->client);
    +
    + if (offset >= 0) {
    + job->context = context->memory_context;
    + job->engine_streamid_offset = offset;
    + host1x_context_get(job->context);
    + }
    + }
    +
    /*
    * job_data is now part of job reference counting, so don't release
    * it from here.
    diff --git a/drivers/gpu/drm/tegra/uapi.c b/drivers/gpu/drm/tegra/uapi.c
    index 690a339c52ec..bfded46b974a 100644
    --- a/drivers/gpu/drm/tegra/uapi.c
    +++ b/drivers/gpu/drm/tegra/uapi.c
    @@ -37,6 +37,9 @@ static void tegra_drm_channel_context_close(struct tegra_drm_context *context)
    struct tegra_drm_mapping *mapping;
    unsigned long id;

    + if (context->memory_context)
    + host1x_context_put(context->memory_context);
    +
    xa_for_each(&context->mappings, id, mapping)
    tegra_drm_mapping_put(mapping);

    @@ -76,6 +79,7 @@ static struct tegra_drm_client *tegra_drm_find_client(struct tegra_drm *tegra, u

    int tegra_drm_ioctl_channel_open(struct drm_device *drm, void *data, struct drm_file *file)
    {
    + struct host1x *host = tegra_drm_to_host1x(drm->dev_private);
    struct tegra_drm_file *fpriv = file->driver_priv;
    struct tegra_drm *tegra = drm->dev_private;
    struct drm_tegra_channel_open *args = data;
    @@ -106,10 +110,29 @@ int tegra_drm_ioctl_channel_open(struct drm_device *drm, void *data, struct drm_
    }
    }

    + /* Only allocate context if the engine supports context isolation. */
    + if (client->ops->get_streamid_offset &&
    + client->ops->get_streamid_offset(client) >= 0) {
    + context->memory_context =
    + host1x_context_alloc(host, get_task_pid(current, PIDTYPE_TGID));
    + if (IS_ERR(context->memory_context)) {
    + if (PTR_ERR(context->memory_context) != -EOPNOTSUPP) {
    + err = PTR_ERR(context->memory_context);
    + goto put_channel;
    + } else {
    + /*
    + * OK, HW does not support contexts or contexts
    + * are disabled.
    + */
    + context->memory_context = NULL;
    + }
    + }
    + }
    +
    err = xa_alloc(&fpriv->contexts, &args->context, context, XA_LIMIT(1, U32_MAX),
    GFP_KERNEL);
    if (err < 0)
    - goto put_channel;
    + goto put_memctx;

    context->client = client;
    xa_init_flags(&context->mappings, XA_FLAGS_ALLOC1);
    @@ -122,6 +145,9 @@ int tegra_drm_ioctl_channel_open(struct drm_device *drm, void *data, struct drm_

    return 0;

    +put_memctx:
    + if (context->memory_context)
    + host1x_context_put(context->memory_context);
    put_channel:
    host1x_channel_put(context->channel);
    free:
    @@ -180,7 +206,11 @@ int tegra_drm_ioctl_channel_map(struct drm_device *drm, void *data, struct drm_f

    kref_init(&mapping->ref);

    - mapping->dev = context->client->base.dev;
    + if (context->memory_context)
    + mapping->dev = &context->memory_context->dev;
    + else
    + mapping->dev = context->client->base.dev;
    +
    mapping->bo = tegra_gem_lookup(file, args->handle);
    if (!mapping->bo) {
    err = -EINVAL;
    --
    2.32.0
    \
     
     \ /
      Last update: 2021-09-16 16:34    [W:4.246 / U:0.196 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site