Re: [PATCH 3/5] drm/amd/display: Add sysfs interface for set/get srm

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 




On 2020-01-17 2:23 p.m., Alex Deucher wrote:
On Thu, Jan 16, 2020 at 3:30 PM Bhawanpreet Lakha
<Bhawanpreet.Lakha@xxxxxxx> 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@xxxxxxx>
Reviewed-by: Rodrigo Siqueira <Rodrigo.Siqueira@xxxxxxx>
---
  .../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


I thought about using request_firmware but, since we also need to save the data aswell

and there is no "save_firmware" interface, we would have difference interfaces for reading and writing.

So to keep it consistent I used sysfs for both. Now we just cat and echo the raw data. vs echo file patch and cat raw data.


Bhawan

+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@xxxxxxxxxxxxxxxxxxxxx
https://nam11.safelinks.protection.outlook.com/?url=https%3A%2F%2Flists.freedesktop.org%2Fmailman%2Flistinfo%2Famd-gfx&amp;data=02%7C01%7CBhawanpreet.Lakha%40amd.com%7C31850cb2894b4459b6cf08d79b82b6af%7C3dd8961fe4884e608e11a82d994e183d%7C0%7C0%7C637148858026280913&amp;sdata=%2BncbIbzgws%2BKPbTAqzARNGAZWM66UoxzjDeJm6vvXlg%3D&amp;reserved=0
_______________________________________________
amd-gfx mailing list
amd-gfx@xxxxxxxxxxxxxxxxxxxxx
https://lists.freedesktop.org/mailman/listinfo/amd-gfx



[Index of Archives]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux