amd-gfx.lists.freedesktop.org archive mirror
 help / color / mirror / Atom feed
From: Alex Deucher <alexdeucher@gmail.com>
To: Bhawanpreet Lakha <Bhawanpreet.Lakha@amd.com>
Cc: "Wentland, Harry" <harry.wentland@amd.com>,
	amd-gfx list <amd-gfx@lists.freedesktop.org>
Subject: Re: [PATCH 3/5] drm/amd/display: Add sysfs interface for set/get srm
Date: Fri, 17 Jan 2020 14:23:07 -0500	[thread overview]
Message-ID: <CADnq5_Ms88BpiKvk5Okitu944yd3Ar5=AAzDb-_ne-SFP7YAEw@mail.gmail.com> (raw)
In-Reply-To: <20200116202945.21801-4-Bhawanpreet.Lakha@amd.com>

On Thu, Jan 16, 2020 at 3:30 PM Bhawanpreet Lakha
<Bhawanpreet.Lakha@amd.com> wrote:
>
> [Why]
> We need to set/get SRM and linux kernel is not suppose to write to the
> storage, so we need to provide a interface.
>
> [How]
> Provide interface so usermode can set/get srm
>
> Signed-off-by: Bhawanpreet Lakha <Bhawanpreet.Lakha@amd.com>
> Reviewed-by: Rodrigo Siqueira <Rodrigo.Siqueira@amd.com>
> ---
>  .../amd/display/amdgpu_dm/amdgpu_dm_hdcp.c    | 124 +++++++++++++++++-
>  .../amd/display/amdgpu_dm/amdgpu_dm_hdcp.h    |   6 +
>  2 files changed, 128 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_hdcp.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_hdcp.c
> index a269916f7dd6..a191c84ad8eb 100644
> --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_hdcp.c
> +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_hdcp.c
> @@ -28,6 +28,8 @@
>  #include "amdgpu_dm.h"
>  #include "dm_helpers.h"
>  #include <drm/drm_hdcp.h>
> +#include "hdcp_psp.h"
> +
>
>  static bool
>  lp_write_i2c(void *handle, uint32_t address, const uint8_t *data, uint32_t size)
> @@ -67,6 +69,16 @@ lp_read_dpcd(void *handle, uint32_t address, uint8_t *data, uint32_t size)
>         return dm_helpers_dp_read_dpcd(link->ctx, link, address, data, size);
>  }
>
> +static uint8_t *psp_get_srm(struct psp_context *psp, uint32_t *srm_version, uint32_t *srm_size)
> +{
> +       return NULL;
> +}
> +
> +static int psp_set_srm(struct psp_context *psp, uint8_t *srm, uint32_t srm_size, uint32_t *srm_version)
> +{
> +       return 0;
> +}
> +
>  static void process_output(struct hdcp_workqueue *hdcp_work)
>  {
>         struct mod_hdcp_output output = hdcp_work->output;
> @@ -88,6 +100,18 @@ static void process_output(struct hdcp_workqueue *hdcp_work)
>         schedule_delayed_work(&hdcp_work->property_validate_dwork, msecs_to_jiffies(0));
>  }
>
> +static void link_lock(struct hdcp_workqueue *work, bool lock)
> +{
> +
> +       int i = 0;
> +
> +       for (i = 0; i < work->max_link; i++) {
> +               if (lock)
> +                       mutex_lock(&work[i].mutex);
> +               else
> +                       mutex_unlock(&work[i].mutex);
> +       }
> +}
>  void hdcp_update_display(struct hdcp_workqueue *hdcp_work,
>                          unsigned int link_index,
>                          struct amdgpu_dm_connector *aconnector,
> @@ -302,7 +326,8 @@ void hdcp_destroy(struct hdcp_workqueue *hdcp_work)
>         }
>
>         kfree(hdcp_work);
> -
> +       kfree(hdcp_work->srm);
> +       kfree(hdcp_work->srm_temp);
>  }
>
>  static void update_config(void *handle, struct cp_psp_stream_config *config)
> @@ -338,6 +363,84 @@ static void update_config(void *handle, struct cp_psp_stream_config *config)
>         hdcp_update_display(hdcp_work, link_index, aconnector, DRM_MODE_HDCP_CONTENT_TYPE0, false);
>  }
>
> +
> +/*
> + * This can be called twice, because SRM_SIZE > PAGE_SIZE.
> + *
> + * We set the SRM on each call, if SRM_SIZE > PAGE_SIZE, PSP will fail on the
> + * first call but pass on the second call.
> + *
> + * Because of this we are not throwing any errors as it will stop the next call.
> + * So it is a good idea to call the "read" sysfs to verify that the SRM was set
> + *
> + */

Rather than using a file to get the data directly in chunks, how about
adding a sysfs file where you can specify the path to the srm file.
The driver can then use the path provided to call request firmware and
just get the entire binary in one shot.

Alex


> +static ssize_t srm_data_write(struct file *filp, struct kobject *kobj, struct bin_attribute *bin_attr, char *buffer,
> +                             loff_t pos, size_t count)
> +{
> +       struct hdcp_workqueue *work;
> +       uint32_t srm_version = 0;
> +
> +       work = container_of(bin_attr, struct hdcp_workqueue, attr);
> +       link_lock(work, true);
> +
> +       memcpy(work->srm_temp + pos, buffer, count);
> +
> +       if (!psp_set_srm(work->hdcp.config.psp.handle, work->srm_temp, pos + count, &srm_version)) {
> +               DRM_DEBUG_DRIVER("HDCP SRM SET version 0x%X", srm_version);
> +               memcpy(work->srm, work->srm_temp, pos + count);
> +               work->srm_size = pos + count;
> +               work->srm_version = srm_version;
> +       }
> +
> +
> +       link_lock(work, false);
> +
> +       return count;
> +}
> +
> +static ssize_t srm_data_read(struct file *filp, struct kobject *kobj, struct bin_attribute *bin_attr, char *buffer,
> +                            loff_t pos, size_t count)
> +{
> +       struct hdcp_workqueue *work;
> +       uint8_t *srm = NULL;
> +       uint32_t srm_version;
> +       uint32_t srm_size;
> +       size_t ret = count;
> +
> +       work = container_of(bin_attr, struct hdcp_workqueue, attr);
> +
> +       link_lock(work, true);
> +
> +       srm = psp_get_srm(work->hdcp.config.psp.handle, &srm_version, &srm_size);
> +
> +       if (!srm)
> +               return -EINVAL;
> +
> +       if (pos >= srm_size)
> +               ret = 0;
> +
> +       if (srm_size - pos < count) {
> +               memcpy(buffer, srm + pos, srm_size - pos);
> +               ret = srm_size - pos;
> +               goto ret;
> +       }
> +
> +       memcpy(buffer, srm + pos, count);
> +
> +ret:
> +       link_lock(work, false);
> +       return ret;
> +}
> +
> +
> +static const struct bin_attribute data_attr = {
> +       .attr = {.name = "hdcp_srm", .mode = 0664},
> +       .size = PSP_HDCP_SRM_FIRST_GEN_MAX_SIZE, /* Limit SRM size */
> +       .write = srm_data_write,
> +       .read = srm_data_read,
> +};
> +
> +
>  struct hdcp_workqueue *hdcp_create_workqueue(struct amdgpu_device *adev, struct cp_psp *cp_psp, struct dc *dc)
>  {
>
> @@ -348,10 +451,19 @@ struct hdcp_workqueue *hdcp_create_workqueue(struct amdgpu_device *adev, struct
>         if (hdcp_work == NULL)
>                 goto fail_alloc_context;
>
> +       hdcp_work->srm = kcalloc(PSP_HDCP_SRM_FIRST_GEN_MAX_SIZE, sizeof(*hdcp_work->srm), GFP_KERNEL);
> +
> +       if (hdcp_work->srm == NULL)
> +               goto fail_alloc_context;
> +
> +       hdcp_work->srm_temp = kcalloc(PSP_HDCP_SRM_FIRST_GEN_MAX_SIZE, sizeof(*hdcp_work->srm_temp), GFP_KERNEL);
> +
> +       if (hdcp_work->srm_temp == NULL)
> +               goto fail_alloc_context;
> +
>         hdcp_work->max_link = max_caps;
>
>         for (i = 0; i < max_caps; i++) {
> -
>                 mutex_init(&hdcp_work[i].mutex);
>
>                 INIT_WORK(&hdcp_work[i].cpirq_work, event_cpirq);
> @@ -371,10 +483,18 @@ struct hdcp_workqueue *hdcp_create_workqueue(struct amdgpu_device *adev, struct
>         cp_psp->funcs.update_stream_config = update_config;
>         cp_psp->handle = hdcp_work;
>
> +       /* File created at /sys/class/drm/card0/device/hdcp_srm*/
> +       hdcp_work[0].attr = data_attr;
> +
> +       if (sysfs_create_bin_file(&adev->dev->kobj, &hdcp_work[0].attr))
> +               DRM_WARN("Failed to create device file hdcp_srm");
> +
>         return hdcp_work;
>
>  fail_alloc_context:
>         kfree(hdcp_work);
> +       kfree(hdcp_work->srm);
> +       kfree(hdcp_work->srm_temp);
>
>         return NULL;
>
> diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_hdcp.h b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_hdcp.h
> index 331b50825510..5159b3a5e5b0 100644
> --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_hdcp.h
> +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_hdcp.h
> @@ -53,6 +53,12 @@ struct hdcp_workqueue {
>
>         enum mod_hdcp_encryption_status encryption_status;
>         uint8_t max_link;
> +
> +       uint8_t *srm;
> +       uint8_t *srm_temp;
> +       uint32_t srm_version;
> +       uint32_t srm_size;
> +       struct bin_attribute attr;
>  };
>
>  void hdcp_update_display(struct hdcp_workqueue *hdcp_work,
> --
> 2.17.1
>
> _______________________________________________
> amd-gfx mailing list
> amd-gfx@lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/amd-gfx
_______________________________________________
amd-gfx mailing list
amd-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/amd-gfx

  reply	other threads:[~2020-01-17 19:23 UTC|newest]

Thread overview: 16+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2020-01-16 20:29 [PATCH 0/5] HDCP SRM interface Bhawanpreet Lakha
2020-01-16 20:29 ` [PATCH 1/5] drm/amd/display: Pass amdgpu_device instead of psp_context Bhawanpreet Lakha
2020-01-16 20:29 ` [PATCH 2/5] drm/amd/display: update psp interface header Bhawanpreet Lakha
2020-01-22 16:10   ` Harry Wentland
2020-01-16 20:29 ` [PATCH 3/5] drm/amd/display: Add sysfs interface for set/get srm Bhawanpreet Lakha
2020-01-17 19:23   ` Alex Deucher [this message]
2020-01-17 19:29     ` Bhawanpreet Lakha
2020-01-22 19:03   ` Harry Wentland
2020-01-16 20:29 ` [PATCH 4/5] drm/amd/display: Load srm before enabling HDCP Bhawanpreet Lakha
2020-01-16 20:29 ` [PATCH 5/5] drm/amd/display: call psp set/get interfaces Bhawanpreet Lakha
2020-01-22 19:25   ` Harry Wentland
2020-01-22 16:11 ` [PATCH 0/5] HDCP SRM interface Harry Wentland
2020-01-22 16:23   ` Alex Deucher
2020-01-22 16:44     ` Bhawanpreet Lakha
2020-01-22 19:27       ` Harry Wentland
2020-01-22 19:49         ` Deucher, Alexander

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to='CADnq5_Ms88BpiKvk5Okitu944yd3Ar5=AAzDb-_ne-SFP7YAEw@mail.gmail.com' \
    --to=alexdeucher@gmail.com \
    --cc=Bhawanpreet.Lakha@amd.com \
    --cc=amd-gfx@lists.freedesktop.org \
    --cc=harry.wentland@amd.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).