All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v9 00/39] drm/i915: Implement HDCP2.2
@ 2018-12-13  4:01 Ramalingam C
  2018-12-13  4:01 ` [PATCH v9 01/39] drm/i915: Gathering the HDCP1.4 routines together Ramalingam C
                   ` (42 more replies)
  0 siblings, 43 replies; 103+ messages in thread
From: Ramalingam C @ 2018-12-13  4:01 UTC (permalink / raw)
  To: intel-gfx, dri-devel, seanpaul, daniel.vetter, tomas.winkler,
	uma.shankar

This series enables the HDCP2.2 for I915. The sequence for HDCP2.2
authentication and encryption is implemented as a generic flow
between HDMI and DP. Encoder specific implementations are moved
into hdcp_shim.

Intel HWs supports HDCP2.2 through ME FW. Hence this series
introduces a client driver for mei bus, so that for HDCP2.2
authentication, HDCP2.2 stack in I915 can avail the services from
ME FW. To enable this client driver set the config variable
CONFIG_INTEL_MEI_HDCP.

Userspace interface remains unchanged as version agnostic. When
userspace request for HDCP enable, Kernel will detect the HDCP source
and sink's HDCP version(1.4/2.2)capability and enable the best capable
version for that combination.

This series enables the HDCP2.2 for Type0 content strams.

Major changes in v9:
  - Mei_hdcp component binding status will impact I915_load [Daniel].
  - worker for sysfs unbind from daniel.
  - i915-mei_hdcp interface defined at i915_mei_hdcp_interface.h
  - Same check_work is used for HDCP1.4 and 2.2 link check. [Daniel]
  - seq_num to and from u32 is done through a helper. [Daniel]
  - hdcp_wired_protocol() is replaced with a const [Daniel]
  - Kdocs are added to mei_hdcp.c [Tomas]
  - i915 port -> mei_ddi_index conversion moved to mei_hdcp [Tomas]
  - SW tracking of the HDCP spec enabled is used [Daniel]

Hopefully covered all suggestions from Tomas and Daniel.

To ease the review process, series is hosted at
https://github.com/ramalingampc2008/drm-tip.git hdcp2_2_v9

Daniel Vetter (1):
  drivers/base: use a worker for sysfs unbind

Ramalingam C (36):
  drm/i915: Gathering the HDCP1.4 routines together
  drm: header for i915 - MEI_HDCP interface
  component: alloc component_match without any comp to match
  drm/i915: component master at i915 driver load
  drm/i915: Initialize HDCP2.2
  drm/i915: MEI interface definition
  drm/i915: hdcp1.4 CP_IRQ handling and SW encryption tracking
  drm/i915: Enable and Disable of HDCP2.2
  drm/i915: Implement HDCP2.2 receiver authentication
  drm: helper functions for hdcp2 seq_num to from u32
  drm/i915: Implement HDCP2.2 repeater authentication
  drm: HDCP2.2 link check related constants
  drm/i915: Implement HDCP2.2 link integrity check
  drm/i915: Handle HDCP2.2 downstream topology change
  drm/i915: Implement the HDCP2.2 support for DP
  drm/i915: Implement the HDCP2.2 support for HDMI
  drm/i915: Add HDCP2.2 support for DP connectors
  drm/i915: Add HDCP2.2 support for HDMI connectors
  misc/mei/hdcp: Client driver for HDCP application
  misc/mei/hdcp: Define ME FW interface for HDCP2.2
  misc/mei/hdcp: Initiate Wired HDCP2.2 Tx Session
  misc/mei/hdcp: Verify Receiver Cert and prepare km
  misc/mei/hdcp: Verify H_prime
  misc/mei/hdcp: Store the HDCP Pairing info
  misc/mei/hdcp: Initiate Locality check
  misc/mei/hdcp: Verify L_prime
  misc/mei/hdcp: Prepare Session Key
  misc/mei/hdcp: Repeater topology verification and ack
  misc/mei/hdcp: Verify M_prime
  misc/mei/hdcp: Enabling the HDCP authentication
  misc/mei/hdcp: Closing wired HDCP2.2 Tx Session
  misc/mei/hdcp: Component framework for I915 Interface
  drm/i915: Commit CP without modeset
  drm/i915: Fix KBL HDCP2.2 encrypt status signalling
  FOR_TEST: i915/Kconfig: Select mei_hdcp by I915
  FOR_TESTING_ONLY: debugfs: Excluding the LSPCon for HDCP1.4

Tomas Winkler (2):
  mei: bus: whitelist hdcp client
  mei: bus: export to_mei_cl_device for mei client device drivers

 drivers/base/bus.c                    |   35 +-
 drivers/base/component.c              |   30 +
 drivers/gpu/drm/i915/i915_debugfs.c   |   10 +-
 drivers/gpu/drm/i915/i915_drv.c       |   86 ++-
 drivers/gpu/drm/i915/i915_drv.h       |    3 +
 drivers/gpu/drm/i915/intel_ddi.c      |    7 -
 drivers/gpu/drm/i915/intel_display.c  |   10 +
 drivers/gpu/drm/i915/intel_dp.c       |  315 ++++++++-
 drivers/gpu/drm/i915/intel_drv.h      |   74 ++-
 drivers/gpu/drm/i915/intel_hdcp.c     | 1178 +++++++++++++++++++++++++++++----
 drivers/gpu/drm/i915/intel_hdmi.c     |  192 +++++-
 drivers/misc/mei/Kconfig              |    8 +
 drivers/misc/mei/Makefile             |    2 +
 drivers/misc/mei/bus-fixup.c          |   16 +
 drivers/misc/mei/bus.c                |    1 -
 drivers/misc/mei/hdcp/Makefile        |    7 +
 drivers/misc/mei/hdcp/mei_hdcp.c      |  807 ++++++++++++++++++++++
 drivers/misc/mei/hdcp/mei_hdcp.h      |  394 +++++++++++
 include/drm/drm_hdcp.h                |   26 +
 include/drm/i915_component.h          |   18 +
 include/drm/i915_mei_hdcp_interface.h |  132 ++++
 include/linux/component.h             |    2 +
 include/linux/mei_cl_bus.h            |    2 +
 23 files changed, 3207 insertions(+), 148 deletions(-)
 create mode 100644 drivers/misc/mei/hdcp/Makefile
 create mode 100644 drivers/misc/mei/hdcp/mei_hdcp.c
 create mode 100644 drivers/misc/mei/hdcp/mei_hdcp.h
 create mode 100644 include/drm/i915_mei_hdcp_interface.h

-- 
2.7.4

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 103+ messages in thread

* [PATCH v9 01/39] drm/i915: Gathering the HDCP1.4 routines together
  2018-12-13  4:01 [PATCH v9 00/39] drm/i915: Implement HDCP2.2 Ramalingam C
@ 2018-12-13  4:01 ` Ramalingam C
  2018-12-13  8:17   ` Winkler, Tomas
  2018-12-19 13:35   ` Daniel Vetter
  2018-12-13  4:01 ` [PATCH v9 02/39] drm: header for i915 - MEI_HDCP interface Ramalingam C
                   ` (41 subsequent siblings)
  42 siblings, 2 replies; 103+ messages in thread
From: Ramalingam C @ 2018-12-13  4:01 UTC (permalink / raw)
  To: intel-gfx, dri-devel, seanpaul, daniel.vetter, tomas.winkler,
	uma.shankar

All HDCP1.4 routines are gathered together, followed by the generic
functions those can be extended for HDCP2.2 too.

Signed-off-by: Ramalingam C <ramalingam.c@intel.com>
---
 drivers/gpu/drm/i915/intel_hdcp.c | 118 +++++++++++++++++++-------------------
 1 file changed, 59 insertions(+), 59 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_hdcp.c b/drivers/gpu/drm/i915/intel_hdcp.c
index e000e54ad569..506b4cc6f46b 100644
--- a/drivers/gpu/drm/i915/intel_hdcp.c
+++ b/drivers/gpu/drm/i915/intel_hdcp.c
@@ -731,6 +731,65 @@ struct intel_connector *intel_hdcp_to_connector(struct intel_hdcp *hdcp)
 	return container_of(hdcp, struct intel_connector, hdcp);
 }
 
+/* Implements Part 3 of the HDCP authorization procedure */
+int intel_hdcp_check_link(struct intel_connector *connector)
+{
+	struct intel_hdcp *hdcp = &connector->hdcp;
+	struct drm_i915_private *dev_priv = connector->base.dev->dev_private;
+	struct intel_digital_port *intel_dig_port = conn_to_dig_port(connector);
+	enum port port = intel_dig_port->base.port;
+	int ret = 0;
+
+	if (!hdcp->shim)
+		return -ENOENT;
+
+	mutex_lock(&hdcp->mutex);
+
+	if (hdcp->value == DRM_MODE_CONTENT_PROTECTION_UNDESIRED)
+		goto out;
+
+	if (!(I915_READ(PORT_HDCP_STATUS(port)) & HDCP_STATUS_ENC)) {
+		DRM_ERROR("%s:%d HDCP check failed: link is not encrypted,%x\n",
+			  connector->base.name, connector->base.base.id,
+			  I915_READ(PORT_HDCP_STATUS(port)));
+		ret = -ENXIO;
+		hdcp->value = DRM_MODE_CONTENT_PROTECTION_DESIRED;
+		schedule_work(&hdcp->prop_work);
+		goto out;
+	}
+
+	if (hdcp->shim->check_link(intel_dig_port)) {
+		if (hdcp->value != DRM_MODE_CONTENT_PROTECTION_UNDESIRED) {
+			hdcp->value = DRM_MODE_CONTENT_PROTECTION_ENABLED;
+			schedule_work(&hdcp->prop_work);
+		}
+		goto out;
+	}
+
+	DRM_DEBUG_KMS("[%s:%d] HDCP link failed, retrying authentication\n",
+		      connector->base.name, connector->base.base.id);
+
+	ret = _intel_hdcp_disable(connector);
+	if (ret) {
+		DRM_ERROR("Failed to disable hdcp (%d)\n", ret);
+		hdcp->value = DRM_MODE_CONTENT_PROTECTION_DESIRED;
+		schedule_work(&hdcp->prop_work);
+		goto out;
+	}
+
+	ret = _intel_hdcp_enable(connector);
+	if (ret) {
+		DRM_ERROR("Failed to enable hdcp (%d)\n", ret);
+		hdcp->value = DRM_MODE_CONTENT_PROTECTION_DESIRED;
+		schedule_work(&hdcp->prop_work);
+		goto out;
+	}
+
+out:
+	mutex_unlock(&hdcp->mutex);
+	return ret;
+}
+
 static void intel_hdcp_check_work(struct work_struct *work)
 {
 	struct intel_hdcp *hdcp = container_of(to_delayed_work(work),
@@ -867,62 +926,3 @@ void intel_hdcp_atomic_check(struct drm_connector *connector,
 						   new_state->crtc);
 	crtc_state->mode_changed = true;
 }
-
-/* Implements Part 3 of the HDCP authorization procedure */
-int intel_hdcp_check_link(struct intel_connector *connector)
-{
-	struct intel_hdcp *hdcp = &connector->hdcp;
-	struct drm_i915_private *dev_priv = connector->base.dev->dev_private;
-	struct intel_digital_port *intel_dig_port = conn_to_dig_port(connector);
-	enum port port = intel_dig_port->base.port;
-	int ret = 0;
-
-	if (!hdcp->shim)
-		return -ENOENT;
-
-	mutex_lock(&hdcp->mutex);
-
-	if (hdcp->value == DRM_MODE_CONTENT_PROTECTION_UNDESIRED)
-		goto out;
-
-	if (!(I915_READ(PORT_HDCP_STATUS(port)) & HDCP_STATUS_ENC)) {
-		DRM_ERROR("%s:%d HDCP check failed: link is not encrypted,%x\n",
-			  connector->base.name, connector->base.base.id,
-			  I915_READ(PORT_HDCP_STATUS(port)));
-		ret = -ENXIO;
-		hdcp->value = DRM_MODE_CONTENT_PROTECTION_DESIRED;
-		schedule_work(&hdcp->prop_work);
-		goto out;
-	}
-
-	if (hdcp->shim->check_link(intel_dig_port)) {
-		if (hdcp->value != DRM_MODE_CONTENT_PROTECTION_UNDESIRED) {
-			hdcp->value = DRM_MODE_CONTENT_PROTECTION_ENABLED;
-			schedule_work(&hdcp->prop_work);
-		}
-		goto out;
-	}
-
-	DRM_DEBUG_KMS("[%s:%d] HDCP link failed, retrying authentication\n",
-		      connector->base.name, connector->base.base.id);
-
-	ret = _intel_hdcp_disable(connector);
-	if (ret) {
-		DRM_ERROR("Failed to disable hdcp (%d)\n", ret);
-		hdcp->value = DRM_MODE_CONTENT_PROTECTION_DESIRED;
-		schedule_work(&hdcp->prop_work);
-		goto out;
-	}
-
-	ret = _intel_hdcp_enable(connector);
-	if (ret) {
-		DRM_DEBUG_KMS("Failed to enable hdcp (%d)\n", ret);
-		hdcp->value = DRM_MODE_CONTENT_PROTECTION_DESIRED;
-		schedule_work(&hdcp->prop_work);
-		goto out;
-	}
-
-out:
-	mutex_unlock(&hdcp->mutex);
-	return ret;
-}
-- 
2.7.4

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply related	[flat|nested] 103+ messages in thread

* [PATCH v9 02/39] drm: header for i915 - MEI_HDCP interface
  2018-12-13  4:01 [PATCH v9 00/39] drm/i915: Implement HDCP2.2 Ramalingam C
  2018-12-13  4:01 ` [PATCH v9 01/39] drm/i915: Gathering the HDCP1.4 routines together Ramalingam C
@ 2018-12-13  4:01 ` Ramalingam C
  2018-12-17 11:28   ` Winkler, Tomas
  2018-12-19 13:37   ` Daniel Vetter
  2018-12-13  4:01 ` [PATCH v9 03/39] drivers/base: use a worker for sysfs unbind Ramalingam C
                   ` (40 subsequent siblings)
  42 siblings, 2 replies; 103+ messages in thread
From: Ramalingam C @ 2018-12-13  4:01 UTC (permalink / raw)
  To: intel-gfx, dri-devel, seanpaul, daniel.vetter, tomas.winkler,
	uma.shankar

Header defines the interface for the I915 and MEI_HDCP drivers.

Signed-off-by: Ramalingam C <ramalingam.c@intel.com>
---
 include/drm/i915_mei_hdcp_interface.h | 132 ++++++++++++++++++++++++++++++++++
 1 file changed, 132 insertions(+)
 create mode 100644 include/drm/i915_mei_hdcp_interface.h

diff --git a/include/drm/i915_mei_hdcp_interface.h b/include/drm/i915_mei_hdcp_interface.h
new file mode 100644
index 000000000000..e3b7fb32612a
--- /dev/null
+++ b/include/drm/i915_mei_hdcp_interface.h
@@ -0,0 +1,132 @@
+/* SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) */
+/*
+ * Copyright © 2017-2018 Intel Corporation
+ *
+ * Authors:
+ * Ramalingam C <ramalingam.c@intel.com>
+ */
+
+#ifndef _I915_MEI_HDCP_INTERFACE_H_
+#define _I915_MEI_HDCP_INTERFACE_H_
+
+#include <linux/mutex.h>
+#include <drm/drm_hdcp.h>
+
+/**
+ * enum hdcp_port_type - HDCP port implementation type defined by ME FW
+ * @HDCP_PORT_TYPE_INVALID: Invalid hdcp port type
+ * @HDCP_PORT_TYPE_INTEGRATED: In-Host HDCP2.x port
+ * @HDCP_PORT_TYPE_LSPCON: HDCP2.2 discrete wired Tx port with LSPCON
+ *			   (HDMI 2.0) solution
+ * @HDCP_PORT_TYPE_CPDP: HDCP2.2 discrete wired Tx port using the CPDP (DP 1.3)
+ *			 solution
+ */
+enum hdcp_port_type {
+	HDCP_PORT_TYPE_INVALID,
+	HDCP_PORT_TYPE_INTEGRATED,
+	HDCP_PORT_TYPE_LSPCON,
+	HDCP_PORT_TYPE_CPDP
+};
+
+/**
+ * enum hdcp_wired_protocol - HDCP adaptation used on the port
+ * @HDCP_PROTOCOL_INVALID: Invalid HDCP adaptation protocol
+ * @HDCP_PROTOCOL_HDMI: HDMI adaptation of HDCP used on the port
+ * @HDCP_PROTOCOL_DP: DP adaptation of HDCP used on the port
+ */
+enum hdcp_wired_protocol {
+	HDCP_PROTOCOL_INVALID,
+	HDCP_PROTOCOL_HDMI,
+	HDCP_PROTOCOL_DP
+};
+
+/**
+ * struct hdcp_port_data - intel specific HDCP port data
+ * @port: port index as per I915
+ * @port_type: HDCP port type as per ME FW classification
+ * @protocol: HDCP adaptation as per ME FW
+ * @k: No of streams transmitted on a port. Only on DP MST this is != 1
+ * @seq_num_m: Count of RepeaterAuth_Stream_Manage msg propagated.
+ *	       Initialized to 0 on AKE_INIT. Incremented after every successful
+ *	       transmission of RepeaterAuth_Stream_Manage message. When it rolls
+ *	       over re-Auth has to be triggered.
+ * @streams: struct hdcp2_streamid_type[k]. Defines the type and id for the
+ *	     streams
+ */
+struct hdcp_port_data {
+	short int port;
+	u8 port_type;
+	u8 protocol;
+	u16 k;
+	u32 seq_num_m;
+	struct hdcp2_streamid_type *streams;
+};
+
+/**
+ * struct i915_hdcp_component_ops- ops for HDCP2.2 services.
+ * @owner: Module providing the ops
+ * @initiate_hdcp2_session: Initiate a Wired HDCP2.2 Tx Session.
+ *			    And Prepare AKE_Init.
+ * @verify_receiver_cert_prepare_km: Verify the Receiver Certificate
+ *				     AKE_Send_Cert and prepare
+				     AKE_Stored_Km/AKE_No_Stored_Km
+ * @verify_hprime: Verify AKE_Send_H_prime
+ * @store_pairing_info: Store pairing info received
+ * @initiate_locality_check: Prepare LC_Init
+ * @verify_lprime: Verify lprime
+ * @get_session_key: Prepare SKE_Send_Eks
+ * @repeater_check_flow_prepare_ack: Validate the Downstream topology
+ *				     and prepare rep_ack
+ * @verify_mprime: Verify mprime
+ * @enable_hdcp_authentication:  Mark a port as authenticated.
+ * @close_hdcp_session: Close the Wired HDCP Tx session per port.
+ *			This also disables the authenticated state of the port.
+ */
+struct i915_hdcp_component_ops {
+	/**
+	 * @owner: mei_hdcp module
+	 */
+	struct module *owner;
+
+	int (*initiate_hdcp2_session)(struct device *dev,
+				      struct hdcp_port_data *data,
+				      struct hdcp2_ake_init *ake_data);
+	int (*verify_receiver_cert_prepare_km)(struct device *dev,
+					       struct hdcp_port_data *data,
+					       struct hdcp2_ake_send_cert
+								*rx_cert,
+					       bool *km_stored,
+					       struct hdcp2_ake_no_stored_km
+								*ek_pub_km,
+					       size_t *msg_sz);
+	int (*verify_hprime)(struct device *dev,
+			     struct hdcp_port_data *data,
+			     struct hdcp2_ake_send_hprime *rx_hprime);
+	int (*store_pairing_info)(struct device *dev,
+				  struct hdcp_port_data *data,
+				  struct hdcp2_ake_send_pairing_info
+								*pairing_info);
+	int (*initiate_locality_check)(struct device *dev,
+				       struct hdcp_port_data *data,
+				       struct hdcp2_lc_init *lc_init_data);
+	int (*verify_lprime)(struct device *dev,
+			     struct hdcp_port_data *data,
+			     struct hdcp2_lc_send_lprime *rx_lprime);
+	int (*get_session_key)(struct device *dev,
+			       struct hdcp_port_data *data,
+			       struct hdcp2_ske_send_eks *ske_data);
+	int (*repeater_check_flow_prepare_ack)(struct device *dev,
+					       struct hdcp_port_data *data,
+					       struct hdcp2_rep_send_receiverid_list
+								*rep_topology,
+					       struct hdcp2_rep_send_ack
+								*rep_send_ack);
+	int (*verify_mprime)(struct device *dev,
+			     struct hdcp_port_data *data,
+			     struct hdcp2_rep_stream_ready *stream_ready);
+	int (*enable_hdcp_authentication)(struct device *dev,
+					  struct hdcp_port_data *data);
+	int (*close_hdcp_session)(struct device *dev,
+				  struct hdcp_port_data *data);
+};
+#endif /* _I915_MEI_HDCP_NTERFACE_H_ */
-- 
2.7.4

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply related	[flat|nested] 103+ messages in thread

* [PATCH v9 03/39] drivers/base: use a worker for sysfs unbind
  2018-12-13  4:01 [PATCH v9 00/39] drm/i915: Implement HDCP2.2 Ramalingam C
  2018-12-13  4:01 ` [PATCH v9 01/39] drm/i915: Gathering the HDCP1.4 routines together Ramalingam C
  2018-12-13  4:01 ` [PATCH v9 02/39] drm: header for i915 - MEI_HDCP interface Ramalingam C
@ 2018-12-13  4:01 ` Ramalingam C
  2018-12-19 13:38   ` Daniel Vetter
  2018-12-13  4:01 ` [PATCH v9 04/39] component: alloc component_match without any comp to match Ramalingam C
                   ` (39 subsequent siblings)
  42 siblings, 1 reply; 103+ messages in thread
From: Ramalingam C @ 2018-12-13  4:01 UTC (permalink / raw)
  To: intel-gfx, dri-devel, seanpaul, daniel.vetter, tomas.winkler,
	uma.shankar
  Cc: Daniel Vetter

From: Daniel Vetter <daniel.vetter@intel.com>

Drivers might want to remove some sysfs files, which needs the same
locks and ends up angering lockdep. Relevant snippet of the stack
trace:

  kernfs_remove_by_name_ns+0x3b/0x80
  bus_remove_driver+0x92/0xa0
  acpi_video_unregister+0x24/0x40
  i915_driver_unload+0x42/0x130 [i915]
  i915_pci_remove+0x19/0x30 [i915]
  pci_device_remove+0x36/0xb0
  device_release_driver_internal+0x185/0x250
  unbind_store+0xaf/0x180
  kernfs_fop_write+0x104/0x190

I've stumbled over this because some new patches by Ram connect the
snd-hda-intel unload (where we do use sysfs unbind) with the locking
chains in the i915 unload code (but without creating a new loop),
which upset our CI. But the bug is already there and can be easily
reproduced by unbind i915 directly.

No idea whether this is the correct place to fix this, should at least
get CI happy again.

Note that the bus locking is already done by device_release_driver ->
device_release_driver_internal, so I dropped that part. Also note that
we don't recheck that the device is still bound by the same driver,
but neither does the current code do that without races. And I figured
that's a obscure enough corner case to not bother.

v2: Use a task work. An entirely async work leads to impressive
fireworks in our CI, notably in the vtcon bind/unbind code. Task work
will be as synchronous as the current code, and so keep all these
preexisting races neatly tugged under the rug.

Cc: Ramalingam C <ramalingam.c@intel.com>
Signed-off-by: Daniel Vetter <daniel.vetter@intel.com>
---
 drivers/base/bus.c | 35 +++++++++++++++++++++++++++++------
 1 file changed, 29 insertions(+), 6 deletions(-)

diff --git a/drivers/base/bus.c b/drivers/base/bus.c
index 8bfd27ec73d6..095c4a140d76 100644
--- a/drivers/base/bus.c
+++ b/drivers/base/bus.c
@@ -17,6 +17,7 @@
 #include <linux/string.h>
 #include <linux/mutex.h>
 #include <linux/sysfs.h>
+#include <linux/task_work.h>
 #include "base.h"
 #include "power/power.h"
 
@@ -174,22 +175,44 @@ static const struct kset_uevent_ops bus_uevent_ops = {
 
 static struct kset *bus_kset;
 
+struct unbind_work {
+	struct callback_head twork;
+	struct device *dev;
+};
+
+void unbind_work_fn(struct callback_head *work)
+{
+	struct unbind_work *unbind_work =
+		container_of(work, struct unbind_work, twork);
+
+	device_release_driver_internal(unbind_work->dev, NULL,
+				       unbind_work->dev->parent);
+	put_device(unbind_work->dev);
+	kfree(unbind_work);
+}
+
 /* Manually detach a device from its associated driver. */
 static ssize_t unbind_store(struct device_driver *drv, const char *buf,
 			    size_t count)
 {
 	struct bus_type *bus = bus_get(drv->bus);
+	struct unbind_work *unbind_work;
 	struct device *dev;
 	int err = -ENODEV;
 
 	dev = bus_find_device_by_name(bus, NULL, buf);
 	if (dev && dev->driver == drv) {
-		if (dev->parent && dev->bus->need_parent_lock)
-			device_lock(dev->parent);
-		device_release_driver(dev);
-		if (dev->parent && dev->bus->need_parent_lock)
-			device_unlock(dev->parent);
-		err = count;
+		unbind_work = kmalloc(sizeof(*unbind_work), GFP_KERNEL);
+		if (unbind_work) {
+			unbind_work->dev = dev;
+			get_device(dev);
+			init_task_work(&unbind_work->twork, unbind_work_fn);
+			task_work_add(current, &unbind_work->twork, true);
+
+			err = count;
+		} else {
+			err = -ENOMEM;
+		}
 	}
 	put_device(dev);
 	bus_put(bus);
-- 
2.7.4

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply related	[flat|nested] 103+ messages in thread

* [PATCH v9 04/39] component: alloc component_match without any comp to match
  2018-12-13  4:01 [PATCH v9 00/39] drm/i915: Implement HDCP2.2 Ramalingam C
                   ` (2 preceding siblings ...)
  2018-12-13  4:01 ` [PATCH v9 03/39] drivers/base: use a worker for sysfs unbind Ramalingam C
@ 2018-12-13  4:01 ` Ramalingam C
  2018-12-19 13:42   ` Daniel Vetter
  2018-12-13  4:01 ` [PATCH v9 05/39] drm/i915: component master at i915 driver load Ramalingam C
                   ` (38 subsequent siblings)
  42 siblings, 1 reply; 103+ messages in thread
From: Ramalingam C @ 2018-12-13  4:01 UTC (permalink / raw)
  To: intel-gfx, dri-devel, seanpaul, daniel.vetter, tomas.winkler,
	uma.shankar
  Cc: ville.syrjala, chris, Ramalingam C, Greg Kroah-Hartman,
	Kate Stewart, Thomas Gleixner, Philippe Ombredanne, linux-kernel

If all the components associated to a component master is not added
to the component framework due to the HW capability or Kconfig
selection, component_match will be NULL at
component_master_add_with_match().

To avoid this, component_match_alloc() is added to the framework,
to allcoate the struct component_match with zero associated components.
Hence component master can be added with a component_match with zero
associated components.

This helps the component master bind call to get triggered,
even if no component is registered for that particular master.

This is meant for big PCI device drivers where small/optional
features are external components, and based on usecases different
combination of components are build as entire driver.

In such PCI device driver Load, if we use the component master for
waiting for few  components(features) availability, only if they are
supported by the underlying HW, then we need to allocate memory for
component_match using the API introduced in this change before
the call to component_master_add_with_match.

v2:
  No Change.

Signed-off-by: Ramalingam C <ramalingam.c@intel.com>
Suggested-by: Daniel Vetter <daniel.vetter@ffwll.ch>
Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Cc: Kate Stewart <kstewart@linuxfoundation.org>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: Philippe Ombredanne <pombredanne@nexb.com>
Cc: linux-kernel@vger.kernel.org
---
 drivers/base/component.c  | 30 ++++++++++++++++++++++++++++++
 include/linux/component.h |  2 ++
 2 files changed, 32 insertions(+)

diff --git a/drivers/base/component.c b/drivers/base/component.c
index e8d676fad0c9..0ab36b2255ea 100644
--- a/drivers/base/component.c
+++ b/drivers/base/component.c
@@ -312,6 +312,36 @@ static int component_match_realloc(struct device *dev,
 }
 
 /*
+ * Allocate the match without any component_match_array elements.
+ *
+ * This function is useful when the component master might end up
+ * registering itself without any matching components.
+ */
+void component_match_alloc(struct device *master,
+	struct component_match **matchptr)
+{
+	struct component_match *match = *matchptr;
+
+	if (IS_ERR(match))
+		return;
+
+	if (match)
+		return;
+
+	match = devres_alloc(devm_component_match_release,
+			     sizeof(*match), GFP_KERNEL);
+	if (!match) {
+		*matchptr = ERR_PTR(-ENOMEM);
+		return;
+	}
+
+	devres_add(master, match);
+
+	*matchptr = match;
+}
+EXPORT_SYMBOL(component_match_alloc);
+
+/*
  * Add a component to be matched, with a release function.
  *
  * The match array is first created or extended if necessary.
diff --git a/include/linux/component.h b/include/linux/component.h
index e71fbbbc74e2..3f6b420a58f8 100644
--- a/include/linux/component.h
+++ b/include/linux/component.h
@@ -37,6 +37,8 @@ void component_match_add_release(struct device *master,
 	struct component_match **matchptr,
 	void (*release)(struct device *, void *),
 	int (*compare)(struct device *, void *), void *compare_data);
+void component_match_alloc(struct device *master,
+	struct component_match **matchptr);
 
 static inline void component_match_add(struct device *master,
 	struct component_match **matchptr,
-- 
2.7.4


^ permalink raw reply related	[flat|nested] 103+ messages in thread

* [PATCH v9 05/39] drm/i915: component master at i915 driver load
  2018-12-13  4:01 [PATCH v9 00/39] drm/i915: Implement HDCP2.2 Ramalingam C
                   ` (3 preceding siblings ...)
  2018-12-13  4:01 ` [PATCH v9 04/39] component: alloc component_match without any comp to match Ramalingam C
@ 2018-12-13  4:01 ` Ramalingam C
  2018-12-19 13:45   ` Daniel Vetter
  2018-12-13  4:01 ` [PATCH v9 06/39] drm/i915: Initialize HDCP2.2 Ramalingam C
                   ` (37 subsequent siblings)
  42 siblings, 1 reply; 103+ messages in thread
From: Ramalingam C @ 2018-12-13  4:01 UTC (permalink / raw)
  To: intel-gfx, dri-devel, seanpaul, daniel.vetter, tomas.winkler,
	uma.shankar

A generic component master is added to hold the i915 registration
until all required kernel modules are up and active.

This is achieved through following steps:
  - moving the i915 driver registration to the component master's
    bind call
  - all required kernel modules will add one component each to
    component_match of I915 component master.

If no component is added to the I915 component master, due to CONFIG
selection or HW limitation, component master's bind call (i915
registration) will be triggered with no wait.

Similarly when a associated component is removed for some reasons,
I915 will be unregistered through component master unbind.

v2:
  i915_driver_unregister is added to the unbind of master.
v3:
  In master_unbind i915_unregister->drm_atomic_helper_shutdown->
	component_unbind_all [Daniel]

Signed-off-by: Ramalingam C <ramalingam.c@intel.com>
Suggested-by: Daniel Vetter <daniel.vetter@ffwll.ch>
---
 drivers/gpu/drm/i915/i915_drv.c | 86 +++++++++++++++++++++++++++++++++++++----
 drivers/gpu/drm/i915/i915_drv.h |  3 ++
 include/drm/i915_component.h    | 11 ++++++
 3 files changed, 92 insertions(+), 8 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c
index b310a897a4ad..b8a204072e60 100644
--- a/drivers/gpu/drm/i915/i915_drv.c
+++ b/drivers/gpu/drm/i915/i915_drv.c
@@ -39,12 +39,14 @@
 #include <linux/vgaarb.h>
 #include <linux/vga_switcheroo.h>
 #include <linux/vt.h>
+#include <linux/component.h>
 #include <acpi/video.h>
 
 #include <drm/drmP.h>
 #include <drm/drm_crtc_helper.h>
 #include <drm/drm_atomic_helper.h>
 #include <drm/i915_drm.h>
+#include <drm/i915_component.h>
 
 #include "i915_drv.h"
 #include "i915_trace.h"
@@ -1577,8 +1579,6 @@ static void i915_driver_register(struct drm_i915_private *dev_priv)
 	if (IS_GEN5(dev_priv))
 		intel_gpu_ips_init(dev_priv);
 
-	intel_audio_init(dev_priv);
-
 	/*
 	 * Some ports require correctly set-up hpd registers for detection to
 	 * work properly (leading to ghost connected connector status), e.g. VGA
@@ -1609,7 +1609,6 @@ static void i915_driver_unregister(struct drm_i915_private *dev_priv)
 	intel_power_domains_disable(dev_priv);
 
 	intel_fbdev_unregister(dev_priv);
-	intel_audio_deinit(dev_priv);
 
 	/*
 	 * After flushing the fbdev (incl. a late async config which will
@@ -1694,6 +1693,48 @@ static void i915_driver_destroy(struct drm_i915_private *i915)
 	pci_set_drvdata(pdev, NULL);
 }
 
+static void i915_driver_load_tail(struct drm_i915_private *dev_priv)
+{
+	i915_driver_register(dev_priv);
+
+	DRM_INFO("load_tail: I915 driver registered\n");
+}
+
+static void i915_driver_unload_head(struct drm_i915_private *dev_priv)
+{
+	i915_driver_unregister(dev_priv);
+
+	DRM_INFO("unload_head: I915 driver unregistered\n");
+}
+
+static int i915_component_master_bind(struct device *dev)
+{
+	struct drm_i915_private *dev_priv = kdev_to_i915(dev);
+	int ret;
+
+	ret = component_bind_all(dev, dev_priv->comp_master);
+	if (ret < 0)
+		return ret;
+
+	i915_driver_load_tail(dev_priv);
+
+	return 0;
+}
+
+static void i915_component_master_unbind(struct device *dev)
+{
+	struct drm_i915_private *dev_priv = kdev_to_i915(dev);
+
+	i915_driver_unload_head(dev_priv);
+	drm_atomic_helper_shutdown(&dev_priv->drm);
+	component_unbind_all(dev, dev_priv->comp_master);
+}
+
+static const struct component_master_ops i915_component_master_ops = {
+	.bind = i915_component_master_bind,
+	.unbind = i915_component_master_unbind,
+};
+
 /**
  * i915_driver_load - setup chip and create an initial config
  * @pdev: PCI device
@@ -1720,9 +1761,22 @@ int i915_driver_load(struct pci_dev *pdev, const struct pci_device_id *ent)
 	if (!i915_modparams.nuclear_pageflip && match_info->gen < 5)
 		dev_priv->drm.driver_features &= ~DRIVER_ATOMIC;
 
+	dev_priv->comp_master = kzalloc(sizeof(*dev_priv->comp_master),
+					GFP_KERNEL);
+	if (!dev_priv->comp_master) {
+		ret = -ENOMEM;
+		goto out_fini;
+	}
+
+	component_match_alloc(dev_priv->drm.dev, &dev_priv->master_match);
+	if (!dev_priv->master_match) {
+		ret = -ENOMEM;
+		goto out_comp_master_clean;
+	}
+
 	ret = pci_enable_device(pdev);
 	if (ret)
-		goto out_fini;
+		goto out_comp_master_clean;
 
 	ret = i915_driver_init_early(dev_priv);
 	if (ret < 0)
@@ -1742,14 +1796,27 @@ int i915_driver_load(struct pci_dev *pdev, const struct pci_device_id *ent)
 	if (ret < 0)
 		goto out_cleanup_hw;
 
-	i915_driver_register(dev_priv);
+	ret = component_master_add_with_match(dev_priv->drm.dev,
+					      &i915_component_master_ops,
+					      dev_priv->master_match);
+	if (ret < 0) {
+		DRM_DEV_ERROR(&pdev->dev, "Master comp add failed %d\n",
+			      ret);
+		goto out_cleanup_modeset;
+	}
+
+	intel_audio_init(dev_priv);
 
 	enable_rpm_wakeref_asserts(dev_priv);
 
 	i915_welcome_messages(dev_priv);
 
+	DRM_INFO("I915 registration waits for req component(s). if any...\n");
+
 	return 0;
 
+out_cleanup_modeset:
+	intel_modeset_cleanup(&dev_priv->drm);
 out_cleanup_hw:
 	i915_driver_cleanup_hw(dev_priv);
 out_cleanup_mmio:
@@ -1759,6 +1826,8 @@ int i915_driver_load(struct pci_dev *pdev, const struct pci_device_id *ent)
 	i915_driver_cleanup_early(dev_priv);
 out_pci_disable:
 	pci_disable_device(pdev);
+out_comp_master_clean:
+	kfree(dev_priv->comp_master);
 out_fini:
 	i915_load_error(dev_priv, "Device initialization failed (%d)\n", ret);
 	i915_driver_destroy(dev_priv);
@@ -1772,13 +1841,14 @@ void i915_driver_unload(struct drm_device *dev)
 
 	disable_rpm_wakeref_asserts(dev_priv);
 
-	i915_driver_unregister(dev_priv);
+	component_master_del(dev_priv->drm.dev, &i915_component_master_ops);
+	kfree(dev_priv->comp_master);
+
+	intel_audio_deinit(dev_priv);
 
 	if (i915_gem_suspend(dev_priv))
 		DRM_ERROR("failed to idle hardware; continuing to unload!\n");
 
-	drm_atomic_helper_shutdown(dev);
-
 	intel_gvt_cleanup(dev_priv);
 
 	intel_modeset_cleanup(dev);
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index e70707e79386..25dc3d7a1e3b 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -2002,6 +2002,9 @@ struct drm_i915_private {
 
 	struct i915_pmu pmu;
 
+	struct i915_component_master *comp_master;
+	struct component_match *master_match;
+
 	/*
 	 * NOTE: This is the dri1/ums dungeon, don't add stuff here. Your patch
 	 * will be rejected. Instead look for a better place.
diff --git a/include/drm/i915_component.h b/include/drm/i915_component.h
index fca22d463e1b..6f94ddd3f2c2 100644
--- a/include/drm/i915_component.h
+++ b/include/drm/i915_component.h
@@ -46,4 +46,15 @@ struct i915_audio_component {
 	int aud_sample_rate[MAX_PORTS];
 };
 
+/**
+ * struct i915_component_master - Used for communication between i915
+ *				  and any other drivers for the services
+ *				  of different feature.
+ */
+struct i915_component_master {
+	/*
+	 * Add here the interface details between I915 and interested modules.
+	 */
+};
+
 #endif /* _I915_COMPONENT_H_ */
-- 
2.7.4

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply related	[flat|nested] 103+ messages in thread

* [PATCH v9 06/39] drm/i915: Initialize HDCP2.2
  2018-12-13  4:01 [PATCH v9 00/39] drm/i915: Implement HDCP2.2 Ramalingam C
                   ` (4 preceding siblings ...)
  2018-12-13  4:01 ` [PATCH v9 05/39] drm/i915: component master at i915 driver load Ramalingam C
@ 2018-12-13  4:01 ` Ramalingam C
  2018-12-19 13:45   ` Daniel Vetter
  2018-12-13  4:01 ` [PATCH v9 07/39] drm/i915: MEI interface definition Ramalingam C
                   ` (36 subsequent siblings)
  42 siblings, 1 reply; 103+ messages in thread
From: Ramalingam C @ 2018-12-13  4:01 UTC (permalink / raw)
  To: intel-gfx, dri-devel, seanpaul, daniel.vetter, tomas.winkler,
	uma.shankar

Add the HDCP2.2 initialization to the existing HDCP1.4 stack.

v2:
  mei interface handle is protected with mutex. [Chris Wilson]
v3:
  Notifiers are used for the mei interface state.
v4:
  Poll for mei client device state
  Error msg for out of mem [Uma]
  Inline req for init function removed [Uma]
v5:
  Rebase as Part of reordering.
  Component is used for the I915 and MEI_HDCP interface [Daniel]
v6:
  HDCP2.2 uses the I915 component master to communicate with mei_hdcp
	- [Daniel]
  Required HDCP2.2 variables defined [Sean Paul]
v7:
  intel_hdcp2.2_init returns void [Uma]
  Realigning the codes.
v8:
  Avoid using bool structure members.
  MEI interface related changes are moved into separate patch.
  Commit msg is updated accordingly.
  intel_hdcp_exit is defined and used from i915_unload
v9:
  Movement of the hdcp_check_link is moved to new patch [Daniel]
  intel_hdcp2_exit is removed as mei_comp will be unbind in i915_unload.

Signed-off-by: Ramalingam C <ramalingam.c@intel.com>
---
 drivers/gpu/drm/i915/intel_dp.c   |  3 ++-
 drivers/gpu/drm/i915/intel_drv.h  | 15 ++++++++++++++-
 drivers/gpu/drm/i915/intel_hdcp.c | 30 +++++++++++++++++++++++++++---
 drivers/gpu/drm/i915/intel_hdmi.c |  2 +-
 4 files changed, 44 insertions(+), 6 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
index e94faa0a42eb..aba884c64879 100644
--- a/drivers/gpu/drm/i915/intel_dp.c
+++ b/drivers/gpu/drm/i915/intel_dp.c
@@ -6902,7 +6902,8 @@ intel_dp_init_connector(struct intel_digital_port *intel_dig_port,
 	intel_dp_add_properties(intel_dp, connector);
 
 	if (is_hdcp_supported(dev_priv, port) && !intel_dp_is_edp(intel_dp)) {
-		int ret = intel_hdcp_init(intel_connector, &intel_dp_hdcp_shim);
+		int ret = intel_hdcp_init(intel_connector, &intel_dp_hdcp_shim,
+					  false);
 		if (ret)
 			DRM_DEBUG_KMS("HDCP init failed, skipping.\n");
 	}
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index d08f08f607dd..dd9371647a8c 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -388,6 +388,17 @@ struct intel_hdcp {
 	u64 value;
 	struct delayed_work check_work;
 	struct work_struct prop_work;
+
+	/* HDCP2.2 related definitions */
+	/* Flag indicates whether this connector supports HDCP2.2 or not. */
+	u8 hdcp2_supported;
+
+	/*
+	 * Content Stream Type defined by content owner. TYPE0(0x0) content can
+	 * flow in the link protected by HDCP2.2 or HDCP1.4, where as TYPE1(0x1)
+	 * content can flow only through a link protected by HDCP2.2.
+	 */
+	u8 content_type;
 };
 
 struct intel_connector {
@@ -2038,12 +2049,14 @@ void intel_hdcp_atomic_check(struct drm_connector *connector,
 			     struct drm_connector_state *old_state,
 			     struct drm_connector_state *new_state);
 int intel_hdcp_init(struct intel_connector *connector,
-		    const struct intel_hdcp_shim *hdcp_shim);
+		    const struct intel_hdcp_shim *hdcp_shim,
+		    bool hdcp2_supported);
 int intel_hdcp_enable(struct intel_connector *connector);
 int intel_hdcp_disable(struct intel_connector *connector);
 int intel_hdcp_check_link(struct intel_connector *connector);
 bool is_hdcp_supported(struct drm_i915_private *dev_priv, enum port port);
 bool intel_hdcp_capable(struct intel_connector *connector);
+bool is_hdcp2_supported(struct drm_i915_private *dev_priv);
 
 /* intel_psr.c */
 #define CAN_PSR(dev_priv) (HAS_PSR(dev_priv) && dev_priv->psr.sink_support)
diff --git a/drivers/gpu/drm/i915/intel_hdcp.c b/drivers/gpu/drm/i915/intel_hdcp.c
index 506b4cc6f46b..584d27f3c699 100644
--- a/drivers/gpu/drm/i915/intel_hdcp.c
+++ b/drivers/gpu/drm/i915/intel_hdcp.c
@@ -833,14 +833,34 @@ bool is_hdcp_supported(struct drm_i915_private *dev_priv, enum port port)
 	return INTEL_GEN(dev_priv) >= 9 && port < PORT_E;
 }
 
+bool is_hdcp2_supported(struct drm_i915_private *dev_priv)
+{
+	return ((INTEL_GEN(dev_priv) >= 10 || IS_GEMINILAKE(dev_priv) ||
+		 IS_KABYLAKE(dev_priv)) && IS_ENABLED(CONFIG_INTEL_MEI_HDCP));
+}
+
+static void intel_hdcp2_init(struct intel_connector *connector)
+{
+	struct drm_i915_private *dev_priv = to_i915(connector->base.dev);
+	struct intel_hdcp *hdcp = &connector->hdcp;
+
+	WARN_ON(!is_hdcp2_supported(dev_priv));
+
+	/* TODO: MEI interface needs to be initialized here */
+	hdcp->hdcp2_supported = 1;
+}
+
 int intel_hdcp_init(struct intel_connector *connector,
-		    const struct intel_hdcp_shim *shim)
+		    const struct intel_hdcp_shim *shim,
+		    bool hdcp2_supported)
 {
 	struct intel_hdcp *hdcp = &connector->hdcp;
 	int ret;
 
-	ret = drm_connector_attach_content_protection_property(
-			&connector->base);
+	if (!shim)
+		return -EINVAL;
+
+	ret = drm_connector_attach_content_protection_property(&connector->base);
 	if (ret)
 		return ret;
 
@@ -848,6 +868,10 @@ int intel_hdcp_init(struct intel_connector *connector,
 	mutex_init(&hdcp->mutex);
 	INIT_DELAYED_WORK(&hdcp->check_work, intel_hdcp_check_work);
 	INIT_WORK(&hdcp->prop_work, intel_hdcp_prop_work);
+
+	if (hdcp2_supported)
+		intel_hdcp2_init(connector);
+
 	return 0;
 }
 
diff --git a/drivers/gpu/drm/i915/intel_hdmi.c b/drivers/gpu/drm/i915/intel_hdmi.c
index 07e803a604bd..38fe0fdbf8d8 100644
--- a/drivers/gpu/drm/i915/intel_hdmi.c
+++ b/drivers/gpu/drm/i915/intel_hdmi.c
@@ -2434,7 +2434,7 @@ void intel_hdmi_init_connector(struct intel_digital_port *intel_dig_port,
 
 	if (is_hdcp_supported(dev_priv, port)) {
 		int ret = intel_hdcp_init(intel_connector,
-					  &intel_hdmi_hdcp_shim);
+					  &intel_hdmi_hdcp_shim, false);
 		if (ret)
 			DRM_DEBUG_KMS("HDCP init failed, skipping.\n");
 	}
-- 
2.7.4

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply related	[flat|nested] 103+ messages in thread

* [PATCH v9 07/39] drm/i915: MEI interface definition
  2018-12-13  4:01 [PATCH v9 00/39] drm/i915: Implement HDCP2.2 Ramalingam C
                   ` (5 preceding siblings ...)
  2018-12-13  4:01 ` [PATCH v9 06/39] drm/i915: Initialize HDCP2.2 Ramalingam C
@ 2018-12-13  4:01 ` Ramalingam C
  2018-12-19 14:00   ` Daniel Vetter
  2018-12-13  4:01 ` [PATCH v9 08/39] drm/i915: hdcp1.4 CP_IRQ handling and SW encryption tracking Ramalingam C
                   ` (35 subsequent siblings)
  42 siblings, 1 reply; 103+ messages in thread
From: Ramalingam C @ 2018-12-13  4:01 UTC (permalink / raw)
  To: intel-gfx, dri-devel, seanpaul, daniel.vetter, tomas.winkler,
	uma.shankar

Defining the mei-i915 interface functions and initialization of
the interface.

v2:
  Adjust to the new interface changes. [Tomas]
  Added further debug logs for the failures at MEI i/f.
  port in hdcp_port data is equipped to handle -ve values.
v3:
  mei comp is matched for global i915 comp master. [Daniel]
  In hdcp_shim hdcp_protocol() is replaced with const variable. [Daniel]
  mei wrappers are adjusted as per the i/f change [Daniel]

Signed-off-by: Ramalingam C <ramalingam.c@intel.com>
---
 drivers/gpu/drm/i915/intel_drv.h  |   5 +
 drivers/gpu/drm/i915/intel_hdcp.c | 248 +++++++++++++++++++++++++++++++++++++-
 include/drm/i915_component.h      |   7 ++
 3 files changed, 259 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index dd9371647a8c..191b6e0f086c 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -39,6 +39,7 @@
 #include <drm/drm_dp_mst_helper.h>
 #include <drm/drm_rect.h>
 #include <drm/drm_atomic.h>
+#include <drm/i915_mei_hdcp_interface.h>
 #include <media/cec-notifier.h>
 
 /**
@@ -379,6 +380,9 @@ struct intel_hdcp_shim {
 	/* Detects panel's hdcp capability. This is optional for HDMI. */
 	int (*hdcp_capable)(struct intel_digital_port *intel_dig_port,
 			    bool *hdcp_capable);
+
+	/* HDCP adaptation(DP/HDMI) required on the port */
+	enum hdcp_wired_protocol protocol;
 };
 
 struct intel_hdcp {
@@ -399,6 +403,7 @@ struct intel_hdcp {
 	 * content can flow only through a link protected by HDCP2.2.
 	 */
 	u8 content_type;
+	struct hdcp_port_data port_data;
 };
 
 struct intel_connector {
diff --git a/drivers/gpu/drm/i915/intel_hdcp.c b/drivers/gpu/drm/i915/intel_hdcp.c
index 584d27f3c699..9405fce07b93 100644
--- a/drivers/gpu/drm/i915/intel_hdcp.c
+++ b/drivers/gpu/drm/i915/intel_hdcp.c
@@ -8,8 +8,10 @@
 
 #include <drm/drmP.h>
 #include <drm/drm_hdcp.h>
+#include <drm/i915_component.h>
 #include <linux/i2c.h>
 #include <linux/random.h>
+#include <linux/component.h>
 
 #include "intel_drv.h"
 #include "i915_reg.h"
@@ -833,6 +835,232 @@ bool is_hdcp_supported(struct drm_i915_private *dev_priv, enum port port)
 	return INTEL_GEN(dev_priv) >= 9 && port < PORT_E;
 }
 
+static __attribute__((unused)) int
+hdcp2_prepare_ake_init(struct intel_connector *connector,
+		       struct hdcp2_ake_init *ake_data)
+{
+	struct hdcp_port_data *data = &connector->hdcp.port_data;
+	struct drm_i915_private *dev_priv = to_i915(connector->base.dev);
+	struct i915_component_master *comp = dev_priv->comp_master;
+	int ret;
+
+	/* During the connector init encoder might not be initialized */
+	if (data->port == PORT_NONE)
+		data->port = connector->encoder->port;
+
+	ret = comp->hdcp_ops->initiate_hdcp2_session(comp->mei_dev,
+						     data, ake_data);
+	if (ret)
+		DRM_DEBUG_KMS("Prepare_ake_init failed. %d\n", ret);
+
+	return ret;
+}
+
+static __attribute__((unused)) int
+hdcp2_verify_rx_cert_prepare_km(struct intel_connector *connector,
+				struct hdcp2_ake_send_cert *rx_cert,
+				bool *paired,
+				struct hdcp2_ake_no_stored_km *ek_pub_km,
+				size_t *msg_sz)
+{
+	struct hdcp_port_data *data = &connector->hdcp.port_data;
+	struct drm_i915_private *dev_priv = to_i915(connector->base.dev);
+	struct i915_component_master *comp = dev_priv->comp_master;
+	int ret;
+
+	ret = comp->hdcp_ops->verify_receiver_cert_prepare_km(comp->mei_dev,
+							      data, rx_cert,
+							      paired, ek_pub_km,
+							      msg_sz);
+	if (ret < 0)
+		DRM_DEBUG_KMS("Verify rx_cert failed. %d\n", ret);
+
+	return ret;
+}
+
+static __attribute__((unused)) int
+hdcp2_verify_hprime(struct intel_connector *connector,
+		    struct hdcp2_ake_send_hprime *rx_hprime)
+{
+	struct hdcp_port_data *data = &connector->hdcp.port_data;
+	struct drm_i915_private *dev_priv = to_i915(connector->base.dev);
+	struct i915_component_master *comp = dev_priv->comp_master;
+	int ret;
+
+	ret = comp->hdcp_ops->verify_hprime(comp->mei_dev, data, rx_hprime);
+	if (ret < 0)
+		DRM_DEBUG_KMS("Verify hprime failed. %d\n", ret);
+
+	return ret;
+}
+
+static __attribute__((unused)) int
+hdcp2_store_pairing_info(struct intel_connector *connector,
+			 struct hdcp2_ake_send_pairing_info *pairing_info)
+{
+	struct hdcp_port_data *data = &connector->hdcp.port_data;
+	struct drm_i915_private *dev_priv = to_i915(connector->base.dev);
+	struct i915_component_master *comp = dev_priv->comp_master;
+	int ret;
+
+	ret = comp->hdcp_ops->store_pairing_info(comp->mei_dev, data,
+						 pairing_info);
+	if (ret < 0)
+		DRM_DEBUG_KMS("Store pairing info failed. %d\n", ret);
+
+	return ret;
+}
+
+static __attribute__((unused)) int
+hdcp2_prepare_lc_init(struct intel_connector *connector,
+		      struct hdcp2_lc_init *lc_init)
+{
+	struct hdcp_port_data *data = &connector->hdcp.port_data;
+	struct drm_i915_private *dev_priv = to_i915(connector->base.dev);
+	struct i915_component_master *comp = dev_priv->comp_master;
+	int ret;
+
+	ret = comp->hdcp_ops->initiate_locality_check(comp->mei_dev, data,
+						      lc_init);
+	if (ret < 0)
+		DRM_DEBUG_KMS("Prepare lc_init failed. %d\n", ret);
+
+	return ret;
+}
+
+static __attribute__((unused)) int
+hdcp2_verify_lprime(struct intel_connector *connector,
+		    struct hdcp2_lc_send_lprime *rx_lprime)
+{
+	struct hdcp_port_data *data = &connector->hdcp.port_data;
+	struct drm_i915_private *dev_priv = to_i915(connector->base.dev);
+	struct i915_component_master *comp = dev_priv->comp_master;
+	int ret;
+
+	ret = comp->hdcp_ops->verify_lprime(comp->mei_dev, data, rx_lprime);
+	if (ret < 0)
+		DRM_DEBUG_KMS("Verify L_Prime failed. %d\n", ret);
+
+	return ret;
+}
+
+static __attribute__((unused))
+int hdcp2_prepare_skey(struct intel_connector *connector,
+		       struct hdcp2_ske_send_eks *ske_data)
+{
+	struct hdcp_port_data *data = &connector->hdcp.port_data;
+	struct drm_i915_private *dev_priv = to_i915(connector->base.dev);
+	struct i915_component_master *comp = dev_priv->comp_master;
+	int ret;
+
+	ret = comp->hdcp_ops->get_session_key(comp->mei_dev, data, ske_data);
+	if (ret < 0)
+		DRM_DEBUG_KMS("Get session key failed. %d\n", ret);
+
+	return ret;
+}
+
+static __attribute__((unused)) int
+hdcp2_verify_rep_topology_prepare_ack(struct intel_connector *connector,
+				      struct hdcp2_rep_send_receiverid_list
+								*rep_topology,
+				      struct hdcp2_rep_send_ack *rep_send_ack)
+{
+	struct hdcp_port_data *data = &connector->hdcp.port_data;
+	struct drm_i915_private *dev_priv = to_i915(connector->base.dev);
+	struct i915_component_master *comp = dev_priv->comp_master;
+	int ret;
+
+	ret = comp->hdcp_ops->repeater_check_flow_prepare_ack(comp->mei_dev,
+							      data,
+							      rep_topology,
+							      rep_send_ack);
+	if (ret < 0)
+		DRM_DEBUG_KMS("Verify rep topology failed. %d\n", ret);
+
+	return ret;
+}
+
+static __attribute__((unused)) int
+hdcp2_verify_mprime(struct intel_connector *connector,
+		    struct hdcp2_rep_stream_ready *stream_ready)
+{
+	struct hdcp_port_data *data = &connector->hdcp.port_data;
+	struct drm_i915_private *dev_priv = to_i915(connector->base.dev);
+	struct i915_component_master *comp = dev_priv->comp_master;
+	int ret;
+
+	ret = comp->hdcp_ops->verify_mprime(comp->mei_dev, data, stream_ready);
+	if (ret < 0)
+		DRM_DEBUG_KMS("Verify mprime failed. %d\n", ret);
+
+	return ret;
+}
+
+static __attribute__((unused))
+int hdcp2_authenticate_port(struct intel_connector *connector)
+{
+	struct hdcp_port_data *data = &connector->hdcp.port_data;
+	struct drm_i915_private *dev_priv = to_i915(connector->base.dev);
+	struct i915_component_master *comp = dev_priv->comp_master;
+	int ret;
+
+	ret = comp->hdcp_ops->enable_hdcp_authentication(comp->mei_dev, data);
+	if (ret < 0)
+		DRM_DEBUG_KMS("Enable hdcp auth failed. %d\n", ret);
+
+	return ret;
+}
+
+static __attribute__((unused))
+int hdcp2_close_mei_session(struct intel_connector *connector)
+{
+	struct drm_i915_private *dev_priv = to_i915(connector->base.dev);
+	struct i915_component_master *comp = dev_priv->comp_master;
+
+	return comp->hdcp_ops->close_hdcp_session(comp->mei_dev,
+						  &connector->hdcp.port_data);
+}
+
+static __attribute__((unused))
+int hdcp2_deauthenticate_port(struct intel_connector *connector)
+{
+	return hdcp2_close_mei_session(connector);
+}
+
+static int i915_hdcp_component_match(struct device *dev, void *data)
+{
+	return !strcmp(dev->driver->name, "mei_hdcp");
+}
+
+static int initialize_hdcp_port_data(struct intel_connector *connector)
+{
+	struct intel_hdcp *hdcp = &connector->hdcp;
+	struct hdcp_port_data *data = &hdcp->port_data;
+
+	data->port = PORT_NONE;
+	if (connector->encoder)
+		data->port = connector->encoder->port;
+
+	data->port_type = (u8)HDCP_PORT_TYPE_INTEGRATED;
+	data->protocol = (u8)hdcp->shim->protocol;
+
+	data->k = 1;
+	if (!data->streams)
+		data->streams = kcalloc(data->k,
+					sizeof(struct hdcp2_streamid_type),
+					GFP_KERNEL);
+	if (!data->streams) {
+		DRM_ERROR("Out of Memory\n");
+		return -ENOMEM;
+	}
+
+	data->streams[0].stream_id = 0;
+	data->streams[0].stream_type = hdcp->content_type;
+
+	return 0;
+}
+
 bool is_hdcp2_supported(struct drm_i915_private *dev_priv)
 {
 	return ((INTEL_GEN(dev_priv) >= 10 || IS_GEMINILAKE(dev_priv) ||
@@ -843,10 +1071,28 @@ static void intel_hdcp2_init(struct intel_connector *connector)
 {
 	struct drm_i915_private *dev_priv = to_i915(connector->base.dev);
 	struct intel_hdcp *hdcp = &connector->hdcp;
+	static bool comp_match_added;
+	int ret;
 
 	WARN_ON(!is_hdcp2_supported(dev_priv));
 
-	/* TODO: MEI interface needs to be initialized here */
+	ret = initialize_hdcp_port_data(connector);
+	if (ret) {
+		DRM_DEBUG_KMS("Mei hdcp data init failed\n");
+		return;
+	}
+
+	/*
+	 * Component for mei is common across the connector.
+	 * Adding the match once is sufficient.
+	 * TODO: Instead of static bool, do we need flag in dev_priv?.
+	 */
+	if (!comp_match_added) {
+		component_match_add(dev_priv->drm.dev, &dev_priv->master_match,
+				    i915_hdcp_component_match, dev_priv);
+		comp_match_added = true;
+	}
+
 	hdcp->hdcp2_supported = 1;
 }
 
diff --git a/include/drm/i915_component.h b/include/drm/i915_component.h
index 6f94ddd3f2c2..7a7201374cfe 100644
--- a/include/drm/i915_component.h
+++ b/include/drm/i915_component.h
@@ -24,6 +24,8 @@
 #ifndef _I915_COMPONENT_H_
 #define _I915_COMPONENT_H_
 
+#include <drm/i915_mei_hdcp_interface.h>
+
 #include "drm_audio_component.h"
 
 /* MAX_PORT is the number of port
@@ -50,8 +52,13 @@ struct i915_audio_component {
  * struct i915_component_master - Used for communication between i915
  *				  and any other drivers for the services
  *				  of different feature.
+ * @mei_dev: device that provide the HDCP2.2 service from MEI Bus.
+ * @hdcp_ops: Ops implemented by mei_hdcp driver, used by i915 driver.
  */
 struct i915_component_master {
+	struct device *mei_dev;
+	const struct i915_hdcp_component_ops *hdcp_ops;
+
 	/*
 	 * Add here the interface details between I915 and interested modules.
 	 */
-- 
2.7.4

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply related	[flat|nested] 103+ messages in thread

* [PATCH v9 08/39] drm/i915: hdcp1.4 CP_IRQ handling and SW encryption tracking
  2018-12-13  4:01 [PATCH v9 00/39] drm/i915: Implement HDCP2.2 Ramalingam C
                   ` (6 preceding siblings ...)
  2018-12-13  4:01 ` [PATCH v9 07/39] drm/i915: MEI interface definition Ramalingam C
@ 2018-12-13  4:01 ` Ramalingam C
  2018-12-19 15:48   ` Daniel Vetter
  2018-12-13  4:01 ` [PATCH v9 09/39] drm/i915: Enable and Disable of HDCP2.2 Ramalingam C
                   ` (34 subsequent siblings)
  42 siblings, 1 reply; 103+ messages in thread
From: Ramalingam C @ 2018-12-13  4:01 UTC (permalink / raw)
  To: intel-gfx, dri-devel, seanpaul, daniel.vetter, tomas.winkler,
	uma.shankar

"hdcp_encrypted" flag is defined to denote the HDCP1.4 encryption status.
This SW tracking is used to determine the need for real hdcp1.4 disable
and hdcp_check_link upon CP_IRQ.

On CP_IRQ we filter the CP_IRQ related to the states like Link failure
and reauthentication req etc and handle them in hdcp_check_link.
CP_IRQ corresponding to the authentication msg availability are ignored.

WARN_ON is added for the abrupt stop of HDCP encryption of a port.

Signed-off-by: Ramalingam C <ramalingam.c@intel.com>
---
 drivers/gpu/drm/i915/intel_dp.c   |  2 +-
 drivers/gpu/drm/i915/intel_drv.h  |  5 ++-
 drivers/gpu/drm/i915/intel_hdcp.c | 89 ++++++++++++++++++++++++++++++---------
 3 files changed, 74 insertions(+), 22 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
index aba884c64879..89315e15fb34 100644
--- a/drivers/gpu/drm/i915/intel_dp.c
+++ b/drivers/gpu/drm/i915/intel_dp.c
@@ -4758,7 +4758,7 @@ static void intel_dp_check_service_irq(struct intel_dp *intel_dp)
 		intel_dp_handle_test_request(intel_dp);
 
 	if (val & DP_CP_IRQ)
-		intel_hdcp_check_link(intel_dp->attached_connector);
+		intel_hdcp_handle_cp_irq(intel_dp->attached_connector);
 
 	if (val & DP_SINK_SPECIFIC_IRQ)
 		DRM_DEBUG_DRIVER("Sink specific irq unhandled\n");
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index 191b6e0f086c..decd0346c6a7 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -393,6 +393,9 @@ struct intel_hdcp {
 	struct delayed_work check_work;
 	struct work_struct prop_work;
 
+	/* HDCP1.4 Encryption status */
+	u8 hdcp_encrypted;
+
 	/* HDCP2.2 related definitions */
 	/* Flag indicates whether this connector supports HDCP2.2 or not. */
 	u8 hdcp2_supported;
@@ -2058,10 +2061,10 @@ int intel_hdcp_init(struct intel_connector *connector,
 		    bool hdcp2_supported);
 int intel_hdcp_enable(struct intel_connector *connector);
 int intel_hdcp_disable(struct intel_connector *connector);
-int intel_hdcp_check_link(struct intel_connector *connector);
 bool is_hdcp_supported(struct drm_i915_private *dev_priv, enum port port);
 bool intel_hdcp_capable(struct intel_connector *connector);
 bool is_hdcp2_supported(struct drm_i915_private *dev_priv);
+void intel_hdcp_handle_cp_irq(struct intel_connector *connector);
 
 /* intel_psr.c */
 #define CAN_PSR(dev_priv) (HAS_PSR(dev_priv) && dev_priv->psr.sink_support)
diff --git a/drivers/gpu/drm/i915/intel_hdcp.c b/drivers/gpu/drm/i915/intel_hdcp.c
index 9405fce07b93..2b7814a6f12b 100644
--- a/drivers/gpu/drm/i915/intel_hdcp.c
+++ b/drivers/gpu/drm/i915/intel_hdcp.c
@@ -75,6 +75,16 @@ bool intel_hdcp_capable(struct intel_connector *connector)
 	return capable;
 }
 
+static inline bool intel_hdcp_in_use(struct intel_connector *connector)
+{
+	struct drm_i915_private *dev_priv = to_i915(connector->base.dev);
+	enum port port = connector->encoder->port;
+	u32 reg;
+
+	reg = I915_READ(PORT_HDCP_STATUS(port));
+	return reg & HDCP_STATUS_ENC;
+}
+
 static int intel_hdcp_poll_ksv_fifo(struct intel_digital_port *intel_dig_port,
 				    const struct intel_hdcp_shim *shim)
 {
@@ -669,6 +679,7 @@ static int _intel_hdcp_disable(struct intel_connector *connector)
 	DRM_DEBUG_KMS("[%s:%d] HDCP is being disabled...\n",
 		      connector->base.name, connector->base.base.id);
 
+	hdcp->hdcp_encrypted = 0;
 	I915_WRITE(PORT_HDCP_CONF(port), 0);
 	if (intel_wait_for_register(dev_priv, PORT_HDCP_STATUS(port), ~0, 0,
 				    ENCRYPT_STATUS_CHANGE_TIMEOUT_MS)) {
@@ -714,8 +725,10 @@ static int _intel_hdcp_enable(struct intel_connector *connector)
 	/* Incase of authentication failures, HDCP spec expects reauth. */
 	for (i = 0; i < tries; i++) {
 		ret = intel_hdcp_auth(conn_to_dig_port(connector), hdcp->shim);
-		if (!ret)
+		if (!ret) {
+			hdcp->hdcp_encrypted = 1;
 			return 0;
+		}
 
 		DRM_DEBUG_KMS("HDCP Auth failure (%d)\n", ret);
 
@@ -742,16 +755,17 @@ int intel_hdcp_check_link(struct intel_connector *connector)
 	enum port port = intel_dig_port->base.port;
 	int ret = 0;
 
-	if (!hdcp->shim)
-		return -ENOENT;
-
 	mutex_lock(&hdcp->mutex);
 
-	if (hdcp->value == DRM_MODE_CONTENT_PROTECTION_UNDESIRED)
+	/* Check_link valid only when HDCP1.4 is enabled */
+	if (hdcp->value != DRM_MODE_CONTENT_PROTECTION_ENABLED ||
+	    !hdcp->hdcp_encrypted) {
+		ret = -EINVAL;
 		goto out;
+	}
 
-	if (!(I915_READ(PORT_HDCP_STATUS(port)) & HDCP_STATUS_ENC)) {
-		DRM_ERROR("%s:%d HDCP check failed: link is not encrypted,%x\n",
+	if (WARN_ON(!intel_hdcp_in_use(connector))) {
+		DRM_ERROR("%s:%d HDCP link stopped encryption,%x\n",
 			  connector->base.name, connector->base.base.id,
 			  I915_READ(PORT_HDCP_STATUS(port)));
 		ret = -ENXIO;
@@ -792,18 +806,6 @@ int intel_hdcp_check_link(struct intel_connector *connector)
 	return ret;
 }
 
-static void intel_hdcp_check_work(struct work_struct *work)
-{
-	struct intel_hdcp *hdcp = container_of(to_delayed_work(work),
-					       struct intel_hdcp,
-					       check_work);
-	struct intel_connector *connector = intel_hdcp_to_connector(hdcp);
-
-	if (!intel_hdcp_check_link(connector))
-		schedule_delayed_work(&hdcp->check_work,
-				      DRM_HDCP_CHECK_PERIOD_MS);
-}
-
 static void intel_hdcp_prop_work(struct work_struct *work)
 {
 	struct intel_hdcp *hdcp = container_of(work, struct intel_hdcp,
@@ -1028,6 +1030,25 @@ int hdcp2_deauthenticate_port(struct intel_connector *connector)
 	return hdcp2_close_mei_session(connector);
 }
 
+static inline void _intel_hdcp_check_work(struct intel_connector *connector)
+{
+	struct intel_hdcp *hdcp = &connector->hdcp;
+
+	if (!intel_hdcp_check_link(connector))
+		schedule_delayed_work(&hdcp->check_work,
+				      DRM_HDCP_CHECK_PERIOD_MS);
+}
+
+static void intel_hdcp_check_work(struct work_struct *work)
+{
+	struct intel_hdcp *hdcp = container_of(to_delayed_work(work),
+					       struct intel_hdcp,
+					       check_work);
+	struct intel_connector *connector = intel_hdcp_to_connector(hdcp);
+
+	_intel_hdcp_check_work(connector);
+}
+
 static int i915_hdcp_component_match(struct device *dev, void *data)
 {
 	return !strcmp(dev->driver->name, "mei_hdcp");
@@ -1156,7 +1177,8 @@ int intel_hdcp_disable(struct intel_connector *connector)
 
 	if (hdcp->value != DRM_MODE_CONTENT_PROTECTION_UNDESIRED) {
 		hdcp->value = DRM_MODE_CONTENT_PROTECTION_UNDESIRED;
-		ret = _intel_hdcp_disable(connector);
+		if (hdcp->hdcp_encrypted)
+			ret = _intel_hdcp_disable(connector);
 	}
 
 	mutex_unlock(&hdcp->mutex);
@@ -1196,3 +1218,30 @@ void intel_hdcp_atomic_check(struct drm_connector *connector,
 						   new_state->crtc);
 	crtc_state->mode_changed = true;
 }
+
+/* Handles the CP_IRQ raised from the DP HDCP sink */
+void intel_hdcp_handle_cp_irq(struct intel_connector *connector)
+{
+	struct intel_hdcp *hdcp = &connector->hdcp;
+
+	if (!hdcp->shim)
+		return;
+
+	/*
+	 * As of now we want to handle CP_IRQ triggered while encryption is
+	 * enabled. This includes the notification for Topology change,
+	 * Link failure, reauth request etc.
+	 * Auth msg availability notifications are ignored with mutex_trylock
+	 * as authentication holds the lock. Lock might be taken for link check
+	 * or hdcp_disable too. In either of state we need not handle the
+	 * CP_IRQ, for known reasons.
+	 */
+	if (!mutex_trylock(&hdcp->mutex))
+		return;
+
+	if (!hdcp->hdcp_encrypted)
+		return;
+
+	mutex_unlock(&hdcp->mutex);
+	_intel_hdcp_check_work(connector);
+}
-- 
2.7.4

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply related	[flat|nested] 103+ messages in thread

* [PATCH v9 09/39] drm/i915: Enable and Disable of HDCP2.2
  2018-12-13  4:01 [PATCH v9 00/39] drm/i915: Implement HDCP2.2 Ramalingam C
                   ` (7 preceding siblings ...)
  2018-12-13  4:01 ` [PATCH v9 08/39] drm/i915: hdcp1.4 CP_IRQ handling and SW encryption tracking Ramalingam C
@ 2018-12-13  4:01 ` Ramalingam C
  2018-12-19 15:54   ` Daniel Vetter
  2018-12-13  4:01 ` [PATCH v9 10/39] drm/i915: Implement HDCP2.2 receiver authentication Ramalingam C
                   ` (33 subsequent siblings)
  42 siblings, 1 reply; 103+ messages in thread
From: Ramalingam C @ 2018-12-13  4:01 UTC (permalink / raw)
  To: intel-gfx, dri-devel, seanpaul, daniel.vetter, tomas.winkler,
	uma.shankar

Considering that HDCP2.2 is more secure than HDCP1.4, When a setup
supports HDCP2.2 and HDCP1.4, HDCP2.2 will be enabled.

When HDCP2.2 enabling fails and HDCP1.4 is supported, HDCP1.4 is
enabled.

This change implements a sequence of enabling and disabling of
HDCP2.2 authentication and HDCP2.2 port encryption.

v2:
  Included few optimization suggestions [Chris Wilson]
  Commit message is updated as per the rebased version.
  intel_wait_for_register is used instead of wait_for. [Chris Wilson]
v3:
  Extra comment added and Style issue fixed [Uma]
v4:
  Rebased as part of patch reordering.
  HDCP2 encryption status is tracked.
  HW state check is moved into WARN_ON [Daniel]
v5:
  Redefined the mei service functions as per comp redesign.
  Merged patches related to hdcp2.2 enabling and disabling [Sean Paul].
  Required shim functionality is defined [Sean Paul]
v6:
  Return values are handles [Uma]
  Realigned the code.
  Check for comp_master is removed.
v7:
  HDCP2.2 is attempted only if mei interface is up.
  Adjust to the new interface
  Avoid bool usage in struct [Tomas]
v8:
  mei_binded status check is removed.
  %s/hdcp2_in_use/hdcp2_encrypted

Signed-off-by: Ramalingam C <ramalingam.c@intel.com>
---
 drivers/gpu/drm/i915/intel_drv.h  |   7 ++
 drivers/gpu/drm/i915/intel_hdcp.c | 202 +++++++++++++++++++++++++++++++++++---
 2 files changed, 195 insertions(+), 14 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index decd0346c6a7..6d5361616ca3 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -383,6 +383,10 @@ struct intel_hdcp_shim {
 
 	/* HDCP adaptation(DP/HDMI) required on the port */
 	enum hdcp_wired_protocol protocol;
+
+	/* Detects whether Panel is HDCP2.2 capable */
+	int (*hdcp_2_2_capable)(struct intel_digital_port *intel_dig_port,
+				bool *capable);
 };
 
 struct intel_hdcp {
@@ -400,6 +404,9 @@ struct intel_hdcp {
 	/* Flag indicates whether this connector supports HDCP2.2 or not. */
 	u8 hdcp2_supported;
 
+	/* HDCP2.2 Encryption status */
+	u8 hdcp2_encrypted;
+
 	/*
 	 * Content Stream Type defined by content owner. TYPE0(0x0) content can
 	 * flow in the link protected by HDCP2.2 or HDCP1.4, where as TYPE1(0x1)
diff --git a/drivers/gpu/drm/i915/intel_hdcp.c b/drivers/gpu/drm/i915/intel_hdcp.c
index 2b7814a6f12b..f0ee448e6546 100644
--- a/drivers/gpu/drm/i915/intel_hdcp.c
+++ b/drivers/gpu/drm/i915/intel_hdcp.c
@@ -75,6 +75,23 @@ bool intel_hdcp_capable(struct intel_connector *connector)
 	return capable;
 }
 
+/* Is HDCP2.2 capable on Platform and Sink */
+static bool intel_hdcp2_capable(struct intel_connector *connector)
+{
+	struct intel_digital_port *intel_dig_port = conn_to_dig_port(connector);
+	struct intel_hdcp *hdcp = &connector->hdcp;
+	bool capable = false;
+
+	/* I915 support for HDCP2.2 */
+	if (!hdcp->hdcp2_supported)
+		return false;
+
+	/* Sink's capability for HDCP2.2 */
+	hdcp->shim->hdcp_2_2_capable(intel_dig_port, &capable);
+
+	return capable;
+}
+
 static inline bool intel_hdcp_in_use(struct intel_connector *connector)
 {
 	struct drm_i915_private *dev_priv = to_i915(connector->base.dev);
@@ -1014,8 +1031,7 @@ int hdcp2_authenticate_port(struct intel_connector *connector)
 	return ret;
 }
 
-static __attribute__((unused))
-int hdcp2_close_mei_session(struct intel_connector *connector)
+static int hdcp2_close_mei_session(struct intel_connector *connector)
 {
 	struct drm_i915_private *dev_priv = to_i915(connector->base.dev);
 	struct i915_component_master *comp = dev_priv->comp_master;
@@ -1024,12 +1040,157 @@ int hdcp2_close_mei_session(struct intel_connector *connector)
 						  &connector->hdcp.port_data);
 }
 
-static __attribute__((unused))
-int hdcp2_deauthenticate_port(struct intel_connector *connector)
+static int hdcp2_deauthenticate_port(struct intel_connector *connector)
 {
 	return hdcp2_close_mei_session(connector);
 }
 
+static int hdcp2_authenticate_sink(struct intel_connector *connector)
+{
+	DRM_ERROR("Sink authentication is done in subsequent patches\n");
+
+	return -EINVAL;
+}
+
+static int hdcp2_enable_encryption(struct intel_connector *connector)
+{
+	struct intel_digital_port *intel_dig_port = conn_to_dig_port(connector);
+	struct drm_i915_private *dev_priv = to_i915(connector->base.dev);
+	struct intel_hdcp *hdcp = &connector->hdcp;
+	enum port port = connector->encoder->port;
+	int ret;
+
+	WARN_ON(I915_READ(HDCP2_STATUS_DDI(port)) & LINK_ENCRYPTION_STATUS);
+
+	if (hdcp->shim->toggle_signalling) {
+		ret = hdcp->shim->toggle_signalling(intel_dig_port, true);
+		if (ret) {
+			DRM_ERROR("Failed to enable HDCP signalling. %d\n",
+				  ret);
+			return ret;
+		}
+	}
+
+	if (I915_READ(HDCP2_STATUS_DDI(port)) & LINK_AUTH_STATUS) {
+		/* Link is Authenticated. Now set for Encryption */
+		I915_WRITE(HDCP2_CTL_DDI(port),
+			   I915_READ(HDCP2_CTL_DDI(port)) |
+			   CTL_LINK_ENCRYPTION_REQ);
+	}
+
+	ret = intel_wait_for_register(dev_priv, HDCP2_STATUS_DDI(port),
+				      LINK_ENCRYPTION_STATUS,
+				      LINK_ENCRYPTION_STATUS,
+				      ENCRYPT_STATUS_CHANGE_TIMEOUT_MS);
+
+	return ret;
+}
+
+static int hdcp2_disable_encryption(struct intel_connector *connector)
+{
+	struct intel_digital_port *intel_dig_port = conn_to_dig_port(connector);
+	struct drm_i915_private *dev_priv = to_i915(connector->base.dev);
+	struct intel_hdcp *hdcp = &connector->hdcp;
+	enum port port = connector->encoder->port;
+	int ret;
+
+	WARN_ON(!(I915_READ(HDCP2_STATUS_DDI(port)) & LINK_ENCRYPTION_STATUS));
+
+	I915_WRITE(HDCP2_CTL_DDI(port),
+		   I915_READ(HDCP2_CTL_DDI(port)) & ~CTL_LINK_ENCRYPTION_REQ);
+
+	ret = intel_wait_for_register(dev_priv, HDCP2_STATUS_DDI(port),
+				      LINK_ENCRYPTION_STATUS, 0x0,
+				      ENCRYPT_STATUS_CHANGE_TIMEOUT_MS);
+	if (ret == -ETIMEDOUT)
+		DRM_DEBUG_KMS("Disable Encryption Timedout");
+
+	if (hdcp->shim->toggle_signalling) {
+		ret = hdcp->shim->toggle_signalling(intel_dig_port, false);
+		if (ret) {
+			DRM_ERROR("Failed to disable HDCP signalling. %d\n",
+				  ret);
+			return ret;
+		}
+	}
+
+	return ret;
+}
+
+static int hdcp2_authenticate_and_encrypt(struct intel_connector *connector)
+{
+	int ret, i, tries = 3;
+
+	for (i = 0; i < tries; i++) {
+		ret = hdcp2_authenticate_sink(connector);
+		if (!ret)
+			break;
+
+		/* Clearing the mei hdcp session */
+		DRM_DEBUG_KMS("HDCP2.2 Auth %d of %d Failed.(%d)\n",
+			      i + 1, tries, ret);
+		if (hdcp2_deauthenticate_port(connector) < 0)
+			DRM_DEBUG_KMS("Port deauth failed.\n");
+	}
+
+	if (i != tries) {
+		/*
+		 * Ensuring the required 200mSec min time interval between
+		 * Session Key Exchange and encryption.
+		 */
+		msleep(HDCP_2_2_DELAY_BEFORE_ENCRYPTION_EN);
+		ret = hdcp2_enable_encryption(connector);
+		if (ret < 0) {
+			DRM_DEBUG_KMS("Encryption Enable Failed.(%d)\n", ret);
+			if (hdcp2_deauthenticate_port(connector) < 0)
+				DRM_DEBUG_KMS("Port deauth failed.\n");
+		}
+	}
+
+	return ret;
+}
+
+static int _intel_hdcp2_enable(struct intel_connector *connector)
+{
+	struct intel_hdcp *hdcp = &connector->hdcp;
+	int ret;
+
+	DRM_DEBUG_KMS("[%s:%d] HDCP2.2 is being enabled. Type: %d\n",
+		      connector->base.name, connector->base.base.id,
+		      hdcp->content_type);
+
+	ret = hdcp2_authenticate_and_encrypt(connector);
+	if (ret) {
+		DRM_DEBUG_KMS("HDCP2 Type%d  Enabling Failed. (%d)\n",
+			      hdcp->content_type, ret);
+		return ret;
+	}
+
+	DRM_DEBUG_KMS("[%s:%d] HDCP2.2 is enabled. Type %d\n",
+		      connector->base.name, connector->base.base.id,
+		      hdcp->content_type);
+
+	hdcp->hdcp2_encrypted = 1;
+	return 0;
+}
+
+static int _intel_hdcp2_disable(struct intel_connector *connector)
+{
+	int ret;
+
+	DRM_DEBUG_KMS("[%s:%d] HDCP2.2 is being Disabled\n",
+		      connector->base.name, connector->base.base.id);
+
+	ret = hdcp2_disable_encryption(connector);
+
+	if (hdcp2_deauthenticate_port(connector) < 0)
+		DRM_DEBUG_KMS("Port deauth failed.\n");
+
+	connector->hdcp.hdcp2_encrypted = 0;
+
+	return ret;
+}
+
 static inline void _intel_hdcp_check_work(struct intel_connector *connector)
 {
 	struct intel_hdcp *hdcp = &connector->hdcp;
@@ -1145,22 +1306,33 @@ int intel_hdcp_init(struct intel_connector *connector,
 int intel_hdcp_enable(struct intel_connector *connector)
 {
 	struct intel_hdcp *hdcp = &connector->hdcp;
-	int ret;
+	int ret = -EINVAL;
 
 	if (!hdcp->shim)
 		return -ENOENT;
 
 	mutex_lock(&hdcp->mutex);
 
-	ret = _intel_hdcp_enable(connector);
-	if (ret)
-		goto out;
+	/*
+	 * Considering that HDCP2.2 is more secure than HDCP1.4, If the setup
+	 * is capable of HDCP2.2, it is preferred to use HDCP2.2.
+	 */
+	if (intel_hdcp2_capable(connector))
+		ret = _intel_hdcp2_enable(connector);
+
+	/* When HDCP2.2 fails, HDCP1.4 will be attempted */
+	if (ret && intel_hdcp_capable(connector)) {
+		ret = _intel_hdcp_enable(connector);
+		if (!ret)
+			schedule_delayed_work(&hdcp->check_work,
+					      DRM_HDCP_CHECK_PERIOD_MS);
+	}
+
+	if (!ret) {
+		hdcp->value = DRM_MODE_CONTENT_PROTECTION_ENABLED;
+		schedule_work(&hdcp->prop_work);
+	}
 
-	hdcp->value = DRM_MODE_CONTENT_PROTECTION_ENABLED;
-	schedule_work(&hdcp->prop_work);
-	schedule_delayed_work(&hdcp->check_work,
-			      DRM_HDCP_CHECK_PERIOD_MS);
-out:
 	mutex_unlock(&hdcp->mutex);
 	return ret;
 }
@@ -1177,7 +1349,9 @@ int intel_hdcp_disable(struct intel_connector *connector)
 
 	if (hdcp->value != DRM_MODE_CONTENT_PROTECTION_UNDESIRED) {
 		hdcp->value = DRM_MODE_CONTENT_PROTECTION_UNDESIRED;
-		if (hdcp->hdcp_encrypted)
+		if (hdcp->hdcp2_encrypted)
+			ret = _intel_hdcp2_disable(connector);
+		else if (hdcp->hdcp_encrypted)
 			ret = _intel_hdcp_disable(connector);
 	}
 
-- 
2.7.4

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply related	[flat|nested] 103+ messages in thread

* [PATCH v9 10/39] drm/i915: Implement HDCP2.2 receiver authentication
  2018-12-13  4:01 [PATCH v9 00/39] drm/i915: Implement HDCP2.2 Ramalingam C
                   ` (8 preceding siblings ...)
  2018-12-13  4:01 ` [PATCH v9 09/39] drm/i915: Enable and Disable of HDCP2.2 Ramalingam C
@ 2018-12-13  4:01 ` Ramalingam C
  2018-12-19 14:35   ` Daniel Vetter
  2018-12-13  4:01 ` [PATCH v9 11/39] drm: helper functions for hdcp2 seq_num to from u32 Ramalingam C
                   ` (32 subsequent siblings)
  42 siblings, 1 reply; 103+ messages in thread
From: Ramalingam C @ 2018-12-13  4:01 UTC (permalink / raw)
  To: intel-gfx, dri-devel, seanpaul, daniel.vetter, tomas.winkler,
	uma.shankar

Implements HDCP2.2 authentication for hdcp2.2 receivers, with
following steps:
	Authentication and Key exchange (AKE).
	Locality Check (LC).
	Session Key Exchange(SKE).
	DP Errata for stream type configuration for receivers.

At AKE, the HDCP Receiver’s public key certificate is verified by the
HDCP Transmitter. A Master Key k m is exchanged.

At LC, the HDCP Transmitter enforces locality on the content by
requiring that the Round Trip Time (RTT) between a pair of messages
is not more than 20 ms.

At SKE, The HDCP Transmitter exchanges Session Key ks with
the HDCP Receiver.

In DP HDCP2.2 encryption and decryption logics use the stream type as
one of the parameter. So Before enabling the Encryption DP HDCP2.2
receiver needs to be communicated with stream type. This is added to
spec as ERRATA.

This generic implementation is complete only with the hdcp2 specific
functions defined at hdcp_shim.

v2: Rebased.
v3:
  %s/PARING/PAIRING
  Coding style fixing [Uma]
v4:
  Rebased as part of patch reordering.
  Defined the functions for mei services. [Daniel]
v5:
  Redefined the mei service functions as per comp redesign.
  Required intel_hdcp members are defined [Sean Paul]
v6:
  Typo of cipher is Fixed [Uma]
  %s/uintxx_t/uxx
  Check for comp_master is removed.
v7:
  Adjust to the new interface.
  Avoid using bool structure members. [Tomas]
v8: Rebased.

Signed-off-by: Ramalingam C <ramalingam.c@intel.com>
---
 drivers/gpu/drm/i915/intel_drv.h  |  34 ++++++
 drivers/gpu/drm/i915/intel_hdcp.c | 211 +++++++++++++++++++++++++++++++++++---
 2 files changed, 230 insertions(+), 15 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index 6d5361616ca3..a6b632d71490 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -387,6 +387,22 @@ struct intel_hdcp_shim {
 	/* Detects whether Panel is HDCP2.2 capable */
 	int (*hdcp_2_2_capable)(struct intel_digital_port *intel_dig_port,
 				bool *capable);
+
+	/* Write HDCP2.2 messages */
+	int (*write_2_2_msg)(struct intel_digital_port *intel_dig_port,
+			     void *buf, size_t size);
+
+	/* Read HDCP2.2 messages */
+	int (*read_2_2_msg)(struct intel_digital_port *intel_dig_port,
+			    u8 msg_id, void *buf, size_t size);
+
+	/*
+	 * Implementation of DP HDCP2.2 Errata for the communication of stream
+	 * type to Receivers. In DP HDCP2.2 Stream type is one of the input to
+	 * the HDCP2.2 Cipher for En/De-Cryption. Not applicable for HDMI.
+	 */
+	int (*config_stream_type)(struct intel_digital_port *intel_dig_port,
+				  void *buf, size_t size);
 };
 
 struct intel_hdcp {
@@ -414,6 +430,24 @@ struct intel_hdcp {
 	 */
 	u8 content_type;
 	struct hdcp_port_data port_data;
+
+	u8 is_paired;
+	u8 is_repeater;
+
+	/*
+	 * Count of ReceiverID_List received. Initialized to 0 at AKE_INIT.
+	 * Incremented after processing the RepeaterAuth_Send_ReceiverID_List.
+	 * When it rolls over re-auth has to be triggered.
+	 */
+	u32 seq_num_v;
+
+	/*
+	 * Count of RepeaterAuth_Stream_Manage msg propagated.
+	 * Initialized to 0 on AKE_INIT. Incremented after every successful
+	 * transmission of RepeaterAuth_Stream_Manage message. When it rolls
+	 * over re-Auth has to be triggered.
+	 */
+	u32 seq_num_m;
 };
 
 struct intel_connector {
diff --git a/drivers/gpu/drm/i915/intel_hdcp.c b/drivers/gpu/drm/i915/intel_hdcp.c
index f0ee448e6546..f1f0ef294e20 100644
--- a/drivers/gpu/drm/i915/intel_hdcp.c
+++ b/drivers/gpu/drm/i915/intel_hdcp.c
@@ -18,6 +18,7 @@
 
 #define KEY_LOAD_TRIES	5
 #define ENCRYPT_STATUS_CHANGE_TIMEOUT_MS	50
+#define HDCP2_LC_RETRY_CNT			3
 
 static
 bool intel_hdcp_is_ksv_valid(u8 *ksv)
@@ -854,7 +855,7 @@ bool is_hdcp_supported(struct drm_i915_private *dev_priv, enum port port)
 	return INTEL_GEN(dev_priv) >= 9 && port < PORT_E;
 }
 
-static __attribute__((unused)) int
+static int
 hdcp2_prepare_ake_init(struct intel_connector *connector,
 		       struct hdcp2_ake_init *ake_data)
 {
@@ -875,7 +876,7 @@ hdcp2_prepare_ake_init(struct intel_connector *connector,
 	return ret;
 }
 
-static __attribute__((unused)) int
+static int
 hdcp2_verify_rx_cert_prepare_km(struct intel_connector *connector,
 				struct hdcp2_ake_send_cert *rx_cert,
 				bool *paired,
@@ -897,9 +898,8 @@ hdcp2_verify_rx_cert_prepare_km(struct intel_connector *connector,
 	return ret;
 }
 
-static __attribute__((unused)) int
-hdcp2_verify_hprime(struct intel_connector *connector,
-		    struct hdcp2_ake_send_hprime *rx_hprime)
+static int hdcp2_verify_hprime(struct intel_connector *connector,
+			       struct hdcp2_ake_send_hprime *rx_hprime)
 {
 	struct hdcp_port_data *data = &connector->hdcp.port_data;
 	struct drm_i915_private *dev_priv = to_i915(connector->base.dev);
@@ -913,7 +913,7 @@ hdcp2_verify_hprime(struct intel_connector *connector,
 	return ret;
 }
 
-static __attribute__((unused)) int
+static int
 hdcp2_store_pairing_info(struct intel_connector *connector,
 			 struct hdcp2_ake_send_pairing_info *pairing_info)
 {
@@ -930,7 +930,7 @@ hdcp2_store_pairing_info(struct intel_connector *connector,
 	return ret;
 }
 
-static __attribute__((unused)) int
+static int
 hdcp2_prepare_lc_init(struct intel_connector *connector,
 		      struct hdcp2_lc_init *lc_init)
 {
@@ -947,7 +947,7 @@ hdcp2_prepare_lc_init(struct intel_connector *connector,
 	return ret;
 }
 
-static __attribute__((unused)) int
+static int
 hdcp2_verify_lprime(struct intel_connector *connector,
 		    struct hdcp2_lc_send_lprime *rx_lprime)
 {
@@ -963,9 +963,8 @@ hdcp2_verify_lprime(struct intel_connector *connector,
 	return ret;
 }
 
-static __attribute__((unused))
-int hdcp2_prepare_skey(struct intel_connector *connector,
-		       struct hdcp2_ske_send_eks *ske_data)
+static int hdcp2_prepare_skey(struct intel_connector *connector,
+			      struct hdcp2_ske_send_eks *ske_data)
 {
 	struct hdcp_port_data *data = &connector->hdcp.port_data;
 	struct drm_i915_private *dev_priv = to_i915(connector->base.dev);
@@ -1016,8 +1015,7 @@ hdcp2_verify_mprime(struct intel_connector *connector,
 	return ret;
 }
 
-static __attribute__((unused))
-int hdcp2_authenticate_port(struct intel_connector *connector)
+static int hdcp2_authenticate_port(struct intel_connector *connector)
 {
 	struct hdcp_port_data *data = &connector->hdcp.port_data;
 	struct drm_i915_private *dev_priv = to_i915(connector->base.dev);
@@ -1045,11 +1043,194 @@ static int hdcp2_deauthenticate_port(struct intel_connector *connector)
 	return hdcp2_close_mei_session(connector);
 }
 
+/* Authentication flow starts from here */
+static int hdcp2_authentication_key_exchange(struct intel_connector *connector)
+{
+	struct intel_digital_port *intel_dig_port = conn_to_dig_port(connector);
+	struct intel_hdcp *hdcp = &connector->hdcp;
+	union {
+		struct hdcp2_ake_init ake_init;
+		struct hdcp2_ake_send_cert send_cert;
+		struct hdcp2_ake_no_stored_km no_stored_km;
+		struct hdcp2_ake_send_hprime send_hprime;
+		struct hdcp2_ake_send_pairing_info pairing_info;
+	} msgs;
+	const struct intel_hdcp_shim *shim = hdcp->shim;
+	size_t size;
+	int ret;
+	bool is_paired;
+
+	/* Init for seq_num */
+	hdcp->seq_num_v = 0;
+	hdcp->seq_num_m = 0;
+
+	ret = hdcp2_prepare_ake_init(connector, &msgs.ake_init);
+	if (ret < 0)
+		return ret;
+
+	ret = shim->write_2_2_msg(intel_dig_port, &msgs.ake_init,
+				  sizeof(msgs.ake_init));
+	if (ret < 0)
+		return ret;
+
+	ret = shim->read_2_2_msg(intel_dig_port, HDCP_2_2_AKE_SEND_CERT,
+				 &msgs.send_cert, sizeof(msgs.send_cert));
+	if (ret < 0)
+		return ret;
+
+	if (msgs.send_cert.rx_caps[0] != HDCP_2_2_RX_CAPS_VERSION_VAL)
+		return -EINVAL;
+
+	hdcp->is_repeater = HDCP_2_2_RX_REPEATER(msgs.send_cert.rx_caps[2]) ?
+			    1 : 0;
+
+	/*
+	 * Here msgs.no_stored_km will hold msgs corresponding to the km
+	 * stored also.
+	 */
+	ret = hdcp2_verify_rx_cert_prepare_km(connector, &msgs.send_cert,
+					      &is_paired,
+					      &msgs.no_stored_km, &size);
+	if (ret < 0)
+		return ret;
+
+	hdcp->is_paired = is_paired ? 1 : 0;
+
+	ret = shim->write_2_2_msg(intel_dig_port, &msgs.no_stored_km, size);
+	if (ret < 0)
+		return ret;
+
+	ret = shim->read_2_2_msg(intel_dig_port, HDCP_2_2_AKE_SEND_HPRIME,
+				 &msgs.send_hprime, sizeof(msgs.send_hprime));
+	if (ret < 0)
+		return ret;
+
+	ret = hdcp2_verify_hprime(connector, &msgs.send_hprime);
+	if (ret < 0)
+		return ret;
+
+	if (!hdcp->is_paired) {
+		/* Pairing is required */
+		ret = shim->read_2_2_msg(intel_dig_port,
+					 HDCP_2_2_AKE_SEND_PAIRING_INFO,
+					 &msgs.pairing_info,
+					 sizeof(msgs.pairing_info));
+		if (ret < 0)
+			return ret;
+
+		ret = hdcp2_store_pairing_info(connector, &msgs.pairing_info);
+		if (ret < 0)
+			return ret;
+		hdcp->is_paired = 1;
+	}
+
+	return 0;
+}
+
+static int hdcp2_locality_check(struct intel_connector *connector)
+{
+	struct intel_digital_port *intel_dig_port = conn_to_dig_port(connector);
+	struct intel_hdcp *hdcp = &connector->hdcp;
+	union {
+		struct hdcp2_lc_init lc_init;
+		struct hdcp2_lc_send_lprime send_lprime;
+	} msgs;
+	const struct intel_hdcp_shim *shim = hdcp->shim;
+	int tries = HDCP2_LC_RETRY_CNT, ret, i;
+
+	for (i = 0; i < tries; i++) {
+		ret = hdcp2_prepare_lc_init(connector, &msgs.lc_init);
+		if (ret < 0)
+			continue;
+
+		ret = shim->write_2_2_msg(intel_dig_port, &msgs.lc_init,
+				      sizeof(msgs.lc_init));
+		if (ret < 0)
+			continue;
+
+		ret = shim->read_2_2_msg(intel_dig_port,
+					 HDCP_2_2_LC_SEND_LPRIME,
+					 &msgs.send_lprime,
+					 sizeof(msgs.send_lprime));
+		if (ret < 0)
+			continue;
+
+		ret = hdcp2_verify_lprime(connector, &msgs.send_lprime);
+		if (!ret)
+			break;
+	}
+
+	return ret;
+}
+
+static int hdcp2_session_key_exchange(struct intel_connector *connector)
+{
+	struct intel_digital_port *intel_dig_port = conn_to_dig_port(connector);
+	struct intel_hdcp *hdcp = &connector->hdcp;
+	struct hdcp2_ske_send_eks send_eks;
+	int ret;
+
+	ret = hdcp2_prepare_skey(connector, &send_eks);
+	if (ret < 0)
+		return ret;
+
+	ret = hdcp->shim->write_2_2_msg(intel_dig_port, &send_eks,
+					sizeof(send_eks));
+	if (ret < 0)
+		return ret;
+
+	return 0;
+}
+
 static int hdcp2_authenticate_sink(struct intel_connector *connector)
 {
-	DRM_ERROR("Sink authentication is done in subsequent patches\n");
+	struct intel_digital_port *intel_dig_port = conn_to_dig_port(connector);
+	struct intel_hdcp *hdcp = &connector->hdcp;
+	const struct intel_hdcp_shim *shim = hdcp->shim;
+	struct hdcp2_dp_errata_stream_type stream_type_msg;
+	int ret;
 
-	return -EINVAL;
+	ret = hdcp2_authentication_key_exchange(connector);
+	if (ret < 0) {
+		DRM_DEBUG_KMS("AKE Failed. Err : %d\n", ret);
+		return ret;
+	}
+
+	ret = hdcp2_locality_check(connector);
+	if (ret < 0) {
+		DRM_DEBUG_KMS("Locality Check failed. Err : %d\n", ret);
+		return ret;
+	}
+
+	ret = hdcp2_session_key_exchange(connector);
+	if (ret < 0) {
+		DRM_DEBUG_KMS("SKE Failed. Err : %d\n", ret);
+		return ret;
+	}
+
+	if (!hdcp->is_repeater && shim->config_stream_type) {
+		/*
+		 * Errata for DP: As Stream type is used for encryption,
+		 * Receiver should be communicated with stream type for the
+		 * decryption of the content.
+		 * Repeater will be communicated with stream type as a
+		 * part of it's auth later in time.
+		 */
+		stream_type_msg.msg_id = HDCP_2_2_ERRATA_DP_STREAM_TYPE;
+		stream_type_msg.stream_type = hdcp->content_type;
+
+		ret = shim->config_stream_type(intel_dig_port, &stream_type_msg,
+					       sizeof(stream_type_msg));
+		if (ret < 0)
+			return ret;
+	}
+
+	hdcp->port_data.streams[0].stream_type = hdcp->content_type;
+	ret = hdcp2_authenticate_port(connector);
+	if (ret < 0)
+		return ret;
+
+	return ret;
 }
 
 static int hdcp2_enable_encryption(struct intel_connector *connector)
-- 
2.7.4

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply related	[flat|nested] 103+ messages in thread

* [PATCH v9 11/39] drm: helper functions for hdcp2 seq_num to from u32
  2018-12-13  4:01 [PATCH v9 00/39] drm/i915: Implement HDCP2.2 Ramalingam C
                   ` (9 preceding siblings ...)
  2018-12-13  4:01 ` [PATCH v9 10/39] drm/i915: Implement HDCP2.2 receiver authentication Ramalingam C
@ 2018-12-13  4:01 ` Ramalingam C
  2018-12-19 14:38   ` Daniel Vetter
  2018-12-13  4:01 ` [PATCH v9 12/39] drm/i915: Implement HDCP2.2 repeater authentication Ramalingam C
                   ` (31 subsequent siblings)
  42 siblings, 1 reply; 103+ messages in thread
From: Ramalingam C @ 2018-12-13  4:01 UTC (permalink / raw)
  To: intel-gfx, dri-devel, seanpaul, daniel.vetter, tomas.winkler,
	uma.shankar

Library functions for endianness are aligned for 16/32/64 bits.
But hdcp sequence numbers are 24bits(big endian).
So for their conversion to and from u32 helper functions are developed.

Signed-off-by: Ramalingam C <ramalingam.c@intel.com>
---
 include/drm/drm_hdcp.h | 18 ++++++++++++++++++
 1 file changed, 18 insertions(+)

diff --git a/include/drm/drm_hdcp.h b/include/drm/drm_hdcp.h
index a6de09c5e47f..d8093ecf3ddc 100644
--- a/include/drm/drm_hdcp.h
+++ b/include/drm/drm_hdcp.h
@@ -250,4 +250,22 @@ struct hdcp2_dp_errata_stream_type {
 #define HDCP_2_2_HDMI_RXSTATUS_READY(x)		((x) & BIT(2))
 #define HDCP_2_2_HDMI_RXSTATUS_REAUTH_REQ(x)	((x) & BIT(3))
 
+/*
+ * Library functions for endianness are aligned for 16/32/64 bits.
+ * But hdcp sequence numbers are 24bits(big endian). So for their conversion
+ * from and to u32 below functions are developed.
+ */
+static inline void
+drm_hdcp2_seq_num_to_u32(u32 *val, u8 seq_num[HDCP_2_2_SEQ_NUM_LEN])
+{
+	*val = seq_num[2] | seq_num[1] << 8 | seq_num[0] << 16;
+}
+
+static inline void drm_hdcp2_u32_to_seq_num(u8 *seq_num, u32 val)
+{
+	seq_num[0] = (val & (0xff << 16)) >> 16;
+	seq_num[1] = (val & (0xff << 8)) >> 8;
+	seq_num[2] = val & 0xff;
+}
+
 #endif
-- 
2.7.4

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply related	[flat|nested] 103+ messages in thread

* [PATCH v9 12/39] drm/i915: Implement HDCP2.2 repeater authentication
  2018-12-13  4:01 [PATCH v9 00/39] drm/i915: Implement HDCP2.2 Ramalingam C
                   ` (10 preceding siblings ...)
  2018-12-13  4:01 ` [PATCH v9 11/39] drm: helper functions for hdcp2 seq_num to from u32 Ramalingam C
@ 2018-12-13  4:01 ` Ramalingam C
  2018-12-13  8:22   ` Winkler, Tomas
  2018-12-19 14:48   ` Daniel Vetter
  2018-12-13  4:01 ` [PATCH v9 13/39] drm: HDCP2.2 link check related constants Ramalingam C
                   ` (30 subsequent siblings)
  42 siblings, 2 replies; 103+ messages in thread
From: Ramalingam C @ 2018-12-13  4:01 UTC (permalink / raw)
  To: intel-gfx, dri-devel, seanpaul, daniel.vetter, tomas.winkler,
	uma.shankar

Implements the HDCP2.2 repeaters authentication steps such as verifying
the downstream topology and sending stream management information.

v2: Rebased.
v3:
  -EINVAL is returned for topology error and rollover scenario.
  Endianness conversion func from drm_hdcp.h is used [Uma]
v4:
  Rebased as part of patches reordering.
  Defined the mei service functions [Daniel]
v5:
  Redefined the mei service functions as per comp redesign.
v6:
  %s/uintxx_t/uxx
  Check for comp_master is removed.
v7:
  Adjust to the new mei interface.
  style issue fixed.
v8:
  drm_hdcp.h change is moved into separate patch [Daniel]

Signed-off-by: Ramalingam C <ramalingam.c@intel.com>
---
 drivers/gpu/drm/i915/intel_hdcp.c | 123 +++++++++++++++++++++++++++++++++++++-
 1 file changed, 121 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_hdcp.c b/drivers/gpu/drm/i915/intel_hdcp.c
index f1f0ef294e20..b52da5c3159d 100644
--- a/drivers/gpu/drm/i915/intel_hdcp.c
+++ b/drivers/gpu/drm/i915/intel_hdcp.c
@@ -978,7 +978,7 @@ static int hdcp2_prepare_skey(struct intel_connector *connector,
 	return ret;
 }
 
-static __attribute__((unused)) int
+static int
 hdcp2_verify_rep_topology_prepare_ack(struct intel_connector *connector,
 				      struct hdcp2_rep_send_receiverid_list
 								*rep_topology,
@@ -999,7 +999,7 @@ hdcp2_verify_rep_topology_prepare_ack(struct intel_connector *connector,
 	return ret;
 }
 
-static __attribute__((unused)) int
+static int
 hdcp2_verify_mprime(struct intel_connector *connector,
 		    struct hdcp2_rep_stream_ready *stream_ready)
 {
@@ -1182,6 +1182,119 @@ static int hdcp2_session_key_exchange(struct intel_connector *connector)
 	return 0;
 }
 
+static
+int hdcp2_propagate_stream_management_info(struct intel_connector *connector)
+{
+	struct intel_digital_port *intel_dig_port = conn_to_dig_port(connector);
+	struct intel_hdcp *hdcp = &connector->hdcp;
+	union {
+		struct hdcp2_rep_stream_manage stream_manage;
+		struct hdcp2_rep_stream_ready stream_ready;
+	} msgs;
+	const struct intel_hdcp_shim *shim = hdcp->shim;
+	int ret;
+
+	/* Prepare RepeaterAuth_Stream_Manage msg */
+	msgs.stream_manage.msg_id = HDCP_2_2_REP_STREAM_MANAGE;
+	drm_hdcp2_u32_to_seq_num(msgs.stream_manage.seq_num_m, hdcp->seq_num_m);
+
+	/* K no of streams is fixed as 1. Stored as big-endian. */
+	msgs.stream_manage.k = __swab16(1);
+
+	/* For HDMI this is forced to be 0x0. For DP SST also this is 0x0. */
+	msgs.stream_manage.streams[0].stream_id = 0;
+	msgs.stream_manage.streams[0].stream_type = hdcp->content_type;
+
+	/* Send it to Repeater */
+	ret = shim->write_2_2_msg(intel_dig_port, &msgs.stream_manage,
+				  sizeof(msgs.stream_manage));
+	if (ret < 0)
+		return ret;
+
+	ret = shim->read_2_2_msg(intel_dig_port, HDCP_2_2_REP_STREAM_READY,
+				 &msgs.stream_ready, sizeof(msgs.stream_ready));
+	if (ret < 0)
+		return ret;
+
+	hdcp->port_data.seq_num_m = hdcp->seq_num_m;
+	hdcp->port_data.streams[0].stream_type = hdcp->content_type;
+
+	ret = hdcp2_verify_mprime(connector, &msgs.stream_ready);
+	if (ret < 0)
+		return ret;
+
+	hdcp->seq_num_m++;
+
+	if (hdcp->seq_num_m > HDCP_2_2_SEQ_NUM_MAX) {
+		DRM_DEBUG_KMS("seq_num_m roll over.\n");
+		return -1;
+	}
+
+	return 0;
+}
+
+static
+int hdcp2_authenticate_repeater_topology(struct intel_connector *connector)
+{
+	struct intel_digital_port *intel_dig_port = conn_to_dig_port(connector);
+	struct intel_hdcp *hdcp = &connector->hdcp;
+	union {
+		struct hdcp2_rep_send_receiverid_list recvid_list;
+		struct hdcp2_rep_send_ack rep_ack;
+	} msgs;
+	const struct intel_hdcp_shim *shim = hdcp->shim;
+	u8 *rx_info;
+	u32 seq_num_v;
+	int ret;
+
+	ret = shim->read_2_2_msg(intel_dig_port, HDCP_2_2_REP_SEND_RECVID_LIST,
+				 &msgs.recvid_list, sizeof(msgs.recvid_list));
+	if (ret < 0)
+		return ret;
+
+	rx_info = msgs.recvid_list.rx_info;
+
+	if (HDCP_2_2_MAX_CASCADE_EXCEEDED(rx_info[1]) ||
+	    HDCP_2_2_MAX_DEVS_EXCEEDED(rx_info[1])) {
+		DRM_DEBUG_KMS("Topology Max Size Exceeded\n");
+		return -EINVAL;
+	}
+
+	/* Converting and Storing the seq_num_v to local variable as DWORD */
+	drm_hdcp2_seq_num_to_u32(&seq_num_v, msgs.recvid_list.seq_num_v);
+
+	if (seq_num_v < hdcp->seq_num_v) {
+		/* Roll over of the seq_num_v from repeater. Reauthenticate. */
+		DRM_DEBUG_KMS("Seq_num_v roll over.\n");
+		return -EINVAL;
+	}
+
+	ret = hdcp2_verify_rep_topology_prepare_ack(connector,
+						    &msgs.recvid_list,
+						    &msgs.rep_ack);
+	if (ret < 0)
+		return ret;
+
+	hdcp->seq_num_v = seq_num_v;
+	ret = shim->write_2_2_msg(intel_dig_port, &msgs.rep_ack,
+				  sizeof(msgs.rep_ack));
+	if (ret < 0)
+		return ret;
+
+	return 0;
+}
+
+static int hdcp2_authenticate_repeater(struct intel_connector *connector)
+{
+	int ret;
+
+	ret = hdcp2_authenticate_repeater_topology(connector);
+	if (ret < 0)
+		return ret;
+
+	return hdcp2_propagate_stream_management_info(connector);
+}
+
 static int hdcp2_authenticate_sink(struct intel_connector *connector)
 {
 	struct intel_digital_port *intel_dig_port = conn_to_dig_port(connector);
@@ -1223,6 +1336,12 @@ static int hdcp2_authenticate_sink(struct intel_connector *connector)
 					       sizeof(stream_type_msg));
 		if (ret < 0)
 			return ret;
+	} else if (hdcp->is_repeater) {
+		ret = hdcp2_authenticate_repeater(connector);
+		if (ret < 0) {
+			DRM_DEBUG_KMS("Repeater Auth Failed. Err: %d\n", ret);
+			return ret;
+		}
 	}
 
 	hdcp->port_data.streams[0].stream_type = hdcp->content_type;
-- 
2.7.4

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply related	[flat|nested] 103+ messages in thread

* [PATCH v9 13/39] drm: HDCP2.2 link check related constants
  2018-12-13  4:01 [PATCH v9 00/39] drm/i915: Implement HDCP2.2 Ramalingam C
                   ` (11 preceding siblings ...)
  2018-12-13  4:01 ` [PATCH v9 12/39] drm/i915: Implement HDCP2.2 repeater authentication Ramalingam C
@ 2018-12-13  4:01 ` Ramalingam C
  2018-12-19 15:16   ` Daniel Vetter
  2018-12-13  4:01 ` [PATCH v9 14/39] drm/i915: Implement HDCP2.2 link integrity check Ramalingam C
                   ` (29 subsequent siblings)
  42 siblings, 1 reply; 103+ messages in thread
From: Ramalingam C @ 2018-12-13  4:01 UTC (permalink / raw)
  To: intel-gfx, dri-devel, seanpaul, daniel.vetter, tomas.winkler,
	uma.shankar

Enums and macros are defined for HDCP2.2 link check.

Signed-off-by: Ramalingam C <ramalingam.c@intel.com>
---
 include/drm/drm_hdcp.h | 8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/include/drm/drm_hdcp.h b/include/drm/drm_hdcp.h
index d8093ecf3ddc..21a128e7020a 100644
--- a/include/drm/drm_hdcp.h
+++ b/include/drm/drm_hdcp.h
@@ -11,6 +11,14 @@
 
 /* Period of hdcp checks (to ensure we're still authenticated) */
 #define DRM_HDCP_CHECK_PERIOD_MS		(128 * 16)
+#define DRM_HDCP2_CHECK_PERIOD_MS		500
+
+enum check_link_response {
+	DRM_HDCP_LINK_PROTECTED	= 0,
+	DRM_HDCP_TOPOLOGY_CHANGE,
+	DRM_HDCP_LINK_INTEGRITY_FAILURE,
+	DRM_HDCP_REAUTH_REQUEST
+};
 
 /* Shared lengths/masks between HDMI/DVI/DisplayPort */
 #define DRM_HDCP_AN_LEN				8
-- 
2.7.4

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply related	[flat|nested] 103+ messages in thread

* [PATCH v9 14/39] drm/i915: Implement HDCP2.2 link integrity check
  2018-12-13  4:01 [PATCH v9 00/39] drm/i915: Implement HDCP2.2 Ramalingam C
                   ` (12 preceding siblings ...)
  2018-12-13  4:01 ` [PATCH v9 13/39] drm: HDCP2.2 link check related constants Ramalingam C
@ 2018-12-13  4:01 ` Ramalingam C
  2018-12-13  4:01 ` [PATCH v9 15/39] drm/i915: Handle HDCP2.2 downstream topology change Ramalingam C
                   ` (28 subsequent siblings)
  42 siblings, 0 replies; 103+ messages in thread
From: Ramalingam C @ 2018-12-13  4:01 UTC (permalink / raw)
  To: intel-gfx, dri-devel, seanpaul, daniel.vetter, tomas.winkler,
	uma.shankar

Implements the link integrity check once in 500mSec.

Once encryption is enabled, an ongoing Link Integrity Check is
performed by the HDCP Receiver to check that cipher synchronization
is maintained between the HDCP Transmitter and the HDCP Receiver.

On the detection of synchronization lost, the HDCP Receiver must assert
the corresponding bits of the RxStatus register. The Transmitter polls
the RxStatus register and it may initiate re-authentication.

v2:
  Rebased.
v3:
  enum check_link_response is used check the link status [Uma]
v4:
  Rebased as part of patch reordering.
v5:
  Required members of intel_hdcp is defined [Sean Paul]
v6:
  hdcp2_check_link is cancelled at required places.
v7:
  Rebased for the component i/f changes.
  Errors due to the sinks are reported as DEBUG logs.
v8:
  hdcp_check_work is used for both hdcp1 and hdcp2 check_link [Daniel]
  hdcp2.2 encryption status check is put under WARN_ON [Daniel]
  drm_hdcp.h changes are moved into separate patch [Daniel]

Signed-off-by: Ramalingam C <ramalingam.c@intel.com>
Reviewed-by: Uma Shankar <uma.shankar@intel.com>
---
 drivers/gpu/drm/i915/intel_drv.h  |  3 ++
 drivers/gpu/drm/i915/intel_hdcp.c | 90 ++++++++++++++++++++++++++++++++++++---
 2 files changed, 87 insertions(+), 6 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index a6b632d71490..60d1359e55f4 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -403,6 +403,9 @@ struct intel_hdcp_shim {
 	 */
 	int (*config_stream_type)(struct intel_digital_port *intel_dig_port,
 				  void *buf, size_t size);
+
+	/* HDCP2.2 Link Integrity Check */
+	int (*check_2_2_link)(struct intel_digital_port *intel_dig_port);
 };
 
 struct intel_hdcp {
diff --git a/drivers/gpu/drm/i915/intel_hdcp.c b/drivers/gpu/drm/i915/intel_hdcp.c
index b52da5c3159d..6fac570fcbac 100644
--- a/drivers/gpu/drm/i915/intel_hdcp.c
+++ b/drivers/gpu/drm/i915/intel_hdcp.c
@@ -103,6 +103,16 @@ static inline bool intel_hdcp_in_use(struct intel_connector *connector)
 	return reg & HDCP_STATUS_ENC;
 }
 
+static inline bool intel_hdcp2_in_use(struct intel_connector *connector)
+{
+	struct drm_i915_private *dev_priv = to_i915(connector->base.dev);
+	enum port port = connector->encoder->port;
+	u32 reg;
+
+	reg = I915_READ(HDCP2_STATUS_DDI(port));
+	return reg & LINK_ENCRYPTION_STATUS;
+}
+
 static int intel_hdcp_poll_ksv_fifo(struct intel_digital_port *intel_dig_port,
 				    const struct intel_hdcp_shim *shim)
 {
@@ -1491,11 +1501,77 @@ static int _intel_hdcp2_disable(struct intel_connector *connector)
 	return ret;
 }
 
+/* Implements the Link Integrity Check for HDCP2.2 */
+static int intel_hdcp2_check_link(struct intel_connector *connector)
+{
+	struct intel_digital_port *intel_dig_port = conn_to_dig_port(connector);
+	struct drm_i915_private *dev_priv = to_i915(connector->base.dev);
+	struct intel_hdcp *hdcp = &connector->hdcp;
+	enum port port = connector->encoder->port;
+	int ret = 0;
+
+	mutex_lock(&hdcp->mutex);
+
+	/* hdcp2_check_link is expected only when HDCP2.2 is Enabled */
+	if (hdcp->value != DRM_MODE_CONTENT_PROTECTION_ENABLED ||
+	    !hdcp->hdcp2_encrypted) {
+		ret = -EINVAL;
+		goto out;
+	}
+
+	if (WARN_ON(!intel_hdcp2_in_use(connector))) {
+		DRM_ERROR("HDCP2.2 link stopped the encryption, %x\n",
+			  I915_READ(HDCP2_STATUS_DDI(port)));
+		ret = -ENXIO;
+		hdcp->value = DRM_MODE_CONTENT_PROTECTION_DESIRED;
+		schedule_work(&hdcp->prop_work);
+		goto out;
+	}
+
+	ret = hdcp->shim->check_2_2_link(intel_dig_port);
+	if (ret == DRM_HDCP_LINK_PROTECTED) {
+		if (hdcp->value != DRM_MODE_CONTENT_PROTECTION_UNDESIRED) {
+			hdcp->value = DRM_MODE_CONTENT_PROTECTION_ENABLED;
+			schedule_work(&hdcp->prop_work);
+		}
+		goto out;
+	}
+
+	DRM_DEBUG_KMS("[%s:%d] HDCP2.2 link failed, retrying auth\n",
+		      connector->base.name, connector->base.base.id);
+
+	ret = _intel_hdcp2_disable(connector);
+	if (ret) {
+		DRM_ERROR("[%s:%d] Failed to disable hdcp2.2 (%d)\n",
+			  connector->base.name, connector->base.base.id, ret);
+		hdcp->value = DRM_MODE_CONTENT_PROTECTION_DESIRED;
+		schedule_work(&hdcp->prop_work);
+		goto out;
+	}
+
+	ret = _intel_hdcp2_enable(connector);
+	if (ret) {
+		DRM_DEBUG_KMS("[%s:%d] Failed to enable hdcp2.2 (%d)\n",
+			      connector->base.name, connector->base.base.id,
+			      ret);
+		hdcp->value = DRM_MODE_CONTENT_PROTECTION_DESIRED;
+		schedule_work(&hdcp->prop_work);
+		goto out;
+	}
+
+out:
+	mutex_unlock(&hdcp->mutex);
+	return ret;
+}
+
 static inline void _intel_hdcp_check_work(struct intel_connector *connector)
 {
 	struct intel_hdcp *hdcp = &connector->hdcp;
 
-	if (!intel_hdcp_check_link(connector))
+	if (!intel_hdcp2_check_link(connector))
+		schedule_delayed_work(&hdcp->check_work,
+				      DRM_HDCP2_CHECK_PERIOD_MS);
+	else if (!intel_hdcp_check_link(connector))
 		schedule_delayed_work(&hdcp->check_work,
 				      DRM_HDCP_CHECK_PERIOD_MS);
 }
@@ -1606,6 +1682,7 @@ int intel_hdcp_init(struct intel_connector *connector,
 int intel_hdcp_enable(struct intel_connector *connector)
 {
 	struct intel_hdcp *hdcp = &connector->hdcp;
+	unsigned long check_link_interval = DRM_HDCP_CHECK_PERIOD_MS;
 	int ret = -EINVAL;
 
 	if (!hdcp->shim)
@@ -1617,18 +1694,19 @@ int intel_hdcp_enable(struct intel_connector *connector)
 	 * Considering that HDCP2.2 is more secure than HDCP1.4, If the setup
 	 * is capable of HDCP2.2, it is preferred to use HDCP2.2.
 	 */
-	if (intel_hdcp2_capable(connector))
+	if (intel_hdcp2_capable(connector)) {
 		ret = _intel_hdcp2_enable(connector);
+		if (!ret)
+			check_link_interval = DRM_HDCP2_CHECK_PERIOD_MS;
+	}
 
 	/* When HDCP2.2 fails, HDCP1.4 will be attempted */
 	if (ret && intel_hdcp_capable(connector)) {
 		ret = _intel_hdcp_enable(connector);
-		if (!ret)
-			schedule_delayed_work(&hdcp->check_work,
-					      DRM_HDCP_CHECK_PERIOD_MS);
 	}
 
 	if (!ret) {
+		schedule_delayed_work(&hdcp->check_work, check_link_interval);
 		hdcp->value = DRM_MODE_CONTENT_PROTECTION_ENABLED;
 		schedule_work(&hdcp->prop_work);
 	}
@@ -1713,7 +1791,7 @@ void intel_hdcp_handle_cp_irq(struct intel_connector *connector)
 	if (!mutex_trylock(&hdcp->mutex))
 		return;
 
-	if (!hdcp->hdcp_encrypted)
+	if (!hdcp->hdcp_encrypted && !hdcp->hdcp2_encrypted)
 		return;
 
 	mutex_unlock(&hdcp->mutex);
-- 
2.7.4

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply related	[flat|nested] 103+ messages in thread

* [PATCH v9 15/39] drm/i915: Handle HDCP2.2 downstream topology change
  2018-12-13  4:01 [PATCH v9 00/39] drm/i915: Implement HDCP2.2 Ramalingam C
                   ` (13 preceding siblings ...)
  2018-12-13  4:01 ` [PATCH v9 14/39] drm/i915: Implement HDCP2.2 link integrity check Ramalingam C
@ 2018-12-13  4:01 ` Ramalingam C
  2018-12-13  4:01 ` [PATCH v9 16/39] drm/i915: Implement the HDCP2.2 support for DP Ramalingam C
                   ` (27 subsequent siblings)
  42 siblings, 0 replies; 103+ messages in thread
From: Ramalingam C @ 2018-12-13  4:01 UTC (permalink / raw)
  To: intel-gfx, dri-devel, seanpaul, daniel.vetter, tomas.winkler,
	uma.shankar

When repeater notifies a downstream topology change, this patch
reauthenticate the repeater alone without disabling the hdcp
encryption. If that fails then complete reauthentication is executed.

v2:
  Rebased.
v3:
  Typo in commit msg is fixed [Uma]
v4:
  Rebased as part of patch reordering.
  Minor style fixes.
v5:
  Rebased.
v6:
  Rebased.
v7:
  Errors due to sinks are reported as DEBUG logs.

Signed-off-by: Ramalingam C <ramalingam.c@intel.com>
Reviewed-by: Uma Shankar <uma.shankar@intel.com>
---
 drivers/gpu/drm/i915/intel_hdcp.c | 20 ++++++++++++++++++--
 1 file changed, 18 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_hdcp.c b/drivers/gpu/drm/i915/intel_hdcp.c
index 6fac570fcbac..cafda8903b50 100644
--- a/drivers/gpu/drm/i915/intel_hdcp.c
+++ b/drivers/gpu/drm/i915/intel_hdcp.c
@@ -1537,8 +1537,24 @@ static int intel_hdcp2_check_link(struct intel_connector *connector)
 		goto out;
 	}
 
-	DRM_DEBUG_KMS("[%s:%d] HDCP2.2 link failed, retrying auth\n",
-		      connector->base.name, connector->base.base.id);
+	if (ret == DRM_HDCP_TOPOLOGY_CHANGE) {
+		if (hdcp->value == DRM_MODE_CONTENT_PROTECTION_UNDESIRED)
+			goto out;
+
+		DRM_DEBUG_KMS("HDCP2.2 Downstream topology change\n");
+		ret = hdcp2_authenticate_repeater_topology(connector);
+		if (!ret) {
+			hdcp->value = DRM_MODE_CONTENT_PROTECTION_ENABLED;
+			schedule_work(&hdcp->prop_work);
+			goto out;
+		}
+		DRM_DEBUG_KMS("[%s:%d] Repeater topology auth failed.(%d)\n",
+			      connector->base.name, connector->base.base.id,
+			      ret);
+	} else {
+		DRM_DEBUG_KMS("[%s:%d] HDCP2.2 link failed, retrying auth\n",
+			      connector->base.name, connector->base.base.id);
+	}
 
 	ret = _intel_hdcp2_disable(connector);
 	if (ret) {
-- 
2.7.4

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply related	[flat|nested] 103+ messages in thread

* [PATCH v9 16/39] drm/i915: Implement the HDCP2.2 support for DP
  2018-12-13  4:01 [PATCH v9 00/39] drm/i915: Implement HDCP2.2 Ramalingam C
                   ` (14 preceding siblings ...)
  2018-12-13  4:01 ` [PATCH v9 15/39] drm/i915: Handle HDCP2.2 downstream topology change Ramalingam C
@ 2018-12-13  4:01 ` Ramalingam C
  2018-12-13  4:01 ` [PATCH v9 17/39] drm/i915: Implement the HDCP2.2 support for HDMI Ramalingam C
                   ` (26 subsequent siblings)
  42 siblings, 0 replies; 103+ messages in thread
From: Ramalingam C @ 2018-12-13  4:01 UTC (permalink / raw)
  To: intel-gfx, dri-devel, seanpaul, daniel.vetter, tomas.winkler,
	uma.shankar

Implements the DP adaptation specific HDCP2.2 functions.

These functions perform the DPCD read and write for communicating the
HDCP2.2 auth message back and forth.

v2:
  wait for cp_irq is merged with this patch. Rebased.
v3:
  wait_queue is used for wait for cp_irq [Chris Wilson]
v4:
  Style fixed.
  %s/PARING/PAIRING
  Few style fixes [Uma]
v5:
  Lookup table for DP HDCP2.2 msg details [Daniel].
  Extra lines are removed.
v6: Rebased.
v7:
  Fixed some regression introduced at v5. [Ankit]
  Macro HDCP_2_2_RX_CAPS_VERSION_VAL is reused [Uma]
  Converted a function to inline [Uma]
  %s/uintxx_t/uxx
v8:
  Error due to the sinks are reported as DEBUG logs.
  Adjust to the new mei interface.
v9:
  ARRAY_SIZE for no of array members [Jon & Daniel]
  return of the wait_for_cp_irq is made as void [Daniel]
  Wait for HDCP2.2 msg is done based on polling the reg bit than
    CP_IRQ based. [Daniel]
  hdcp adaptation is added as a const in the hdcp_shim [Daniel]

Signed-off-by: Ramalingam C <ramalingam.c@intel.com>
Signed-off-by: Ankit K Nautiyal <ankit.k.nautiyal@intel.com>
Reviewed-by: Uma Shankar <uma.shankar@intel.com>
---
 drivers/gpu/drm/i915/intel_dp.c | 310 ++++++++++++++++++++++++++++++++++++++++
 1 file changed, 310 insertions(+)

diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
index 89315e15fb34..a8ace7d85918 100644
--- a/drivers/gpu/drm/i915/intel_dp.c
+++ b/drivers/gpu/drm/i915/intel_dp.c
@@ -5797,6 +5797,310 @@ int intel_dp_hdcp_capable(struct intel_digital_port *intel_dig_port,
 	return 0;
 }
 
+static struct hdcp2_dp_msg_data {
+	u8 msg_id;
+	u32 offset;
+	bool msg_detectable;
+	u32 timeout;
+	u32 timeout2; /* Added for non_paired situation */
+	} hdcp2_msg_data[] = {
+		{HDCP_2_2_AKE_INIT, DP_HDCP_2_2_AKE_INIT_OFFSET, false, 0, 0},
+		{HDCP_2_2_AKE_SEND_CERT, DP_HDCP_2_2_AKE_SEND_CERT_OFFSET,
+				false, HDCP_2_2_CERT_TIMEOUT_MS, 0},
+		{HDCP_2_2_AKE_NO_STORED_KM, DP_HDCP_2_2_AKE_NO_STORED_KM_OFFSET,
+				false, 0, 0},
+		{HDCP_2_2_AKE_STORED_KM, DP_HDCP_2_2_AKE_STORED_KM_OFFSET,
+				false, 0, 0},
+		{HDCP_2_2_AKE_SEND_HPRIME, DP_HDCP_2_2_AKE_SEND_HPRIME_OFFSET,
+				true, HDCP_2_2_HPRIME_PAIRED_TIMEOUT_MS,
+				HDCP_2_2_HPRIME_NO_PAIRED_TIMEOUT_MS},
+		{HDCP_2_2_AKE_SEND_PAIRING_INFO,
+				DP_HDCP_2_2_AKE_SEND_PAIRING_INFO_OFFSET, true,
+				HDCP_2_2_PAIRING_TIMEOUT_MS, 0},
+		{HDCP_2_2_LC_INIT, DP_HDCP_2_2_LC_INIT_OFFSET, false, 0, 0},
+		{HDCP_2_2_LC_SEND_LPRIME, DP_HDCP_2_2_LC_SEND_LPRIME_OFFSET,
+				false, HDCP_2_2_DP_LPRIME_TIMEOUT_MS, 0},
+		{HDCP_2_2_SKE_SEND_EKS, DP_HDCP_2_2_SKE_SEND_EKS_OFFSET, false,
+				0, 0},
+		{HDCP_2_2_REP_SEND_RECVID_LIST,
+				DP_HDCP_2_2_REP_SEND_RECVID_LIST_OFFSET, true,
+				HDCP_2_2_RECVID_LIST_TIMEOUT_MS, 0},
+		{HDCP_2_2_REP_SEND_ACK, DP_HDCP_2_2_REP_SEND_ACK_OFFSET, false,
+				0, 0},
+		{HDCP_2_2_REP_STREAM_MANAGE,
+				DP_HDCP_2_2_REP_STREAM_MANAGE_OFFSET, false,
+				0, 0},
+		{HDCP_2_2_REP_STREAM_READY, DP_HDCP_2_2_REP_STREAM_READY_OFFSET,
+				false, HDCP_2_2_STREAM_READY_TIMEOUT_MS, 0},
+		{HDCP_2_2_ERRATA_DP_STREAM_TYPE,
+				DP_HDCP_2_2_REG_STREAM_TYPE_OFFSET, false,
+				0, 0},
+		};
+
+static inline
+int intel_dp_hdcp2_read_rx_status(struct intel_digital_port *intel_dig_port,
+				  u8 *rx_status)
+{
+	ssize_t ret;
+
+	ret = drm_dp_dpcd_read(&intel_dig_port->dp.aux,
+			       DP_HDCP_2_2_REG_RXSTATUS_OFFSET, rx_status,
+			       HDCP_2_2_DP_RXSTATUS_LEN);
+	if (ret != HDCP_2_2_DP_RXSTATUS_LEN) {
+		DRM_DEBUG_KMS("Read bstatus from DP/AUX failed (%zd)\n", ret);
+		return ret >= 0 ? -EIO : ret;
+	}
+
+	return 0;
+}
+
+static
+int hdcp2_detect_msg_availability(struct intel_digital_port *intel_dig_port,
+				  u8 msg_id, bool *msg_ready)
+{
+	u8 rx_status;
+	int ret;
+
+	*msg_ready = false;
+	ret = intel_dp_hdcp2_read_rx_status(intel_dig_port, &rx_status);
+	if (ret < 0)
+		return ret;
+
+	switch (msg_id) {
+	case HDCP_2_2_AKE_SEND_HPRIME:
+		if (HDCP_2_2_DP_RXSTATUS_H_PRIME(rx_status))
+			*msg_ready = true;
+		break;
+	case HDCP_2_2_AKE_SEND_PAIRING_INFO:
+		if (HDCP_2_2_DP_RXSTATUS_PAIRING(rx_status))
+			*msg_ready = true;
+		break;
+	case HDCP_2_2_REP_SEND_RECVID_LIST:
+		if (HDCP_2_2_DP_RXSTATUS_READY(rx_status))
+			*msg_ready = true;
+		break;
+	default:
+		DRM_ERROR("Unidentified msg_id: %d\n", msg_id);
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static ssize_t
+intel_dp_hdcp2_wait_for_msg(struct intel_digital_port *intel_dig_port,
+			    struct hdcp2_dp_msg_data *hdcp2_msg_data)
+{
+	struct intel_dp *dp = &intel_dig_port->dp;
+	struct intel_hdcp *hdcp = &dp->attached_connector->hdcp;
+	u8 msg_id = hdcp2_msg_data->msg_id;
+	int ret, timeout;
+	bool msg_ready = false;
+
+	if (msg_id == HDCP_2_2_AKE_SEND_HPRIME && !hdcp->is_paired)
+		timeout = hdcp2_msg_data->timeout2;
+	else
+		timeout = hdcp2_msg_data->timeout;
+
+	/*
+	 * There is no way to detect the CERT, LPRIME and STREAM_READY
+	 * availability. So Wait for timeout and read the msg.
+	 */
+	if (!hdcp2_msg_data->msg_detectable) {
+		mdelay(timeout);
+		ret = 0;
+	} else {
+		/* TODO: In case if you need to wait on CP_IRQ, do it here */
+		ret = __wait_for(ret =
+				 hdcp2_detect_msg_availability(intel_dig_port,
+							       msg_id,
+							       &msg_ready),
+				 !ret && msg_ready, timeout * 1000,
+				 1000, 5 * 1000);
+
+		if (!msg_ready)
+			ret = -ETIMEDOUT;
+	}
+
+	if (ret)
+		DRM_DEBUG_KMS("msg_id %d, ret %d, timeout(mSec): %d\n",
+			      hdcp2_msg_data->msg_id, ret, timeout);
+
+	return ret;
+}
+
+static struct hdcp2_dp_msg_data *get_hdcp2_dp_msg_data(u8 msg_id)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(hdcp2_msg_data); i++)
+		if (hdcp2_msg_data[i].msg_id == msg_id)
+			return &hdcp2_msg_data[i];
+
+	return NULL;
+}
+
+static
+int intel_dp_hdcp2_write_msg(struct intel_digital_port *intel_dig_port,
+			     void *buf, size_t size)
+{
+	unsigned int offset;
+	u8 *byte = buf;
+	ssize_t ret, bytes_to_write, len;
+	struct hdcp2_dp_msg_data *hdcp2_msg_data;
+
+	hdcp2_msg_data = get_hdcp2_dp_msg_data(*byte);
+	if (!hdcp2_msg_data)
+		return -EINVAL;
+
+	offset = hdcp2_msg_data->offset;
+
+	/* No msg_id in DP HDCP2.2 msgs */
+	bytes_to_write = size - 1;
+	byte++;
+
+	while (bytes_to_write) {
+		len = bytes_to_write > DP_AUX_MAX_PAYLOAD_BYTES ?
+				DP_AUX_MAX_PAYLOAD_BYTES : bytes_to_write;
+
+		ret = drm_dp_dpcd_write(&intel_dig_port->dp.aux,
+					offset, (void *)byte, len);
+		if (ret < 0)
+			return ret;
+
+		bytes_to_write -= ret;
+		byte += ret;
+		offset += ret;
+	}
+
+	return size;
+}
+
+static
+ssize_t get_receiver_id_list_size(struct intel_digital_port *intel_dig_port)
+{
+	u8 rx_info[HDCP_2_2_RXINFO_LEN];
+	u32 dev_cnt;
+	ssize_t ret;
+
+	ret = drm_dp_dpcd_read(&intel_dig_port->dp.aux,
+			       DP_HDCP_2_2_REG_RXINFO_OFFSET,
+			       (void *)rx_info, HDCP_2_2_RXINFO_LEN);
+	if (ret != HDCP_2_2_RXINFO_LEN)
+		return ret >= 0 ? -EIO : ret;
+
+	dev_cnt = (HDCP_2_2_DEV_COUNT_HI(rx_info[0]) << 4 |
+		   HDCP_2_2_DEV_COUNT_LO(rx_info[1]));
+
+	if (dev_cnt > HDCP_2_2_MAX_DEVICE_COUNT)
+		dev_cnt = HDCP_2_2_MAX_DEVICE_COUNT;
+
+	ret = sizeof(struct hdcp2_rep_send_receiverid_list) -
+		HDCP_2_2_RECEIVER_IDS_MAX_LEN +
+		(dev_cnt * HDCP_2_2_RECEIVER_ID_LEN);
+
+	return ret;
+}
+
+static
+int intel_dp_hdcp2_read_msg(struct intel_digital_port *intel_dig_port,
+			    u8 msg_id, void *buf, size_t size)
+{
+	unsigned int offset;
+	u8 *byte = buf;
+	ssize_t ret, bytes_to_recv, len;
+	struct hdcp2_dp_msg_data *hdcp2_msg_data;
+
+	hdcp2_msg_data = get_hdcp2_dp_msg_data(msg_id);
+	if (!hdcp2_msg_data)
+		return -EINVAL;
+	offset = hdcp2_msg_data->offset;
+
+	ret = intel_dp_hdcp2_wait_for_msg(intel_dig_port, hdcp2_msg_data);
+	if (ret < 0)
+		return ret;
+
+	if (msg_id == HDCP_2_2_REP_SEND_RECVID_LIST) {
+		ret = get_receiver_id_list_size(intel_dig_port);
+		if (ret < 0)
+			return ret;
+
+		size = ret;
+	}
+	bytes_to_recv = size - 1;
+
+	/* DP adaptation msgs has no msg_id */
+	byte++;
+
+	while (bytes_to_recv) {
+		len = bytes_to_recv > DP_AUX_MAX_PAYLOAD_BYTES ?
+		      DP_AUX_MAX_PAYLOAD_BYTES : bytes_to_recv;
+
+		ret = drm_dp_dpcd_read(&intel_dig_port->dp.aux, offset,
+				       (void *)byte, len);
+		if (ret < 0) {
+			DRM_DEBUG_KMS("msg_id %d, ret %zd\n", msg_id, ret);
+			return ret;
+		}
+
+		bytes_to_recv -= ret;
+		byte += ret;
+		offset += ret;
+	}
+	byte = buf;
+	*byte = msg_id;
+
+	return size;
+}
+
+static
+int intel_dp_hdcp2_config_stream_type(struct intel_digital_port *intel_dig_port,
+				      void *buf, size_t size)
+{
+	return intel_dp_hdcp2_write_msg(intel_dig_port, buf, size);
+}
+
+static
+int intel_dp_hdcp2_check_link(struct intel_digital_port *intel_dig_port)
+{
+	u8 rx_status;
+	int ret;
+
+	ret = intel_dp_hdcp2_read_rx_status(intel_dig_port, &rx_status);
+	if (ret)
+		return ret;
+
+	if (HDCP_2_2_DP_RXSTATUS_REAUTH_REQ(rx_status))
+		ret = DRM_HDCP_REAUTH_REQUEST;
+	else if (HDCP_2_2_DP_RXSTATUS_LINK_FAILED(rx_status))
+		ret = DRM_HDCP_LINK_INTEGRITY_FAILURE;
+	else if (HDCP_2_2_DP_RXSTATUS_READY(rx_status))
+		ret = DRM_HDCP_TOPOLOGY_CHANGE;
+
+	return ret;
+}
+
+static
+int intel_dp_hdcp2_capable(struct intel_digital_port *intel_dig_port,
+			   bool *capable)
+{
+	u8 rx_caps[3];
+	int ret;
+
+	*capable = false;
+	ret = drm_dp_dpcd_read(&intel_dig_port->dp.aux,
+			       DP_HDCP_2_2_REG_RX_CAPS_OFFSET,
+			       rx_caps, HDCP_2_2_RXCAPS_LEN);
+	if (ret != HDCP_2_2_RXCAPS_LEN)
+		return ret >= 0 ? -EIO : ret;
+
+	if (rx_caps[0] == HDCP_2_2_RX_CAPS_VERSION_VAL &&
+	    HDCP_2_2_DP_HDCP_CAPABLE(rx_caps[2]))
+		*capable = true;
+
+	return 0;
+}
+
 static const struct intel_hdcp_shim intel_dp_hdcp_shim = {
 	.write_an_aksv = intel_dp_hdcp_write_an_aksv,
 	.read_bksv = intel_dp_hdcp_read_bksv,
@@ -5809,6 +6113,12 @@ static const struct intel_hdcp_shim intel_dp_hdcp_shim = {
 	.toggle_signalling = intel_dp_hdcp_toggle_signalling,
 	.check_link = intel_dp_hdcp_check_link,
 	.hdcp_capable = intel_dp_hdcp_capable,
+	.write_2_2_msg = intel_dp_hdcp2_write_msg,
+	.read_2_2_msg = intel_dp_hdcp2_read_msg,
+	.config_stream_type = intel_dp_hdcp2_config_stream_type,
+	.check_2_2_link = intel_dp_hdcp2_check_link,
+	.hdcp_2_2_capable = intel_dp_hdcp2_capable,
+	.protocol = HDCP_PROTOCOL_DP,
 };
 
 static void intel_edp_panel_vdd_sanitize(struct intel_dp *intel_dp)
-- 
2.7.4

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply related	[flat|nested] 103+ messages in thread

* [PATCH v9 17/39] drm/i915: Implement the HDCP2.2 support for HDMI
  2018-12-13  4:01 [PATCH v9 00/39] drm/i915: Implement HDCP2.2 Ramalingam C
                   ` (15 preceding siblings ...)
  2018-12-13  4:01 ` [PATCH v9 16/39] drm/i915: Implement the HDCP2.2 support for DP Ramalingam C
@ 2018-12-13  4:01 ` Ramalingam C
  2018-12-13  4:01 ` [PATCH v9 18/39] drm/i915: Add HDCP2.2 support for DP connectors Ramalingam C
                   ` (25 subsequent siblings)
  42 siblings, 0 replies; 103+ messages in thread
From: Ramalingam C @ 2018-12-13  4:01 UTC (permalink / raw)
  To: intel-gfx, dri-devel, seanpaul, daniel.vetter, tomas.winkler,
	uma.shankar

Implements the HDMI adaptation specific HDCP2.2 operations.

Basically these are DDC read and write for authenticating through
HDCP2.2 messages.

v2: Rebased.
v3:
  No more special handling of Gmbus burst read for AKE_SEND_CERT.
  Style fixed with few naming. [Uma]
  %s/PARING/PAIRING
v4:
  msg_sz is initialized at definition.
  Lookup table is defined for HDMI HDCP2.2 msgs [Daniel].
v5: Rebased.
v6:
  Make a function as inline [Uma]
  %s/uintxx_t/uxx
v7:
  Errors due to sinks are reported as DEBUG logs.
  Adjust to the new mei interface.
v8:
  ARRAY_SIZE for the # of array members [Jon & Daniel].
  hdcp adaptation is added as a const in the hdcp_shim [Daniel]

Signed-off-by: Ramalingam C <ramalingam.c@intel.com>
Reviewed-by: Uma Shankar <uma.shankar@intel.com>
---
 drivers/gpu/drm/i915/intel_hdmi.c | 189 ++++++++++++++++++++++++++++++++++++++
 1 file changed, 189 insertions(+)

diff --git a/drivers/gpu/drm/i915/intel_hdmi.c b/drivers/gpu/drm/i915/intel_hdmi.c
index 38fe0fdbf8d8..5f179f1dd4ad 100644
--- a/drivers/gpu/drm/i915/intel_hdmi.c
+++ b/drivers/gpu/drm/i915/intel_hdmi.c
@@ -1134,6 +1134,190 @@ bool intel_hdmi_hdcp_check_link(struct intel_digital_port *intel_dig_port)
 	return true;
 }
 
+static struct hdcp2_hdmi_msg_data {
+	u8 msg_id;
+	u32 timeout;
+	u32 timeout2;
+	} hdcp2_msg_data[] = {
+		{HDCP_2_2_AKE_INIT, 0, 0},
+		{HDCP_2_2_AKE_SEND_CERT, HDCP_2_2_CERT_TIMEOUT_MS, 0},
+		{HDCP_2_2_AKE_NO_STORED_KM, 0, 0},
+		{HDCP_2_2_AKE_STORED_KM, 0, 0},
+		{HDCP_2_2_AKE_SEND_HPRIME, HDCP_2_2_HPRIME_PAIRED_TIMEOUT_MS,
+				HDCP_2_2_HPRIME_NO_PAIRED_TIMEOUT_MS},
+		{HDCP_2_2_AKE_SEND_PAIRING_INFO, HDCP_2_2_PAIRING_TIMEOUT_MS,
+				0},
+		{HDCP_2_2_LC_INIT, 0, 0},
+		{HDCP_2_2_LC_SEND_LPRIME, HDCP_2_2_HDMI_LPRIME_TIMEOUT_MS, 0},
+		{HDCP_2_2_SKE_SEND_EKS, 0, 0},
+		{HDCP_2_2_REP_SEND_RECVID_LIST,
+				HDCP_2_2_RECVID_LIST_TIMEOUT_MS, 0},
+		{HDCP_2_2_REP_SEND_ACK, 0, 0},
+		{HDCP_2_2_REP_STREAM_MANAGE, 0, 0},
+		{HDCP_2_2_REP_STREAM_READY, HDCP_2_2_STREAM_READY_TIMEOUT_MS,
+				0},
+	};
+
+static
+int intel_hdmi_hdcp2_read_rx_status(struct intel_digital_port *intel_dig_port,
+				    uint8_t *rx_status)
+{
+	return intel_hdmi_hdcp_read(intel_dig_port,
+				    HDCP_2_2_HDMI_REG_RXSTATUS_OFFSET,
+				    rx_status,
+				    HDCP_2_2_HDMI_RXSTATUS_LEN);
+}
+
+static int get_hdcp2_msg_timeout(u8 msg_id, bool is_paired)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(hdcp2_msg_data); i++)
+		if (hdcp2_msg_data[i].msg_id == msg_id &&
+		    (msg_id != HDCP_2_2_AKE_SEND_HPRIME || is_paired))
+			return hdcp2_msg_data[i].timeout;
+		else if (hdcp2_msg_data[i].msg_id == msg_id)
+			return hdcp2_msg_data[i].timeout2;
+
+	return -EINVAL;
+}
+
+static inline
+int hdcp2_detect_msg_availability(struct intel_digital_port *intel_digital_port,
+				  u8 msg_id, bool *msg_ready,
+				  ssize_t *msg_sz)
+{
+	u8 rx_status[HDCP_2_2_HDMI_RXSTATUS_LEN];
+	int ret;
+
+	ret = intel_hdmi_hdcp2_read_rx_status(intel_digital_port, rx_status);
+	if (ret < 0) {
+		DRM_DEBUG_KMS("rx_status read failed. Err %d\n", ret);
+		return ret;
+	}
+
+	*msg_sz = ((HDCP_2_2_HDMI_RXSTATUS_MSG_SZ_HI(rx_status[1]) << 8) |
+		  rx_status[0]);
+
+	if (msg_id == HDCP_2_2_REP_SEND_RECVID_LIST)
+		*msg_ready = (HDCP_2_2_HDMI_RXSTATUS_READY(rx_status[1]) &&
+			     *msg_sz);
+	else
+		*msg_ready = *msg_sz;
+
+	return 0;
+}
+
+static ssize_t
+intel_hdmi_hdcp2_wait_for_msg(struct intel_digital_port *intel_dig_port,
+			      u8 msg_id, bool paired)
+{
+	bool msg_ready = false;
+	int timeout, ret;
+	ssize_t msg_sz = 0;
+
+	timeout = get_hdcp2_msg_timeout(msg_id, paired);
+	if (timeout < 0)
+		return timeout;
+
+	ret = __wait_for(ret = hdcp2_detect_msg_availability(intel_dig_port,
+							     msg_id, &msg_ready,
+							     &msg_sz),
+			 !ret && msg_ready && msg_sz, timeout * 1000,
+			 1000, 5 * 1000);
+	if (ret)
+		DRM_DEBUG_KMS("msg_id: %d, ret: %d, timeout: %d\n",
+			      msg_id, ret, timeout);
+
+	return ret ? ret : msg_sz;
+}
+
+static
+int intel_hdmi_hdcp2_write_msg(struct intel_digital_port *intel_dig_port,
+			       void *buf, size_t size)
+{
+	unsigned int offset;
+
+	offset = HDCP_2_2_HDMI_REG_WR_MSG_OFFSET;
+	return intel_hdmi_hdcp_write(intel_dig_port, offset, buf, size);
+}
+
+static
+int intel_hdmi_hdcp2_read_msg(struct intel_digital_port *intel_dig_port,
+			      u8 msg_id, void *buf, size_t size)
+{
+	struct intel_hdmi *hdmi = &intel_dig_port->hdmi;
+	struct intel_hdcp *hdcp = &hdmi->attached_connector->hdcp;
+	unsigned int offset;
+	ssize_t ret;
+
+	ret = intel_hdmi_hdcp2_wait_for_msg(intel_dig_port, msg_id,
+					    hdcp->is_paired);
+	if (ret < 0)
+		return ret;
+
+	/*
+	 * Available msg size should be equal to or lesser than the
+	 * available buffer.
+	 */
+	if (ret > size) {
+		DRM_DEBUG_KMS("msg_sz(%zd) is more than exp size(%zu)\n",
+			      ret, size);
+		return -1;
+	}
+
+	offset = HDCP_2_2_HDMI_REG_RD_MSG_OFFSET;
+	ret = intel_hdmi_hdcp_read(intel_dig_port, offset, buf, ret);
+	if (ret)
+		DRM_DEBUG_KMS("Failed to read msg_id: %d(%zd)\n", msg_id, ret);
+
+	return ret;
+}
+
+static
+int intel_hdmi_hdcp2_check_link(struct intel_digital_port *intel_dig_port)
+{
+	u8 rx_status[HDCP_2_2_HDMI_RXSTATUS_LEN];
+	int ret;
+
+	ret = intel_hdmi_hdcp2_read_rx_status(intel_dig_port, rx_status);
+	if (ret)
+		return ret;
+
+	/*
+	 * Re-auth request and Link Integrity Failures are represented by
+	 * same bit. i.e reauth_req.
+	 */
+	if (HDCP_2_2_HDMI_RXSTATUS_REAUTH_REQ(rx_status[1]))
+		ret = DRM_HDCP_REAUTH_REQUEST;
+	else if (HDCP_2_2_HDMI_RXSTATUS_READY(rx_status[1]))
+		ret = DRM_HDCP_TOPOLOGY_CHANGE;
+
+	return ret;
+}
+
+static
+int intel_hdmi_hdcp2_capable(struct intel_digital_port *intel_dig_port,
+			     bool *capable)
+{
+	u8 hdcp2_version;
+	int ret;
+
+	*capable = false;
+	ret = intel_hdmi_hdcp_read(intel_dig_port, HDCP_2_2_HDMI_REG_VER_OFFSET,
+				   &hdcp2_version, sizeof(hdcp2_version));
+	if (!ret && hdcp2_version & HDCP_2_2_HDMI_SUPPORT_MASK)
+		*capable = true;
+
+	return ret;
+}
+
+static inline
+enum hdcp_wired_protocol intel_hdmi_hdcp2_protocol(void)
+{
+	return HDCP_PROTOCOL_HDMI;
+}
+
 static const struct intel_hdcp_shim intel_hdmi_hdcp_shim = {
 	.write_an_aksv = intel_hdmi_hdcp_write_an_aksv,
 	.read_bksv = intel_hdmi_hdcp_read_bksv,
@@ -1145,6 +1329,11 @@ static const struct intel_hdcp_shim intel_hdmi_hdcp_shim = {
 	.read_v_prime_part = intel_hdmi_hdcp_read_v_prime_part,
 	.toggle_signalling = intel_hdmi_hdcp_toggle_signalling,
 	.check_link = intel_hdmi_hdcp_check_link,
+	.write_2_2_msg = intel_hdmi_hdcp2_write_msg,
+	.read_2_2_msg = intel_hdmi_hdcp2_read_msg,
+	.check_2_2_link	= intel_hdmi_hdcp2_check_link,
+	.hdcp_2_2_capable = intel_hdmi_hdcp2_capable,
+	.protocol = HDCP_PROTOCOL_HDMI,
 };
 
 static void intel_hdmi_prepare(struct intel_encoder *encoder,
-- 
2.7.4

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply related	[flat|nested] 103+ messages in thread

* [PATCH v9 18/39] drm/i915: Add HDCP2.2 support for DP connectors
  2018-12-13  4:01 [PATCH v9 00/39] drm/i915: Implement HDCP2.2 Ramalingam C
                   ` (16 preceding siblings ...)
  2018-12-13  4:01 ` [PATCH v9 17/39] drm/i915: Implement the HDCP2.2 support for HDMI Ramalingam C
@ 2018-12-13  4:01 ` Ramalingam C
  2018-12-13  4:01 ` [PATCH v9 19/39] drm/i915: Add HDCP2.2 support for HDMI connectors Ramalingam C
                   ` (24 subsequent siblings)
  42 siblings, 0 replies; 103+ messages in thread
From: Ramalingam C @ 2018-12-13  4:01 UTC (permalink / raw)
  To: intel-gfx, dri-devel, seanpaul, daniel.vetter, tomas.winkler,
	uma.shankar

On DP connector init, intel_hdcp_init is passed with a flag for hdcp2.2
support based on the platform capability.

v2:
  Rebased.
v3:
  Collected the reviewed-by received.

Signed-off-by: Ramalingam C <ramalingam.c@intel.com>
Reviewed-by: Uma Shankar <uma.shankar@intel.com>
---
 drivers/gpu/drm/i915/intel_dp.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
index a8ace7d85918..87078dcc372c 100644
--- a/drivers/gpu/drm/i915/intel_dp.c
+++ b/drivers/gpu/drm/i915/intel_dp.c
@@ -7213,7 +7213,7 @@ intel_dp_init_connector(struct intel_digital_port *intel_dig_port,
 
 	if (is_hdcp_supported(dev_priv, port) && !intel_dp_is_edp(intel_dp)) {
 		int ret = intel_hdcp_init(intel_connector, &intel_dp_hdcp_shim,
-					  false);
+					  is_hdcp2_supported(dev_priv));
 		if (ret)
 			DRM_DEBUG_KMS("HDCP init failed, skipping.\n");
 	}
-- 
2.7.4

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply related	[flat|nested] 103+ messages in thread

* [PATCH v9 19/39] drm/i915: Add HDCP2.2 support for HDMI connectors
  2018-12-13  4:01 [PATCH v9 00/39] drm/i915: Implement HDCP2.2 Ramalingam C
                   ` (17 preceding siblings ...)
  2018-12-13  4:01 ` [PATCH v9 18/39] drm/i915: Add HDCP2.2 support for DP connectors Ramalingam C
@ 2018-12-13  4:01 ` Ramalingam C
  2018-12-13  4:01 ` [PATCH v9 20/39] mei: bus: whitelist hdcp client Ramalingam C
                   ` (23 subsequent siblings)
  42 siblings, 0 replies; 103+ messages in thread
From: Ramalingam C @ 2018-12-13  4:01 UTC (permalink / raw)
  To: intel-gfx, dri-devel, seanpaul, daniel.vetter, tomas.winkler,
	uma.shankar

On HDMI connector init, intel_hdcp_init is passed with a flag for hdcp2.2
support based on the platform capability.

v2:
  Rebased.
v3:
  Collected the reviewed-by received.

Signed-off-by: Ramalingam C <ramalingam.c@intel.com>
Reviewed-by: Uma Shankar <uma.shankar@intel.com>
---
 drivers/gpu/drm/i915/intel_hdmi.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/i915/intel_hdmi.c b/drivers/gpu/drm/i915/intel_hdmi.c
index 5f179f1dd4ad..0c3b287bff24 100644
--- a/drivers/gpu/drm/i915/intel_hdmi.c
+++ b/drivers/gpu/drm/i915/intel_hdmi.c
@@ -2623,7 +2623,8 @@ void intel_hdmi_init_connector(struct intel_digital_port *intel_dig_port,
 
 	if (is_hdcp_supported(dev_priv, port)) {
 		int ret = intel_hdcp_init(intel_connector,
-					  &intel_hdmi_hdcp_shim, false);
+					 &intel_hdmi_hdcp_shim,
+					 is_hdcp2_supported(dev_priv));
 		if (ret)
 			DRM_DEBUG_KMS("HDCP init failed, skipping.\n");
 	}
-- 
2.7.4

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply related	[flat|nested] 103+ messages in thread

* [PATCH v9 20/39] mei: bus: whitelist hdcp client
  2018-12-13  4:01 [PATCH v9 00/39] drm/i915: Implement HDCP2.2 Ramalingam C
                   ` (18 preceding siblings ...)
  2018-12-13  4:01 ` [PATCH v9 19/39] drm/i915: Add HDCP2.2 support for HDMI connectors Ramalingam C
@ 2018-12-13  4:01 ` Ramalingam C
  2018-12-13  4:01 ` [PATCH v9 21/39] mei: bus: export to_mei_cl_device for mei client device drivers Ramalingam C
                   ` (22 subsequent siblings)
  42 siblings, 0 replies; 103+ messages in thread
From: Ramalingam C @ 2018-12-13  4:01 UTC (permalink / raw)
  To: intel-gfx, dri-devel, seanpaul, daniel.vetter, tomas.winkler,
	uma.shankar

From: Tomas Winkler <tomas.winkler@intel.com>

Whitelist HDCP client for in kernel drm use

v2:
  Rebased.

Signed-off-by: Tomas Winkler <tomas.winkler@intel.com>
---
 drivers/misc/mei/bus-fixup.c | 16 ++++++++++++++++
 1 file changed, 16 insertions(+)

diff --git a/drivers/misc/mei/bus-fixup.c b/drivers/misc/mei/bus-fixup.c
index 80215c312f0e..5fcac02233af 100644
--- a/drivers/misc/mei/bus-fixup.c
+++ b/drivers/misc/mei/bus-fixup.c
@@ -40,6 +40,9 @@ static const uuid_le mei_nfc_info_guid = MEI_UUID_NFC_INFO;
 #define MEI_UUID_MKHIF_FIX UUID_LE(0x55213584, 0x9a29, 0x4916, \
 			0xba, 0xdf, 0xf, 0xb7, 0xed, 0x68, 0x2a, 0xeb)
 
+#define MEI_UUID_HDCP UUID_LE(0xB638AB7E, 0x94E2, 0x4EA2, \
+			      0xA5, 0x52, 0xD1, 0xC5, 0x4B, 0x62, 0x7F, 0x04)
+
 #define MEI_UUID_ANY NULL_UUID_LE
 
 /**
@@ -71,6 +74,18 @@ static void blacklist(struct mei_cl_device *cldev)
 	cldev->do_match = 0;
 }
 
+/**
+ * whitelist - forcefully whitelist client
+ *
+ * @cldev: me clients device
+ */
+static void whitelist(struct mei_cl_device *cldev)
+{
+	dev_dbg(&cldev->dev, "running hook %s\n", __func__);
+
+	cldev->do_match = 1;
+}
+
 #define OSTYPE_LINUX    2
 struct mei_os_ver {
 	__le16 build;
@@ -472,6 +487,7 @@ static struct mei_fixup {
 	MEI_FIXUP(MEI_UUID_NFC_HCI, mei_nfc),
 	MEI_FIXUP(MEI_UUID_WD, mei_wd),
 	MEI_FIXUP(MEI_UUID_MKHIF_FIX, mei_mkhi_fix),
+	MEI_FIXUP(MEI_UUID_HDCP, whitelist),
 };
 
 /**
-- 
2.7.4

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply related	[flat|nested] 103+ messages in thread

* [PATCH v9 21/39] mei: bus: export to_mei_cl_device for mei client device drivers
  2018-12-13  4:01 [PATCH v9 00/39] drm/i915: Implement HDCP2.2 Ramalingam C
                   ` (19 preceding siblings ...)
  2018-12-13  4:01 ` [PATCH v9 20/39] mei: bus: whitelist hdcp client Ramalingam C
@ 2018-12-13  4:01 ` Ramalingam C
  2018-12-13  4:01 ` [PATCH v9 22/39] misc/mei/hdcp: Client driver for HDCP application Ramalingam C
                   ` (21 subsequent siblings)
  42 siblings, 0 replies; 103+ messages in thread
From: Ramalingam C @ 2018-12-13  4:01 UTC (permalink / raw)
  To: intel-gfx, dri-devel, seanpaul, daniel.vetter, tomas.winkler,
	uma.shankar

From: Tomas Winkler <tomas.winkler@intel.com>

Export to_mei_cl_device macro, it is needed also in mei client drivers.

Signed-off-by: Tomas Winkler <tomas.winkler@intel.com>
---
 drivers/misc/mei/bus.c     | 1 -
 include/linux/mei_cl_bus.h | 2 ++
 2 files changed, 2 insertions(+), 1 deletion(-)

diff --git a/drivers/misc/mei/bus.c b/drivers/misc/mei/bus.c
index fc3872fe7b25..e5456faf00e6 100644
--- a/drivers/misc/mei/bus.c
+++ b/drivers/misc/mei/bus.c
@@ -28,7 +28,6 @@
 #include "client.h"
 
 #define to_mei_cl_driver(d) container_of(d, struct mei_cl_driver, driver)
-#define to_mei_cl_device(d) container_of(d, struct mei_cl_device, dev)
 
 /**
  * __mei_cl_send - internal client send (write)
diff --git a/include/linux/mei_cl_bus.h b/include/linux/mei_cl_bus.h
index 7fde40e17c8b..03b6ba2a63f8 100644
--- a/include/linux/mei_cl_bus.h
+++ b/include/linux/mei_cl_bus.h
@@ -55,6 +55,8 @@ struct mei_cl_device {
 	void *priv_data;
 };
 
+#define to_mei_cl_device(d) container_of(d, struct mei_cl_device, dev)
+
 struct mei_cl_driver {
 	struct device_driver driver;
 	const char *name;
-- 
2.7.4

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply related	[flat|nested] 103+ messages in thread

* [PATCH v9 22/39] misc/mei/hdcp: Client driver for HDCP application
  2018-12-13  4:01 [PATCH v9 00/39] drm/i915: Implement HDCP2.2 Ramalingam C
                   ` (20 preceding siblings ...)
  2018-12-13  4:01 ` [PATCH v9 21/39] mei: bus: export to_mei_cl_device for mei client device drivers Ramalingam C
@ 2018-12-13  4:01 ` Ramalingam C
  2018-12-13  4:01 ` [PATCH v9 23/39] misc/mei/hdcp: Define ME FW interface for HDCP2.2 Ramalingam C
                   ` (20 subsequent siblings)
  42 siblings, 0 replies; 103+ messages in thread
From: Ramalingam C @ 2018-12-13  4:01 UTC (permalink / raw)
  To: intel-gfx, dri-devel, seanpaul, daniel.vetter, tomas.winkler,
	uma.shankar

ME FW is contributes a vital role in HDCP2.2 authentication.
HDCP2.2 driver needs to communicate to ME FW for each step of the
HDCP2.2 authentication.

ME FW prepare and HDCP2.2 authentication  parameters and encrypt them
as per spec. With such parameter Driver prepares HDCP2.2 auth messages
and communicate with HDCP2.2 sink.

Similarly HDCP2. sink's response is shared with ME FW for decrypt and
verification.

Once All the steps of HDCP2.2 authentications are complete on driver's
request ME FW will configure the port as authenticated and supply the
HDCP keys to the Gen HW for encryption.

Only after this stage HDCP2.2 driver can start the HDCP2.2 encryption
for a port.

ME FW is interfaced to kernel through MEI Bus Driver. To obtain the
HDCP2.2 services from the ME FW through MEI Bus driver MEI Client
Driver is developed.

v2:
  hdcp files are moved to drivers/misc/mei/hdcp/ [Tomas]
v3:
  Squashed the Kbuild support [Tomas]
  UUID renamed and Module License is modified [Tomas]
  drv_data is set to null at remove [Tomas]
v4:
  Module name is changed to "MEI HDCP"
  I915 Selects the MEI_HDCP
v5:
  Remove redundant text from the License header
  Fix malformed licence
  Removed the drv_data resetting.
v6:
  K-Doc addition. [Tomas]

Signed-off-by: Ramalingam C <ramalingam.c@intel.com>
Signed-off-by: Tomas Winkler <tomas.winkler@intel.com>
---
 drivers/misc/mei/Kconfig         |  7 +++++
 drivers/misc/mei/Makefile        |  2 ++
 drivers/misc/mei/hdcp/Makefile   |  7 +++++
 drivers/misc/mei/hdcp/mei_hdcp.c | 65 ++++++++++++++++++++++++++++++++++++++++
 4 files changed, 81 insertions(+)
 create mode 100644 drivers/misc/mei/hdcp/Makefile
 create mode 100644 drivers/misc/mei/hdcp/mei_hdcp.c

diff --git a/drivers/misc/mei/Kconfig b/drivers/misc/mei/Kconfig
index c49e1d2269af..9c518b7f0011 100644
--- a/drivers/misc/mei/Kconfig
+++ b/drivers/misc/mei/Kconfig
@@ -43,3 +43,10 @@ config INTEL_MEI_TXE
 
 	  Supported SoCs:
 	  Intel Bay Trail
+
+config INTEL_MEI_HDCP
+	tristate "Intel HDCP2.2 services of ME Interface"
+	select INTEL_MEI_ME
+	depends on DRM_I915
+	help
+	  MEI Support for HDCP2.2 Services on Intel SoCs.
diff --git a/drivers/misc/mei/Makefile b/drivers/misc/mei/Makefile
index cd6825afa8e1..e64d1212fb85 100644
--- a/drivers/misc/mei/Makefile
+++ b/drivers/misc/mei/Makefile
@@ -23,3 +23,5 @@ mei-txe-objs += hw-txe.o
 
 mei-$(CONFIG_EVENT_TRACING) += mei-trace.o
 CFLAGS_mei-trace.o = -I$(src)
+
+obj-$(CONFIG_INTEL_MEI_HDCP) += hdcp/
diff --git a/drivers/misc/mei/hdcp/Makefile b/drivers/misc/mei/hdcp/Makefile
new file mode 100644
index 000000000000..c1a86dd9782b
--- /dev/null
+++ b/drivers/misc/mei/hdcp/Makefile
@@ -0,0 +1,7 @@
+# SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause
+#
+# Copyright (c) 2017-2018, Intel Corporation.
+#
+# Makefile - HDCP client driver for Intel MEI Bus Driver.
+
+obj-$(CONFIG_INTEL_MEI_HDCP) += mei_hdcp.o
diff --git a/drivers/misc/mei/hdcp/mei_hdcp.c b/drivers/misc/mei/hdcp/mei_hdcp.c
new file mode 100644
index 000000000000..6e7101512842
--- /dev/null
+++ b/drivers/misc/mei/hdcp/mei_hdcp.c
@@ -0,0 +1,65 @@
+/* SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) */
+/*
+ * Copyright © 2017-2018 Intel Corporation
+ *
+ * Mei_hdcp.c: HDCP client driver for mei bus
+ *
+ * Authors:
+ * Ramalingam C <ramalingam.c@intel.com>
+ */
+
+/**
+ * DOC: MEI_HDCP Client Driver
+ *
+ * This is a client driver to the mei_bus to make the HDCP2.2 services of
+ * ME FW available for the interested consumers like I915.
+ *
+ * This module will act as a translation layer between HDCP protocol
+ * implementor(I915) and ME FW by translating HDCP2.2 authentication
+ * messages to ME FW command payloads and vice versa.
+ */
+
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/uuid.h>
+#include <linux/mei_cl_bus.h>
+
+static int mei_hdcp_probe(struct mei_cl_device *cldev,
+			  const struct mei_cl_device_id *id)
+{
+	int ret;
+
+	ret = mei_cldev_enable(cldev);
+	if (ret < 0)
+		dev_err(&cldev->dev, "mei_cldev_enable Failed. %d\n", ret);
+
+	return ret;
+}
+
+static int mei_hdcp_remove(struct mei_cl_device *cldev)
+{
+	return mei_cldev_disable(cldev);
+}
+
+#define MEI_UUID_HDCP		UUID_LE(0xB638AB7E, 0x94E2, 0x4EA2, 0xA5, \
+					0x52, 0xD1, 0xC5, 0x4B, \
+					0x62, 0x7F, 0x04)
+
+static struct mei_cl_device_id mei_hdcp_tbl[] = {
+	{ .uuid = MEI_UUID_HDCP, .version = MEI_CL_VERSION_ANY },
+	{ }
+};
+MODULE_DEVICE_TABLE(mei, mei_hdcp_tbl);
+
+static struct mei_cl_driver mei_hdcp_driver = {
+	.id_table	= mei_hdcp_tbl,
+	.name		= KBUILD_MODNAME,
+	.probe		= mei_hdcp_probe,
+	.remove		= mei_hdcp_remove,
+};
+
+module_mei_cl_driver(mei_hdcp_driver);
+
+MODULE_AUTHOR("Intel Corporation");
+MODULE_LICENSE("Dual BSD/GPL");
+MODULE_DESCRIPTION("MEI HDCP");
-- 
2.7.4

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply related	[flat|nested] 103+ messages in thread

* [PATCH v9 23/39] misc/mei/hdcp: Define ME FW interface for HDCP2.2
  2018-12-13  4:01 [PATCH v9 00/39] drm/i915: Implement HDCP2.2 Ramalingam C
                   ` (21 preceding siblings ...)
  2018-12-13  4:01 ` [PATCH v9 22/39] misc/mei/hdcp: Client driver for HDCP application Ramalingam C
@ 2018-12-13  4:01 ` Ramalingam C
  2018-12-13  4:01 ` [PATCH v9 24/39] misc/mei/hdcp: Initiate Wired HDCP2.2 Tx Session Ramalingam C
                   ` (19 subsequent siblings)
  42 siblings, 0 replies; 103+ messages in thread
From: Ramalingam C @ 2018-12-13  4:01 UTC (permalink / raw)
  To: intel-gfx, dri-devel, seanpaul, daniel.vetter, tomas.winkler,
	uma.shankar

Defines the HDCP specific ME FW interfaces such as Request CMDs,
payload structure for CMDs and their response status codes.

This patch defines payload size(Excluding the Header)for each WIRED
HDCP2.2 CMDs.

v2: Rebased.
v3:
  Extra comments are removed.
v4:
  %s/\/\*\*/\/\*
v5:
  Extra lines are removed.
v6:
  Remove redundant text from the License header
  %s/LPRIME_HALF/V_PRIME_HALF
  %s/uintxx_t/uxx
v7:
  Extra taps removed.

Signed-off-by: Ramalingam C <ramalingam.c@intel.com>
---
 drivers/misc/mei/hdcp/mei_hdcp.h | 366 +++++++++++++++++++++++++++++++++++++++
 1 file changed, 366 insertions(+)
 create mode 100644 drivers/misc/mei/hdcp/mei_hdcp.h

diff --git a/drivers/misc/mei/hdcp/mei_hdcp.h b/drivers/misc/mei/hdcp/mei_hdcp.h
new file mode 100644
index 000000000000..d1456e3dbf22
--- /dev/null
+++ b/drivers/misc/mei/hdcp/mei_hdcp.h
@@ -0,0 +1,366 @@
+/* SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) */
+/*
+ * Copyright © 2017-2018 Intel Corporation
+ *
+ * Authors:
+ * Ramalingam C <ramalingam.c@intel.com>
+ */
+
+#ifndef __MEI_HDCP_H__
+#define __MEI_HDCP_H__
+
+#include <drm/drm_hdcp.h>
+
+/* me_hdcp_status: Enumeration of all HDCP Status Codes */
+enum me_hdcp_status {
+	ME_HDCP_STATUS_SUCCESS			= 0x0000,
+
+	/* WiDi Generic Status Codes */
+	ME_HDCP_STATUS_INTERNAL_ERROR		= 0x1000,
+	ME_HDCP_STATUS_UNKNOWN_ERROR		= 0x1001,
+	ME_HDCP_STATUS_INCORRECT_API_VERSION	= 0x1002,
+	ME_HDCP_STATUS_INVALID_FUNCTION		= 0x1003,
+	ME_HDCP_STATUS_INVALID_BUFFER_LENGTH	= 0x1004,
+	ME_HDCP_STATUS_INVALID_PARAMS		= 0x1005,
+	ME_HDCP_STATUS_AUTHENTICATION_FAILED	= 0x1006,
+
+	/* WiDi Status Codes */
+	ME_HDCP_INVALID_SESSION_STATE		= 0x6000,
+	ME_HDCP_SRM_FRAGMENT_UNEXPECTED		= 0x6001,
+	ME_HDCP_SRM_INVALID_LENGTH		= 0x6002,
+	ME_HDCP_SRM_FRAGMENT_OFFSET_INVALID	= 0x6003,
+	ME_HDCP_SRM_VERIFICATION_FAILED		= 0x6004,
+	ME_HDCP_SRM_VERSION_TOO_OLD		= 0x6005,
+	ME_HDCP_RX_CERT_VERIFICATION_FAILED	= 0x6006,
+	ME_HDCP_RX_REVOKED			= 0x6007,
+	ME_HDCP_H_VERIFICATION_FAILED		= 0x6008,
+	ME_HDCP_REPEATER_CHECK_UNEXPECTED	= 0x6009,
+	ME_HDCP_TOPOLOGY_MAX_EXCEEDED		= 0x600A,
+	ME_HDCP_V_VERIFICATION_FAILED		= 0x600B,
+	ME_HDCP_L_VERIFICATION_FAILED		= 0x600C,
+	ME_HDCP_STREAM_KEY_ALLOC_FAILED		= 0x600D,
+	ME_HDCP_BASE_KEY_RESET_FAILED		= 0x600E,
+	ME_HDCP_NONCE_GENERATION_FAILED		= 0x600F,
+	ME_HDCP_STATUS_INVALID_E_KEY_STATE	= 0x6010,
+	ME_HDCP_STATUS_INVALID_CS_ICV		= 0x6011,
+	ME_HDCP_STATUS_INVALID_KB_KEY_STATE	= 0x6012,
+	ME_HDCP_STATUS_INVALID_PAVP_MODE_ICV	= 0x6013,
+	ME_HDCP_STATUS_INVALID_PAVP_MODE	= 0x6014,
+	ME_HDCP_STATUS_LC_MAX_ATTEMPTS		= 0x6015,
+
+	/* New status for HDCP 2.1 */
+	ME_HDCP_STATUS_MISMATCH_IN_M		= 0x6016,
+
+	/* New status code for HDCP 2.2 Rx */
+	ME_HDCP_STATUS_RX_PROV_NOT_ALLOWED	= 0x6017,
+	ME_HDCP_STATUS_RX_PROV_WRONG_SUBJECT	= 0x6018,
+	ME_HDCP_RX_NEEDS_PROVISIONING		= 0x6019,
+	ME_HDCP_BKSV_ICV_AUTH_FAILED		= 0x6020,
+	ME_HDCP_STATUS_INVALID_STREAM_ID	= 0x6021,
+	ME_HDCP_STATUS_CHAIN_NOT_INITIALIZED	= 0x6022,
+	ME_HDCP_FAIL_NOT_EXPECTED		= 0x6023,
+	ME_HDCP_FAIL_HDCP_OFF			= 0x6024,
+	ME_HDCP_FAIL_INVALID_PAVP_MEMORY_MODE	= 0x6025,
+	ME_HDCP_FAIL_AES_ECB_FAILURE		= 0x6026,
+	ME_HDCP_FEATURE_NOT_SUPPORTED		= 0x6027,
+	ME_HDCP_DMA_READ_ERROR			= 0x6028,
+	ME_HDCP_DMA_WRITE_ERROR			= 0x6029,
+	ME_HDCP_FAIL_INVALID_PACKET_SIZE	= 0x6030,
+	ME_HDCP_H264_PARSING_ERROR		= 0x6031,
+	ME_HDCP_HDCP2_ERRATA_VIDEO_VIOLATION	= 0x6032,
+	ME_HDCP_HDCP2_ERRATA_AUDIO_VIOLATION	= 0x6033,
+	ME_HDCP_TX_ACTIVE_ERROR			= 0x6034,
+	ME_HDCP_MODE_CHANGE_ERROR		= 0x6035,
+	ME_HDCP_STREAM_TYPE_ERROR		= 0x6036,
+	ME_HDCP_STREAM_MANAGE_NOT_POSSIBLE	= 0x6037,
+
+	ME_HDCP_STATUS_PORT_INVALID_COMMAND	= 0x6038,
+	ME_HDCP_STATUS_UNSUPPORTED_PROTOCOL	= 0x6039,
+	ME_HDCP_STATUS_INVALID_PORT_INDEX	= 0x603a,
+	ME_HDCP_STATUS_TX_AUTH_NEEDED		= 0x603b,
+	ME_HDCP_STATUS_NOT_INTEGRATED_PORT	= 0x603c,
+	ME_HDCP_STATUS_SESSION_MAX_REACHED	= 0x603d,
+
+	/* hdcp capable bit is not set in rx_caps(error is unique to DP) */
+	ME_HDCP_STATUS_NOT_HDCP_CAPABLE		= 0x6041,
+
+	ME_HDCP_STATUS_INVALID_STREAM_COUNT	= 0x6042,
+};
+
+#define HDCP_API_VERSION				0x00010000
+
+#define HDCP_M_LEN					16
+#define HDCP_KH_LEN					16
+
+/* Payload Buffer size(Excluding Header) for CMDs and corresponding response */
+/* Wired_Tx_AKE  */
+#define	WIRED_CMD_BUF_LEN_INITIATE_HDCP2_SESSION_IN	(4 + 1)
+#define	WIRED_CMD_BUF_LEN_INITIATE_HDCP2_SESSION_OUT	(4 + 8 + 3)
+
+#define	WIRED_CMD_BUF_LEN_VERIFY_RECEIVER_CERT_IN	(4 + 522 + 8 + 3)
+#define	WIRED_CMD_BUF_LEN_VERIFY_RECEIVER_CERT_MIN_OUT	(4 + 1 + 3 + 16 + 16)
+#define	WIRED_CMD_BUF_LEN_VERIFY_RECEIVER_CERT_MAX_OUT	(4 + 1 + 3 + 128)
+
+#define	WIRED_CMD_BUF_LEN_AKE_SEND_HPRIME_IN		(4 + 32)
+#define	WIRED_CMD_BUF_LEN_AKE_SEND_HPRIME_OUT		(4)
+
+#define	WIRED_CMD_BUF_LEN_SEND_PAIRING_INFO_IN		(4 + 16)
+#define	WIRED_CMD_BUF_LEN_SEND_PAIRING_INFO_OUT		(4)
+
+#define	WIRED_CMD_BUF_LEN_CLOSE_SESSION_IN		(4)
+#define	WIRED_CMD_BUF_LEN_CLOSE_SESSION_OUT		(4)
+
+/* Wired_Tx_LC */
+#define	WIRED_CMD_BUF_LEN_INIT_LOCALITY_CHECK_IN	(4)
+#define	WIRED_CMD_BUF_LEN_INIT_LOCALITY_CHECK_OUT	(4 + 8)
+
+#define	WIRED_CMD_BUF_LEN_VALIDATE_LOCALITY_IN		(4 + 32)
+#define	WIRED_CMD_BUF_LEN_VALIDATE_LOCALITY_OUT		(4)
+
+/* Wired_Tx_SKE */
+#define	WIRED_CMD_BUF_LEN_GET_SESSION_KEY_IN		(4)
+#define	WIRED_CMD_BUF_LEN_GET_SESSION_KEY_OUT		(4 + 16 + 8)
+
+/* Wired_Tx_SKE */
+#define	WIRED_CMD_BUF_LEN_ENABLE_AUTH_IN		(4 + 1)
+#define	WIRED_CMD_BUF_LEN_ENABLE_AUTH_OUT		(4)
+
+/* Wired_Tx_Repeater */
+#define	WIRED_CMD_BUF_LEN_VERIFY_REPEATER_IN		(4 + 2 + 3 + 16 + 155)
+#define	WIRED_CMD_BUF_LEN_VERIFY_REPEATER_OUT		(4 + 1 + 16)
+
+#define	WIRED_CMD_BUF_LEN_REPEATER_AUTH_STREAM_REQ_MIN_IN	(4 + 3 + \
+								32 + 2 + 2)
+
+#define	WIRED_CMD_BUF_LEN_REPEATER_AUTH_STREAM_REQ_OUT		(4)
+
+/* hdcp_command_id: Enumeration of all WIRED HDCP Command IDs */
+enum hdcp_command_id {
+	_WIDI_COMMAND_BASE		= 0x00030000,
+	WIDI_INITIATE_HDCP2_SESSION	= _WIDI_COMMAND_BASE,
+	HDCP_GET_SRM_STATUS,
+	HDCP_SEND_SRM_FRAGMENT,
+
+	/* The wired HDCP Tx commands */
+	_WIRED_COMMAND_BASE		= 0x00031000,
+	WIRED_INITIATE_HDCP2_SESSION	= _WIRED_COMMAND_BASE,
+	WIRED_VERIFY_RECEIVER_CERT,
+	WIRED_AKE_SEND_HPRIME,
+	WIRED_AKE_SEND_PAIRING_INFO,
+	WIRED_INIT_LOCALITY_CHECK,
+	WIRED_VALIDATE_LOCALITY,
+	WIRED_GET_SESSION_KEY,
+	WIRED_ENABLE_AUTH,
+	WIRED_VERIFY_REPEATER,
+	WIRED_REPEATER_AUTH_STREAM_REQ,
+	WIRED_CLOSE_SESSION,
+
+	_WIRED_COMMANDS_COUNT,
+};
+
+union encrypted_buff {
+	u8		e_kpub_km[HDCP_2_2_E_KPUB_KM_LEN];
+	u8		e_kh_km_m[HDCP_2_2_E_KH_KM_M_LEN];
+	struct {
+		u8	e_kh_km[HDCP_KH_LEN];
+		u8	m[HDCP_M_LEN];
+	} __packed;
+};
+
+/* HDCP HECI message header. All header values are little endian. */
+struct hdcp_cmd_header {
+	u32			api_version;
+	u32			command_id;
+	enum me_hdcp_status	status;
+	/* Length of the HECI message (excluding the header) */
+	u32			buffer_len;
+} __packed;
+
+/* Empty command request or response. No data follows the header. */
+struct hdcp_cmd_no_data {
+	struct hdcp_cmd_header header;
+} __packed;
+
+/* Uniquely identifies the hdcp port being addressed for a given command. */
+struct hdcp_port_id {
+	u8	integrated_port_type;
+	u8	physical_port;
+	u16	reserved;
+} __packed;
+
+/*
+ * Data structures for integrated wired HDCP2 Tx in
+ * support of the AKE protocol
+ */
+/* HECI struct for integrated wired HDCP Tx session initiation. */
+struct wired_cmd_initiate_hdcp2_session_in {
+	struct hdcp_cmd_header	header;
+	struct hdcp_port_id	port;
+	u8			protocol; /* for HDMI vs DP */
+} __packed;
+
+struct wired_cmd_initiate_hdcp2_session_out {
+	struct hdcp_cmd_header	header;
+	struct hdcp_port_id	port;
+	u8			r_tx[HDCP_2_2_RTX_LEN];
+	struct hdcp2_tx_caps	tx_caps;
+} __packed;
+
+/* HECI struct for ending an integrated wired HDCP Tx session. */
+struct wired_cmd_close_session_in {
+	struct hdcp_cmd_header	header;
+	struct hdcp_port_id	port;
+} __packed;
+
+struct wired_cmd_close_session_out {
+	struct hdcp_cmd_header	header;
+	struct hdcp_port_id	port;
+} __packed;
+
+/* HECI struct for integrated wired HDCP Tx Rx Cert verification. */
+struct wired_cmd_verify_receiver_cert_in {
+	struct hdcp_cmd_header	header;
+	struct hdcp_port_id	port;
+	struct hdcp2_cert_rx	cert_rx;
+	u8			r_rx[HDCP_2_2_RRX_LEN];
+	u8			rx_caps[HDCP_2_2_RXCAPS_LEN];
+} __packed;
+
+struct wired_cmd_verify_receiver_cert_out {
+	struct hdcp_cmd_header	header;
+	struct hdcp_port_id	port;
+	u8			km_stored;
+	u8			reserved[3];
+	union encrypted_buff	ekm_buff;
+} __packed;
+
+/* HECI struct for verification of Rx's Hprime in a HDCP Tx session */
+struct wired_cmd_ake_send_hprime_in {
+	struct hdcp_cmd_header	header;
+	struct hdcp_port_id	port;
+	u8			h_prime[HDCP_2_2_H_PRIME_LEN];
+} __packed;
+
+struct wired_cmd_ake_send_hprime_out {
+	struct hdcp_cmd_header	header;
+	struct hdcp_port_id	port;
+} __packed;
+
+/*
+ * HECI struct for sending in AKE pairing data generated by the Rx in an
+ * integrated wired HDCP Tx session.
+ */
+struct wired_cmd_ake_send_pairing_info_in {
+	struct hdcp_cmd_header	header;
+	struct hdcp_port_id	port;
+	u8			e_kh_km[HDCP_2_2_E_KH_KM_LEN];
+} __packed;
+
+struct wired_cmd_ake_send_pairing_info_out {
+	struct hdcp_cmd_header	header;
+	struct hdcp_port_id	port;
+} __packed;
+
+/* Data structures for integrated wired HDCP2 Tx in support of the LC protocol*/
+/*
+ * HECI struct for initiating locality check with an
+ * integrated wired HDCP Tx session.
+ */
+struct wired_cmd_init_locality_check_in {
+	struct hdcp_cmd_header	header;
+	struct hdcp_port_id	port;
+} __packed;
+
+struct wired_cmd_init_locality_check_out {
+	struct hdcp_cmd_header	header;
+	struct hdcp_port_id	port;
+	u8			r_n[HDCP_2_2_RN_LEN];
+} __packed;
+
+/*
+ * HECI struct for validating an Rx's LPrime value in an
+ * integrated wired HDCP Tx session.
+ */
+struct wired_cmd_validate_locality_in {
+	struct hdcp_cmd_header	header;
+	struct hdcp_port_id	port;
+	u8			l_prime[HDCP_2_2_L_PRIME_LEN];
+} __packed;
+
+struct wired_cmd_validate_locality_out {
+	struct hdcp_cmd_header	header;
+	struct hdcp_port_id	port;
+} __packed;
+
+/*
+ * Data structures for integrated wired HDCP2 Tx in support of the
+ * SKE protocol
+ */
+/* HECI struct for creating session key */
+struct wired_cmd_get_session_key_in {
+	struct hdcp_cmd_header	header;
+	struct hdcp_port_id	port;
+} __packed;
+
+struct wired_cmd_get_session_key_out {
+	struct hdcp_cmd_header	header;
+	struct hdcp_port_id	port;
+	u8			e_dkey_ks[HDCP_2_2_E_DKEY_KS_LEN];
+	u8			r_iv[HDCP_2_2_RIV_LEN];
+} __packed;
+
+/* HECI struct for the Tx enable authentication command */
+struct wired_cmd_enable_auth_in {
+	struct hdcp_cmd_header	header;
+	struct hdcp_port_id	port;
+	u8			stream_type;
+} __packed;
+
+struct wired_cmd_enable_auth_out {
+	struct hdcp_cmd_header	header;
+	struct hdcp_port_id	port;
+} __packed;
+
+/*
+ * Data structures for integrated wired HDCP2 Tx in support of
+ * the repeater protocols
+ */
+/*
+ * HECI struct for verifying the downstream repeater's HDCP topology in an
+ * integrated wired HDCP Tx session.
+ */
+struct wired_cmd_verify_repeater_in {
+	struct hdcp_cmd_header	header;
+	struct hdcp_port_id	port;
+	u8			rx_info[HDCP_2_2_RXINFO_LEN];
+	u8			seq_num_v[HDCP_2_2_SEQ_NUM_LEN];
+	u8			v_prime[HDCP_2_2_V_PRIME_HALF_LEN];
+	u8			receiver_ids[HDCP_2_2_RECEIVER_IDS_MAX_LEN];
+} __packed;
+
+struct wired_cmd_verify_repeater_out {
+	struct hdcp_cmd_header	header;
+	struct hdcp_port_id	port;
+	u8			content_type_supported;
+	u8			v[HDCP_2_2_V_PRIME_HALF_LEN];
+} __packed;
+
+/*
+ * HECI struct in support of stream management in an
+ * integrated wired HDCP Tx session.
+ */
+struct wired_cmd_repeater_auth_stream_req_in {
+	struct hdcp_cmd_header		header;
+	struct hdcp_port_id		port;
+	u8				seq_num_m[HDCP_2_2_SEQ_NUM_LEN];
+	u8				m_prime[HDCP_2_2_MPRIME_LEN];
+	u16				k;
+	struct hdcp2_streamid_type	streams[1];
+} __packed;
+
+struct wired_cmd_repeater_auth_stream_req_out {
+	struct hdcp_cmd_header	header;
+	struct hdcp_port_id	port;
+} __packed;
+
+#endif /* __MEI_HDCP_H__ */
-- 
2.7.4

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply related	[flat|nested] 103+ messages in thread

* [PATCH v9 24/39] misc/mei/hdcp: Initiate Wired HDCP2.2 Tx Session
  2018-12-13  4:01 [PATCH v9 00/39] drm/i915: Implement HDCP2.2 Ramalingam C
                   ` (22 preceding siblings ...)
  2018-12-13  4:01 ` [PATCH v9 23/39] misc/mei/hdcp: Define ME FW interface for HDCP2.2 Ramalingam C
@ 2018-12-13  4:01 ` Ramalingam C
  2018-12-13  4:01 ` [PATCH v9 25/39] misc/mei/hdcp: Verify Receiver Cert and prepare km Ramalingam C
                   ` (18 subsequent siblings)
  42 siblings, 0 replies; 103+ messages in thread
From: Ramalingam C @ 2018-12-13  4:01 UTC (permalink / raw)
  To: intel-gfx, dri-devel, seanpaul, daniel.vetter, tomas.winkler,
	uma.shankar

Request ME FW to start the HDCP2.2 session for an intel port.
Prepares payloads for command WIRED_INITIATE_HDCP2_SESSION and sends
to ME FW.

On Success, ME FW will start a HDCP2.2 session for the port and
provides the content for HDCP2.2 AKE_Init message.

v2: Rebased.
v3:
  cldev is add as a separate parameter [Tomas]
  Redundant comment and typecast are removed [Tomas]
v4:
  %zd is used for size [Alexander]
  %s/return -1/return -EIO [Alexander]
  Spellings in commit msg is fixed [Uma]
v5: Rebased.
v6:
  Collected the rb-ed by.
  Realigning the patches in the series.
v7:
  Adjust to the new mei interface.
  Fix for kdoc.
v8:
  K-Doc Addition.
  memcpy for const length.

Signed-off-by: Ramalingam C <ramalingam.c@intel.com>
Reviewed-by: Uma Shankar <uma.shankar@intel.com>
---
 drivers/misc/mei/hdcp/mei_hdcp.c | 81 ++++++++++++++++++++++++++++++++++++++++
 drivers/misc/mei/hdcp/mei_hdcp.h | 28 ++++++++++++++
 2 files changed, 109 insertions(+)

diff --git a/drivers/misc/mei/hdcp/mei_hdcp.c b/drivers/misc/mei/hdcp/mei_hdcp.c
index 6e7101512842..124f02e2b7c4 100644
--- a/drivers/misc/mei/hdcp/mei_hdcp.c
+++ b/drivers/misc/mei/hdcp/mei_hdcp.c
@@ -23,6 +23,87 @@
 #include <linux/slab.h>
 #include <linux/uuid.h>
 #include <linux/mei_cl_bus.h>
+#include <drm/drm_connector.h>
+#include <drm/i915_component.h>
+
+#include "mei_hdcp.h"
+
+/**
+ * mei_initiate_hdcp2_session() - Initiate a Wired HDCP2.2 Tx Session in ME FW
+ * @dev: device corresponding to the mei_cl_device
+ * @hdcp_data: Intel HW specific hdcp data
+ * @ake_data: AKE_Init msg output.
+ *
+ * Return:  0 on Success, <0 on Failure.
+ */
+static int
+mei_initiate_hdcp2_session(struct device *dev, struct hdcp_port_data *data,
+			   struct hdcp2_ake_init *ake_data)
+{
+	struct wired_cmd_initiate_hdcp2_session_in session_init_in = { { 0 } };
+	struct wired_cmd_initiate_hdcp2_session_out
+						session_init_out = { { 0 } };
+	struct mei_cl_device *cldev;
+	ssize_t byte;
+
+	if (!dev || !data || !ake_data)
+		return -EINVAL;
+
+	cldev = to_mei_cl_device(dev);
+
+	session_init_in.header.api_version = HDCP_API_VERSION;
+	session_init_in.header.command_id = WIRED_INITIATE_HDCP2_SESSION;
+	session_init_in.header.status = ME_HDCP_STATUS_SUCCESS;
+	session_init_in.header.buffer_len =
+				WIRED_CMD_BUF_LEN_INITIATE_HDCP2_SESSION_IN;
+
+	session_init_in.port.integrated_port_type = data->port_type;
+	session_init_in.port.physical_port = (u8)GET_MEI_DDI_INDEX(data->port);
+	session_init_in.protocol = data->protocol;
+
+	byte = mei_cldev_send(cldev, (u8 *)&session_init_in,
+			      sizeof(session_init_in));
+	if (byte < 0) {
+		dev_dbg(dev, "mei_cldev_send failed. %zd\n", byte);
+		return byte;
+	}
+
+	byte = mei_cldev_recv(cldev, (u8 *)&session_init_out,
+			      sizeof(session_init_out));
+	if (byte < 0) {
+		dev_dbg(dev, "mei_cldev_recv failed. %zd\n", byte);
+		return byte;
+	}
+
+	if (session_init_out.header.status != ME_HDCP_STATUS_SUCCESS) {
+		dev_dbg(dev, "ME cmd 0x%08X Failed. Status: 0x%X\n",
+			WIRED_INITIATE_HDCP2_SESSION,
+			session_init_out.header.status);
+		return -EIO;
+	}
+
+	ake_data->msg_id = HDCP_2_2_AKE_INIT;
+	ake_data->tx_caps = session_init_out.tx_caps;
+	memcpy(ake_data->r_tx, session_init_out.r_tx, HDCP_2_2_RTX_LEN);
+
+	return 0;
+}
+
+static __attribute__((unused))
+struct i915_hdcp_component_ops mei_hdcp_ops = {
+	.owner = THIS_MODULE,
+	.initiate_hdcp2_session = mei_initiate_hdcp2_session,
+	.verify_receiver_cert_prepare_km = NULL,
+	.verify_hprime = NULL,
+	.store_pairing_info = NULL,
+	.initiate_locality_check = NULL,
+	.verify_lprime = NULL,
+	.get_session_key = NULL,
+	.repeater_check_flow_prepare_ack = NULL,
+	.verify_mprime = NULL,
+	.enable_hdcp_authentication = NULL,
+	.close_hdcp_session = NULL,
+};
 
 static int mei_hdcp_probe(struct mei_cl_device *cldev,
 			  const struct mei_cl_device_id *id)
diff --git a/drivers/misc/mei/hdcp/mei_hdcp.h b/drivers/misc/mei/hdcp/mei_hdcp.h
index d1456e3dbf22..cac1a525476d 100644
--- a/drivers/misc/mei/hdcp/mei_hdcp.h
+++ b/drivers/misc/mei/hdcp/mei_hdcp.h
@@ -363,4 +363,32 @@ struct wired_cmd_repeater_auth_stream_req_out {
 	struct hdcp_port_id	port;
 } __packed;
 
+enum mei_hdcp_ddi {
+	MEI_DDI_INVALID_PORT = 0x0,
+
+	MEI_DDI_B = 1,
+	MEI_DDI_C,
+	MEI_DDI_D,
+	MEI_DDI_E,
+	MEI_DDI_F,
+	MEI_DDI_A = 7,
+	MEI_DDI_RANGE_END = MEI_DDI_A,
+};
+
+enum i915_port {
+	PORT_NONE = -1,
+
+	PORT_A = 0,
+	PORT_B,
+	PORT_C,
+	PORT_D,
+	PORT_E,
+	PORT_F,
+	I915_MAX_PORTS,
+};
+
+#define GET_MEI_DDI_INDEX(p) ({						\
+	enum i915_port __p = (enum i915_port)(p);			\
+	__p == PORT_A ? MEI_DDI_A : (enum mei_hdcp_ddi)__p;		\
+})
 #endif /* __MEI_HDCP_H__ */
-- 
2.7.4

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply related	[flat|nested] 103+ messages in thread

* [PATCH v9 25/39] misc/mei/hdcp: Verify Receiver Cert and prepare km
  2018-12-13  4:01 [PATCH v9 00/39] drm/i915: Implement HDCP2.2 Ramalingam C
                   ` (23 preceding siblings ...)
  2018-12-13  4:01 ` [PATCH v9 24/39] misc/mei/hdcp: Initiate Wired HDCP2.2 Tx Session Ramalingam C
@ 2018-12-13  4:01 ` Ramalingam C
  2018-12-13  4:01 ` [PATCH v9 26/39] misc/mei/hdcp: Verify H_prime Ramalingam C
                   ` (17 subsequent siblings)
  42 siblings, 0 replies; 103+ messages in thread
From: Ramalingam C @ 2018-12-13  4:01 UTC (permalink / raw)
  To: intel-gfx, dri-devel, seanpaul, daniel.vetter, tomas.winkler,
	uma.shankar

Requests for verification for receiver certification and also the
preparation for next AKE auth message with km.

On Success ME FW validate the HDCP2.2 receivers certificate and do the
revocation check on the receiver ID. AKE_Stored_Km will be prepared if
the receiver is already paired, else AKE_No_Stored_Km will be prepared.

Here AKE_Stored_Km and AKE_No_Stored_Km are HDCP2.2 protocol msgs.

v2: Rebased.
v3:
  cldev is passed as first parameter [Tomas]
  Redundant comments and cast are removed [Tomas]
v4:
  %zd is used for ssize_t [Alexander]
  %s/return -1/return -EIO [Alexander]
v5: Rebased.
v6:
  Collected the Rb-ed by.
  Rebasing.
v7:
  Adjust to the new mei interface.
  Fix for Kdoc.
v8:
  K-Doc Addition. [Tomas]
  memcpy for const length.

Signed-off-by: Ramalingam C <ramalingam.c@intel.com>
Reviewed-by: Uma Shankar <uma.shankar@intel.com>
---
 drivers/misc/mei/hdcp/mei_hdcp.c | 81 +++++++++++++++++++++++++++++++++++++++-
 1 file changed, 80 insertions(+), 1 deletion(-)

diff --git a/drivers/misc/mei/hdcp/mei_hdcp.c b/drivers/misc/mei/hdcp/mei_hdcp.c
index 124f02e2b7c4..270baf24f21b 100644
--- a/drivers/misc/mei/hdcp/mei_hdcp.c
+++ b/drivers/misc/mei/hdcp/mei_hdcp.c
@@ -89,11 +89,90 @@ mei_initiate_hdcp2_session(struct device *dev, struct hdcp_port_data *data,
 	return 0;
 }
 
+/**
+ * mei_verify_receiver_cert_prepare_km() - Verify the Receiver Certificate
+ * AKE_Send_Cert and prepare AKE_Stored_Km/AKE_No_Stored_Km
+ * @dev: device corresponding to the mei_cl_device
+ * @hdcp_data: Intel HW specific hdcp data
+ * @rx_cert: AKE_Send_Cert for verification
+ * @km_stored: Pairing status flag output
+ * @ek_pub_km: AKE_Stored_Km/AKE_No_Stored_Km output msg
+ * @msg_sz : size of AKE_XXXXX_Km output msg
+ *
+ * Return: 0 on Success, <0 on Failure
+ */
+static int
+mei_verify_receiver_cert_prepare_km(struct device *dev,
+				    struct hdcp_port_data *data,
+				    struct hdcp2_ake_send_cert *rx_cert,
+				    bool *km_stored,
+				    struct hdcp2_ake_no_stored_km *ek_pub_km,
+				    size_t *msg_sz)
+{
+	struct wired_cmd_verify_receiver_cert_in verify_rxcert_in = { { 0 } };
+	struct wired_cmd_verify_receiver_cert_out verify_rxcert_out = { { 0 } };
+	struct mei_cl_device *cldev;
+	ssize_t byte;
+
+	if (!dev || !data || !rx_cert || !km_stored || !ek_pub_km || !msg_sz)
+		return -EINVAL;
+
+	cldev = to_mei_cl_device(dev);
+
+	verify_rxcert_in.header.api_version = HDCP_API_VERSION;
+	verify_rxcert_in.header.command_id = WIRED_VERIFY_RECEIVER_CERT;
+	verify_rxcert_in.header.status = ME_HDCP_STATUS_SUCCESS;
+	verify_rxcert_in.header.buffer_len =
+				WIRED_CMD_BUF_LEN_VERIFY_RECEIVER_CERT_IN;
+
+	verify_rxcert_in.port.integrated_port_type = data->port_type;
+	verify_rxcert_in.port.physical_port = (u8)GET_MEI_DDI_INDEX(data->port);
+
+	verify_rxcert_in.cert_rx = rx_cert->cert_rx;
+	memcpy(verify_rxcert_in.r_rx, &rx_cert->r_rx, HDCP_2_2_RRX_LEN);
+	memcpy(verify_rxcert_in.rx_caps, rx_cert->rx_caps, HDCP_2_2_RXCAPS_LEN);
+
+	byte = mei_cldev_send(cldev, (u8 *)&verify_rxcert_in,
+			      sizeof(verify_rxcert_in));
+	if (byte < 0) {
+		dev_dbg(dev, "mei_cldev_send failed: %zd\n", byte);
+		return byte;
+	}
+
+	byte = mei_cldev_recv(cldev, (u8 *)&verify_rxcert_out,
+			      sizeof(verify_rxcert_out));
+	if (byte < 0) {
+		dev_dbg(dev, "mei_cldev_recv failed: %zd\n", byte);
+		return byte;
+	}
+
+	if (verify_rxcert_out.header.status != ME_HDCP_STATUS_SUCCESS) {
+		dev_dbg(dev, "ME cmd 0x%08X Failed. Status: 0x%X\n",
+			WIRED_VERIFY_RECEIVER_CERT,
+			verify_rxcert_out.header.status);
+		return -EIO;
+	}
+
+	*km_stored = verify_rxcert_out.km_stored;
+	if (verify_rxcert_out.km_stored) {
+		ek_pub_km->msg_id = HDCP_2_2_AKE_STORED_KM;
+		*msg_sz = sizeof(struct hdcp2_ake_stored_km);
+	} else {
+		ek_pub_km->msg_id = HDCP_2_2_AKE_NO_STORED_KM;
+		*msg_sz = sizeof(struct hdcp2_ake_no_stored_km);
+	}
+
+	memcpy(ek_pub_km->e_kpub_km, &verify_rxcert_out.ekm_buff,
+	       sizeof(verify_rxcert_out.ekm_buff));
+
+	return 0;
+}
+
 static __attribute__((unused))
 struct i915_hdcp_component_ops mei_hdcp_ops = {
 	.owner = THIS_MODULE,
 	.initiate_hdcp2_session = mei_initiate_hdcp2_session,
-	.verify_receiver_cert_prepare_km = NULL,
+	.verify_receiver_cert_prepare_km = mei_verify_receiver_cert_prepare_km,
 	.verify_hprime = NULL,
 	.store_pairing_info = NULL,
 	.initiate_locality_check = NULL,
-- 
2.7.4

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply related	[flat|nested] 103+ messages in thread

* [PATCH v9 26/39] misc/mei/hdcp: Verify H_prime
  2018-12-13  4:01 [PATCH v9 00/39] drm/i915: Implement HDCP2.2 Ramalingam C
                   ` (24 preceding siblings ...)
  2018-12-13  4:01 ` [PATCH v9 25/39] misc/mei/hdcp: Verify Receiver Cert and prepare km Ramalingam C
@ 2018-12-13  4:01 ` Ramalingam C
  2018-12-13  4:01 ` [PATCH v9 27/39] misc/mei/hdcp: Store the HDCP Pairing info Ramalingam C
                   ` (16 subsequent siblings)
  42 siblings, 0 replies; 103+ messages in thread
From: Ramalingam C @ 2018-12-13  4:01 UTC (permalink / raw)
  To: intel-gfx, dri-devel, seanpaul, daniel.vetter, tomas.winkler,
	uma.shankar

Requests for the verification of AKE_Send_H_prime.

ME will calculate the H and comparing it with received H_Prime.
The result will be returned as status.

Here AKE_Send_H_prime is a HDCP2.2 Authentication msg.

v2: Rebased.
v3:
  cldev is passed as first parameter [Tomas]
  Redundant comments and cast are removed [Tomas]
v4:
  %zd for ssize_t [Alexander]
  %s/return -1/return -EIO [Alexander]
  Styles and typos fixed [Uma]
v5: Rebased.
v6:
  Collected the Rb-ed by.
  Rebasing.
v7:
  Adjust to the new mei interface.
  Fix for Kdoc.
v8:
  K-Doc Addition [Tomas]
  memcpy for const length.

Signed-off-by: Ramalingam C <ramalingam.c@intel.com>
Reviewed-by: Uma Shankar <uma.shankar@intel.com>
---
 drivers/misc/mei/hdcp/mei_hdcp.c | 57 +++++++++++++++++++++++++++++++++++++++-
 1 file changed, 56 insertions(+), 1 deletion(-)

diff --git a/drivers/misc/mei/hdcp/mei_hdcp.c b/drivers/misc/mei/hdcp/mei_hdcp.c
index 270baf24f21b..3e4f91e8b8f4 100644
--- a/drivers/misc/mei/hdcp/mei_hdcp.c
+++ b/drivers/misc/mei/hdcp/mei_hdcp.c
@@ -168,12 +168,67 @@ mei_verify_receiver_cert_prepare_km(struct device *dev,
 	return 0;
 }
 
+/**
+ * mei_verify_hprime() - Verify AKE_Send_H_prime at ME FW.
+ * @dev: device corresponding to the mei_cl_device
+ * @hdcp_data: Intel HW specific hdcp data
+ * @rx_hprime: AKE_Send_H_prime msg for ME FW verification
+ *
+ * Return: 0 on Success, <0 on Failure
+ */
+static int mei_verify_hprime(struct device *dev, struct hdcp_port_data *data,
+			     struct hdcp2_ake_send_hprime *rx_hprime)
+{
+	struct wired_cmd_ake_send_hprime_in send_hprime_in = { { 0 } };
+	struct wired_cmd_ake_send_hprime_out send_hprime_out = { { 0 } };
+	struct mei_cl_device *cldev;
+	ssize_t byte;
+
+	if (!dev || !data || !rx_hprime)
+		return -EINVAL;
+
+	cldev = to_mei_cl_device(dev);
+
+	send_hprime_in.header.api_version = HDCP_API_VERSION;
+	send_hprime_in.header.command_id = WIRED_AKE_SEND_HPRIME;
+	send_hprime_in.header.status = ME_HDCP_STATUS_SUCCESS;
+	send_hprime_in.header.buffer_len = WIRED_CMD_BUF_LEN_AKE_SEND_HPRIME_IN;
+
+	send_hprime_in.port.integrated_port_type = data->port_type;
+	send_hprime_in.port.physical_port = (u8)GET_MEI_DDI_INDEX(data->port);
+
+	memcpy(send_hprime_in.h_prime, rx_hprime->h_prime,
+	       HDCP_2_2_H_PRIME_LEN);
+
+	byte = mei_cldev_send(cldev, (u8 *)&send_hprime_in,
+			      sizeof(send_hprime_in));
+	if (byte < 0) {
+		dev_dbg(dev, "mei_cldev_send failed. %zd\n", byte);
+		return byte;
+	}
+
+	byte = mei_cldev_recv(cldev, (u8 *)&send_hprime_out,
+			      sizeof(send_hprime_out));
+	if (byte < 0) {
+		dev_dbg(dev, "mei_cldev_recv failed. %zd\n", byte);
+		return byte;
+	}
+
+	if (send_hprime_out.header.status != ME_HDCP_STATUS_SUCCESS) {
+		dev_dbg(dev, "ME cmd 0x%08X Failed. Status: 0x%X\n",
+			WIRED_AKE_SEND_HPRIME, send_hprime_out.header.status);
+		return -EIO;
+	}
+
+	return 0;
+}
+
 static __attribute__((unused))
 struct i915_hdcp_component_ops mei_hdcp_ops = {
 	.owner = THIS_MODULE,
 	.initiate_hdcp2_session = mei_initiate_hdcp2_session,
 	.verify_receiver_cert_prepare_km = mei_verify_receiver_cert_prepare_km,
-	.verify_hprime = NULL,
+	.verify_hprime = mei_verify_hprime,
 	.store_pairing_info = NULL,
 	.initiate_locality_check = NULL,
 	.verify_lprime = NULL,
-- 
2.7.4

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply related	[flat|nested] 103+ messages in thread

* [PATCH v9 27/39] misc/mei/hdcp: Store the HDCP Pairing info
  2018-12-13  4:01 [PATCH v9 00/39] drm/i915: Implement HDCP2.2 Ramalingam C
                   ` (25 preceding siblings ...)
  2018-12-13  4:01 ` [PATCH v9 26/39] misc/mei/hdcp: Verify H_prime Ramalingam C
@ 2018-12-13  4:01 ` Ramalingam C
  2018-12-13  4:01 ` [PATCH v9 28/39] misc/mei/hdcp: Initiate Locality check Ramalingam C
                   ` (15 subsequent siblings)
  42 siblings, 0 replies; 103+ messages in thread
From: Ramalingam C @ 2018-12-13  4:01 UTC (permalink / raw)
  To: intel-gfx, dri-devel, seanpaul, daniel.vetter, tomas.winkler,
	uma.shankar

Provides Pairing info to ME to store.

Pairing is a process to fast track the subsequent authentication
with the same HDCP sink.

On Success, received HDCP pairing info is stored in non-volatile
memory of ME.

v2: Rebased.
v3:
  cldev is passed as first parameter [Tomas]
  Redundant comments and cast are removed [Tomas]
v4:
  %zd for ssize_t [Alexander]
  %s/return -1/return -EIO [Alexander]
  Style fixed [Uma]
v5: Rebased.
v6:
  Collected the Rb-ed by.
  Rebasing.
v7:
  Adjust to the new mei interface.
  Fix for Kdoc.
v8:
  K-Doc addition. [Tomas]
  memcpy for const length.

Signed-off-by: Ramalingam C <ramalingam.c@intel.com>
Reviewed-by: Uma Shankar <uma.shankar@intel.com>
---
 drivers/misc/mei/hdcp/mei_hdcp.c | 60 +++++++++++++++++++++++++++++++++++++++-
 1 file changed, 59 insertions(+), 1 deletion(-)

diff --git a/drivers/misc/mei/hdcp/mei_hdcp.c b/drivers/misc/mei/hdcp/mei_hdcp.c
index 3e4f91e8b8f4..809d6270b6c1 100644
--- a/drivers/misc/mei/hdcp/mei_hdcp.c
+++ b/drivers/misc/mei/hdcp/mei_hdcp.c
@@ -223,13 +223,71 @@ static int mei_verify_hprime(struct device *dev, struct hdcp_port_data *data,
 	return 0;
 }
 
+/**
+ * mei_store_pairing_info() - Store pairing info received at ME FW
+ * @dev: device corresponding to the mei_cl_device
+ * @hdcp_data: Intel HW specific hdcp data
+ * @pairing_info: AKE_Send_Pairing_Info msg input to ME FW
+ *
+ * Return: 0 on Success, <0 on Failure
+ */
+static int
+mei_store_pairing_info(struct device *dev, struct hdcp_port_data *data,
+		       struct hdcp2_ake_send_pairing_info *pairing_info)
+{
+	struct wired_cmd_ake_send_pairing_info_in pairing_info_in = { { 0 } };
+	struct wired_cmd_ake_send_pairing_info_out pairing_info_out = { { 0 } };
+	struct mei_cl_device *cldev;
+	ssize_t byte;
+
+	if (!dev || !data || !pairing_info)
+		return -EINVAL;
+
+	cldev = to_mei_cl_device(dev);
+
+	pairing_info_in.header.api_version = HDCP_API_VERSION;
+	pairing_info_in.header.command_id = WIRED_AKE_SEND_PAIRING_INFO;
+	pairing_info_in.header.status = ME_HDCP_STATUS_SUCCESS;
+	pairing_info_in.header.buffer_len =
+					WIRED_CMD_BUF_LEN_SEND_PAIRING_INFO_IN;
+
+	pairing_info_in.port.integrated_port_type = data->port_type;
+	pairing_info_in.port.physical_port = (u8)GET_MEI_DDI_INDEX(data->port);
+
+	memcpy(pairing_info_in.e_kh_km, pairing_info->e_kh_km,
+	       HDCP_2_2_E_KH_KM_LEN);
+
+	byte = mei_cldev_send(cldev, (u8 *)&pairing_info_in,
+			      sizeof(pairing_info_in));
+	if (byte < 0) {
+		dev_dbg(dev, "mei_cldev_send failed. %zd\n", byte);
+		return byte;
+	}
+
+	byte = mei_cldev_recv(cldev, (u8 *)&pairing_info_out,
+			      sizeof(pairing_info_out));
+	if (byte < 0) {
+		dev_dbg(dev, "mei_cldev_recv failed. %zd\n", byte);
+		return byte;
+	}
+
+	if (pairing_info_out.header.status != ME_HDCP_STATUS_SUCCESS) {
+		dev_dbg(dev, "ME cmd 0x%08X failed. Status: 0x%X\n",
+			WIRED_AKE_SEND_PAIRING_INFO,
+			pairing_info_out.header.status);
+		return -EIO;
+	}
+
+	return 0;
+}
+
 static __attribute__((unused))
 struct i915_hdcp_component_ops mei_hdcp_ops = {
 	.owner = THIS_MODULE,
 	.initiate_hdcp2_session = mei_initiate_hdcp2_session,
 	.verify_receiver_cert_prepare_km = mei_verify_receiver_cert_prepare_km,
 	.verify_hprime = mei_verify_hprime,
-	.store_pairing_info = NULL,
+	.store_pairing_info = mei_store_pairing_info,
 	.initiate_locality_check = NULL,
 	.verify_lprime = NULL,
 	.get_session_key = NULL,
-- 
2.7.4

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply related	[flat|nested] 103+ messages in thread

* [PATCH v9 28/39] misc/mei/hdcp: Initiate Locality check
  2018-12-13  4:01 [PATCH v9 00/39] drm/i915: Implement HDCP2.2 Ramalingam C
                   ` (26 preceding siblings ...)
  2018-12-13  4:01 ` [PATCH v9 27/39] misc/mei/hdcp: Store the HDCP Pairing info Ramalingam C
@ 2018-12-13  4:01 ` Ramalingam C
  2018-12-13  4:01 ` [PATCH v9 29/39] misc/mei/hdcp: Verify L_prime Ramalingam C
                   ` (14 subsequent siblings)
  42 siblings, 0 replies; 103+ messages in thread
From: Ramalingam C @ 2018-12-13  4:01 UTC (permalink / raw)
  To: intel-gfx, dri-devel, seanpaul, daniel.vetter, tomas.winkler,
	uma.shankar

Requests ME to start the second stage of HDCP2.2 authentication,
called Locality Check.

On Success, ME FW will provide LC_Init message to send to hdcp sink.

v2: Rebased.
v3:
  cldev is passed as first parameter [Tomas]
  Redundant comments and cast are removed [Tomas]
v4:
  %zd used for ssize_t [Alexander]
  %s/return -1/return -EIO [Alexander]
  Style fixed [Uma]
v5: Rebased.
v6:
  Collected the Rb-ed by.
  Rebasing.
v7:
  Adjust to the new mei interface.
  Fix for Kdoc.
v8:
  K-Doc addition. [Tomas]

Signed-off-by: Ramalingam C <ramalingam.c@intel.com>
Reviewed-by: Uma Shankar <uma.shankar@intel.com>
---
 drivers/misc/mei/hdcp/mei_hdcp.c | 56 +++++++++++++++++++++++++++++++++++++++-
 1 file changed, 55 insertions(+), 1 deletion(-)

diff --git a/drivers/misc/mei/hdcp/mei_hdcp.c b/drivers/misc/mei/hdcp/mei_hdcp.c
index 809d6270b6c1..db1492f64d6b 100644
--- a/drivers/misc/mei/hdcp/mei_hdcp.c
+++ b/drivers/misc/mei/hdcp/mei_hdcp.c
@@ -281,6 +281,60 @@ mei_store_pairing_info(struct device *dev, struct hdcp_port_data *data,
 	return 0;
 }
 
+/**
+ * mei_initiate_locality_check() - Prepare LC_Init
+ * @dev: device corresponding to the mei_cl_device
+ * @hdcp_data: Intel HW specific hdcp data
+ * @lc_init_data: LC_Init msg output
+ *
+ * Return: 0 on Success, <0 on Failure
+ */
+static int
+mei_initiate_locality_check(struct device *dev, struct hdcp_port_data *data,
+			    struct hdcp2_lc_init *lc_init_data)
+{
+	struct wired_cmd_init_locality_check_in lc_init_in = { { 0 } };
+	struct wired_cmd_init_locality_check_out lc_init_out = { { 0 } };
+	struct mei_cl_device *cldev;
+	ssize_t byte;
+
+	if (!dev || !data || !lc_init_data)
+		return -EINVAL;
+
+	cldev = to_mei_cl_device(dev);
+
+	lc_init_in.header.api_version = HDCP_API_VERSION;
+	lc_init_in.header.command_id = WIRED_INIT_LOCALITY_CHECK;
+	lc_init_in.header.status = ME_HDCP_STATUS_SUCCESS;
+	lc_init_in.header.buffer_len = WIRED_CMD_BUF_LEN_INIT_LOCALITY_CHECK_IN;
+
+	lc_init_in.port.integrated_port_type = data->port_type;
+	lc_init_in.port.physical_port = (u8)GET_MEI_DDI_INDEX(data->port);
+
+	byte = mei_cldev_send(cldev, (u8 *)&lc_init_in, sizeof(lc_init_in));
+	if (byte < 0) {
+		dev_dbg(dev, "mei_cldev_send failed. %zd\n", byte);
+		return byte;
+	}
+
+	byte = mei_cldev_recv(cldev, (u8 *)&lc_init_out, sizeof(lc_init_out));
+	if (byte < 0) {
+		dev_dbg(dev, "mei_cldev_recv failed. %zd\n", byte);
+		return byte;
+	}
+
+	if (lc_init_out.header.status != ME_HDCP_STATUS_SUCCESS) {
+		dev_dbg(dev, "ME cmd 0x%08X Failed. status: 0x%X\n",
+			WIRED_INIT_LOCALITY_CHECK, lc_init_out.header.status);
+		return -EIO;
+	}
+
+	lc_init_data->msg_id = HDCP_2_2_LC_INIT;
+	memcpy(lc_init_data->r_n, lc_init_out.r_n, HDCP_2_2_RN_LEN);
+
+	return 0;
+}
+
 static __attribute__((unused))
 struct i915_hdcp_component_ops mei_hdcp_ops = {
 	.owner = THIS_MODULE,
@@ -288,7 +342,7 @@ struct i915_hdcp_component_ops mei_hdcp_ops = {
 	.verify_receiver_cert_prepare_km = mei_verify_receiver_cert_prepare_km,
 	.verify_hprime = mei_verify_hprime,
 	.store_pairing_info = mei_store_pairing_info,
-	.initiate_locality_check = NULL,
+	.initiate_locality_check = mei_initiate_locality_check,
 	.verify_lprime = NULL,
 	.get_session_key = NULL,
 	.repeater_check_flow_prepare_ack = NULL,
-- 
2.7.4

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply related	[flat|nested] 103+ messages in thread

* [PATCH v9 29/39] misc/mei/hdcp: Verify L_prime
  2018-12-13  4:01 [PATCH v9 00/39] drm/i915: Implement HDCP2.2 Ramalingam C
                   ` (27 preceding siblings ...)
  2018-12-13  4:01 ` [PATCH v9 28/39] misc/mei/hdcp: Initiate Locality check Ramalingam C
@ 2018-12-13  4:01 ` Ramalingam C
  2018-12-13  4:01 ` [PATCH v9 30/39] misc/mei/hdcp: Prepare Session Key Ramalingam C
                   ` (13 subsequent siblings)
  42 siblings, 0 replies; 103+ messages in thread
From: Ramalingam C @ 2018-12-13  4:01 UTC (permalink / raw)
  To: intel-gfx, dri-devel, seanpaul, daniel.vetter, tomas.winkler,
	uma.shankar

Request to ME to verify the LPrime received from HDCP sink.

On Success, ME FW will verify the received Lprime by calculating and
comparing with L.

This represents the completion of Locality Check.

v2: Rebased.
v3:
  cldev is passed as first parameter [Tomas]
  Redundant comments and cast are removed [Tomas]
v4:
  %zd for ssize_t [Alexander]
  %s/return -1/return -EIO [Alexander]
  Style fixed [Uma]
v5: Rebased.
v6:
  Collected the Rb-ed by.
  Rebasing.
v7:
  Adjust to the new mei interface.
  Fix for Kdoc.
v8:
  K-Doc addition. [Tomas]
  memcpy for const length.

Signed-off-by: Ramalingam C <ramalingam.c@intel.com>
Reviewed-by: Uma Shankar <uma.shankar@intel.com>
---
 drivers/misc/mei/hdcp/mei_hdcp.c | 59 +++++++++++++++++++++++++++++++++++++++-
 1 file changed, 58 insertions(+), 1 deletion(-)

diff --git a/drivers/misc/mei/hdcp/mei_hdcp.c b/drivers/misc/mei/hdcp/mei_hdcp.c
index db1492f64d6b..b6cc55c13d4a 100644
--- a/drivers/misc/mei/hdcp/mei_hdcp.c
+++ b/drivers/misc/mei/hdcp/mei_hdcp.c
@@ -335,6 +335,63 @@ mei_initiate_locality_check(struct device *dev, struct hdcp_port_data *data,
 	return 0;
 }
 
+/**
+ * mei_verify_lprime() - Verify lprime.
+ * @dev: device corresponding to the mei_cl_device
+ * @hdcp_data: Intel HW specific hdcp data
+ * @rx_lprime: LC_Send_L_prime msg for ME FW verification
+ *
+ * Return: 0 on Success, <0 on Failure
+ */
+static int mei_verify_lprime(struct device *dev, struct hdcp_port_data *data,
+			     struct hdcp2_lc_send_lprime *rx_lprime)
+{
+	struct wired_cmd_validate_locality_in verify_lprime_in = { { 0 } };
+	struct wired_cmd_validate_locality_out verify_lprime_out = { { 0 } };
+	struct mei_cl_device *cldev;
+	ssize_t byte;
+
+	if (!dev || !data || !rx_lprime)
+		return -EINVAL;
+
+	cldev = to_mei_cl_device(dev);
+
+	verify_lprime_in.header.api_version = HDCP_API_VERSION;
+	verify_lprime_in.header.command_id = WIRED_VALIDATE_LOCALITY;
+	verify_lprime_in.header.status = ME_HDCP_STATUS_SUCCESS;
+	verify_lprime_in.header.buffer_len =
+					WIRED_CMD_BUF_LEN_VALIDATE_LOCALITY_IN;
+
+	verify_lprime_in.port.integrated_port_type = data->port_type;
+	verify_lprime_in.port.physical_port = (u8)GET_MEI_DDI_INDEX(data->port);
+
+	memcpy(verify_lprime_in.l_prime, rx_lprime->l_prime,
+	       HDCP_2_2_L_PRIME_LEN);
+
+	byte = mei_cldev_send(cldev, (u8 *)&verify_lprime_in,
+			      sizeof(verify_lprime_in));
+	if (byte < 0) {
+		dev_dbg(dev, "mei_cldev_send failed. %zd\n", byte);
+		return byte;
+	}
+
+	byte = mei_cldev_recv(cldev, (u8 *)&verify_lprime_out,
+			      sizeof(verify_lprime_out));
+	if (byte < 0) {
+		dev_dbg(dev, "mei_cldev_recv failed. %zd\n", byte);
+		return byte;
+	}
+
+	if (verify_lprime_out.header.status != ME_HDCP_STATUS_SUCCESS) {
+		dev_dbg(dev, "ME cmd 0x%08X failed. status: 0x%X\n",
+			WIRED_VALIDATE_LOCALITY,
+			verify_lprime_out.header.status);
+		return -EIO;
+	}
+
+	return 0;
+}
+
 static __attribute__((unused))
 struct i915_hdcp_component_ops mei_hdcp_ops = {
 	.owner = THIS_MODULE,
@@ -343,7 +400,7 @@ struct i915_hdcp_component_ops mei_hdcp_ops = {
 	.verify_hprime = mei_verify_hprime,
 	.store_pairing_info = mei_store_pairing_info,
 	.initiate_locality_check = mei_initiate_locality_check,
-	.verify_lprime = NULL,
+	.verify_lprime = mei_verify_lprime,
 	.get_session_key = NULL,
 	.repeater_check_flow_prepare_ack = NULL,
 	.verify_mprime = NULL,
-- 
2.7.4

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply related	[flat|nested] 103+ messages in thread

* [PATCH v9 30/39] misc/mei/hdcp: Prepare Session Key
  2018-12-13  4:01 [PATCH v9 00/39] drm/i915: Implement HDCP2.2 Ramalingam C
                   ` (28 preceding siblings ...)
  2018-12-13  4:01 ` [PATCH v9 29/39] misc/mei/hdcp: Verify L_prime Ramalingam C
@ 2018-12-13  4:01 ` Ramalingam C
  2018-12-13  4:01 ` [PATCH v9 31/39] misc/mei/hdcp: Repeater topology verification and ack Ramalingam C
                   ` (12 subsequent siblings)
  42 siblings, 0 replies; 103+ messages in thread
From: Ramalingam C @ 2018-12-13  4:01 UTC (permalink / raw)
  To: intel-gfx, dri-devel, seanpaul, daniel.vetter, tomas.winkler,
	uma.shankar

Request to ME to prepare the encrypted session key.

On Success, ME provides Encrypted session key. Function populates
the HDCP2.2 authentication msg SKE_Send_Eks.

v2: Rebased.
v3:
  cldev is passed as first parameter [Tomas]
  Redundant comments and cast are removed [Tomas]
v4:
  %zd for ssize_t [Alexander]
  %s/return -1/return -EIO [Alexander]
  Style fixed [Uma]
v5: Rebased.
v6:
  Collected the Rb-ed by.
  Rebasing.
v7:
  Adjust to the new mei interface.
  Fix for Kdoc.
v8:
  K-Doc addition. [Tomas]

Signed-off-by: Ramalingam C <ramalingam.c@intel.com>
Reviewed-by: Uma Shankar <uma.shankar@intel.com>
---
 drivers/misc/mei/hdcp/mei_hdcp.c | 58 +++++++++++++++++++++++++++++++++++++++-
 1 file changed, 57 insertions(+), 1 deletion(-)

diff --git a/drivers/misc/mei/hdcp/mei_hdcp.c b/drivers/misc/mei/hdcp/mei_hdcp.c
index b6cc55c13d4a..554e07ba69c3 100644
--- a/drivers/misc/mei/hdcp/mei_hdcp.c
+++ b/drivers/misc/mei/hdcp/mei_hdcp.c
@@ -392,6 +392,62 @@ static int mei_verify_lprime(struct device *dev, struct hdcp_port_data *data,
 	return 0;
 }
 
+/**
+ * mei_get_session_key() - Prepare SKE_Send_Eks.
+ * @dev: device corresponding to the mei_cl_device
+ * @hdcp_data: Intel HW specific hdcp data
+ * @ske_data: SKE_Send_Eks msg output from ME FW.
+ *
+ * Return: 0 on Success, <0 on Failure
+ */
+static int mei_get_session_key(struct device *dev, struct hdcp_port_data *data,
+			       struct hdcp2_ske_send_eks *ske_data)
+{
+	struct wired_cmd_get_session_key_in get_skey_in = { { 0 } };
+	struct wired_cmd_get_session_key_out get_skey_out = { { 0 } };
+	struct mei_cl_device *cldev;
+	ssize_t byte;
+
+	if (!dev || !data || !ske_data)
+		return -EINVAL;
+
+	cldev = to_mei_cl_device(dev);
+
+	get_skey_in.header.api_version = HDCP_API_VERSION;
+	get_skey_in.header.command_id = WIRED_GET_SESSION_KEY;
+	get_skey_in.header.status = ME_HDCP_STATUS_SUCCESS;
+	get_skey_in.header.buffer_len = WIRED_CMD_BUF_LEN_GET_SESSION_KEY_IN;
+
+	get_skey_in.port.integrated_port_type = data->port_type;
+	get_skey_in.port.physical_port = (u8)GET_MEI_DDI_INDEX(data->port);
+
+	byte = mei_cldev_send(cldev, (u8 *)&get_skey_in, sizeof(get_skey_in));
+	if (byte < 0) {
+		dev_dbg(dev, "mei_cldev_send failed. %zd\n", byte);
+		return byte;
+	}
+
+	byte = mei_cldev_recv(cldev, (u8 *)&get_skey_out, sizeof(get_skey_out));
+
+	if (byte < 0) {
+		dev_dbg(dev, "mei_cldev_recv failed. %zd\n", byte);
+		return byte;
+	}
+
+	if (get_skey_out.header.status != ME_HDCP_STATUS_SUCCESS) {
+		dev_dbg(dev, "ME cmd 0x%08X failed. status: 0x%X\n",
+			WIRED_GET_SESSION_KEY, get_skey_out.header.status);
+		return -EIO;
+	}
+
+	ske_data->msg_id = HDCP_2_2_SKE_SEND_EKS;
+	memcpy(ske_data->e_dkey_ks, get_skey_out.e_dkey_ks,
+	       HDCP_2_2_E_DKEY_KS_LEN);
+	memcpy(ske_data->riv, get_skey_out.r_iv, HDCP_2_2_RIV_LEN);
+
+	return 0;
+}
+
 static __attribute__((unused))
 struct i915_hdcp_component_ops mei_hdcp_ops = {
 	.owner = THIS_MODULE,
@@ -401,7 +457,7 @@ struct i915_hdcp_component_ops mei_hdcp_ops = {
 	.store_pairing_info = mei_store_pairing_info,
 	.initiate_locality_check = mei_initiate_locality_check,
 	.verify_lprime = mei_verify_lprime,
-	.get_session_key = NULL,
+	.get_session_key = mei_get_session_key,
 	.repeater_check_flow_prepare_ack = NULL,
 	.verify_mprime = NULL,
 	.enable_hdcp_authentication = NULL,
-- 
2.7.4

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply related	[flat|nested] 103+ messages in thread

* [PATCH v9 31/39] misc/mei/hdcp: Repeater topology verification and ack
  2018-12-13  4:01 [PATCH v9 00/39] drm/i915: Implement HDCP2.2 Ramalingam C
                   ` (29 preceding siblings ...)
  2018-12-13  4:01 ` [PATCH v9 30/39] misc/mei/hdcp: Prepare Session Key Ramalingam C
@ 2018-12-13  4:01 ` Ramalingam C
  2018-12-13  4:01 ` [PATCH v9 32/39] misc/mei/hdcp: Verify M_prime Ramalingam C
                   ` (11 subsequent siblings)
  42 siblings, 0 replies; 103+ messages in thread
From: Ramalingam C @ 2018-12-13  4:01 UTC (permalink / raw)
  To: intel-gfx, dri-devel, seanpaul, daniel.vetter, tomas.winkler,
	uma.shankar

Request ME to verify the downstream topology information received.

ME FW will validate the Repeaters receiver id list and
downstream topology.

On Success ME FW will provide the Least Significant
128bits of VPrime, which forms the repeater ack.

v2: Rebased.
v3:
  cldev is passed as first parameter [Tomas]
  Redundant comments and cast are removed [Tomas]
v4:
  %zd for ssize_t [Alexander]
  %s/return -1/return -EIO [Alexander]
  Style and typos fixed [Uma]
v5: Rebased.
v6: Rebasing.
v7:
  Adjust to the new mei interface.
  Fix for Kdoc.
v8:
  K-Doc addition. [Tomas]

Signed-off-by: Ramalingam C <ramalingam.c@intel.com>
Reviewed-by: Uma Shankar <uma.shankar@intel.com>
---
 drivers/misc/mei/hdcp/mei_hdcp.c | 76 +++++++++++++++++++++++++++++++++++++++-
 1 file changed, 75 insertions(+), 1 deletion(-)

diff --git a/drivers/misc/mei/hdcp/mei_hdcp.c b/drivers/misc/mei/hdcp/mei_hdcp.c
index 554e07ba69c3..b8c039107d0f 100644
--- a/drivers/misc/mei/hdcp/mei_hdcp.c
+++ b/drivers/misc/mei/hdcp/mei_hdcp.c
@@ -448,6 +448,80 @@ static int mei_get_session_key(struct device *dev, struct hdcp_port_data *data,
 	return 0;
 }
 
+/**
+ * mei_repeater_check_flow_prepare_ack() - Validate the Downstream topology
+ * and prepare rep_ack.
+ * @dev: device corresponding to the mei_cl_device
+ * @hdcp_data: Intel HW specific hdcp data
+ * @rep_topology: Receiver ID List to be validated
+ * @rep_send_ack : repeater ack from ME FW.
+ *
+ * Return: 0 on Success, <0 on Failure
+ */
+static int
+mei_repeater_check_flow_prepare_ack(struct device *dev,
+				    struct hdcp_port_data *data,
+				    struct hdcp2_rep_send_receiverid_list
+							*rep_topology,
+				    struct hdcp2_rep_send_ack *rep_send_ack)
+{
+	struct wired_cmd_verify_repeater_in verify_repeater_in = { { 0 } };
+	struct wired_cmd_verify_repeater_out verify_repeater_out = { { 0 } };
+	struct mei_cl_device *cldev;
+	ssize_t byte;
+
+	if (!dev || !rep_topology || !rep_send_ack || !data)
+		return -EINVAL;
+
+	cldev = to_mei_cl_device(dev);
+
+	verify_repeater_in.header.api_version = HDCP_API_VERSION;
+	verify_repeater_in.header.command_id = WIRED_VERIFY_REPEATER;
+	verify_repeater_in.header.status = ME_HDCP_STATUS_SUCCESS;
+	verify_repeater_in.header.buffer_len =
+					WIRED_CMD_BUF_LEN_VERIFY_REPEATER_IN;
+
+	verify_repeater_in.port.integrated_port_type = data->port_type;
+	verify_repeater_in.port.physical_port =
+					(u8)GET_MEI_DDI_INDEX(data->port);
+
+	memcpy(verify_repeater_in.rx_info, rep_topology->rx_info,
+	       HDCP_2_2_RXINFO_LEN);
+	memcpy(verify_repeater_in.seq_num_v, rep_topology->seq_num_v,
+	       HDCP_2_2_SEQ_NUM_LEN);
+	memcpy(verify_repeater_in.v_prime, rep_topology->v_prime,
+	       HDCP_2_2_V_PRIME_HALF_LEN);
+	memcpy(verify_repeater_in.receiver_ids, rep_topology->receiver_ids,
+	       HDCP_2_2_RECEIVER_IDS_MAX_LEN);
+
+	byte = mei_cldev_send(cldev, (u8 *)&verify_repeater_in,
+			      sizeof(verify_repeater_in));
+	if (byte < 0) {
+		dev_dbg(dev, "mei_cldev_send failed. %zd\n", byte);
+		return byte;
+	}
+
+	byte = mei_cldev_recv(cldev, (u8 *)&verify_repeater_out,
+			      sizeof(verify_repeater_out));
+	if (byte < 0) {
+		dev_dbg(dev, "mei_cldev_recv failed. %zd\n", byte);
+		return byte;
+	}
+
+	if (verify_repeater_out.header.status != ME_HDCP_STATUS_SUCCESS) {
+		dev_dbg(dev, "ME cmd 0x%08X failed. status: 0x%X\n",
+			WIRED_VERIFY_REPEATER,
+			verify_repeater_out.header.status);
+		return -EIO;
+	}
+
+	memcpy(rep_send_ack->v, verify_repeater_out.v,
+	       HDCP_2_2_V_PRIME_HALF_LEN);
+	rep_send_ack->msg_id = HDCP_2_2_REP_SEND_ACK;
+
+	return 0;
+}
+
 static __attribute__((unused))
 struct i915_hdcp_component_ops mei_hdcp_ops = {
 	.owner = THIS_MODULE,
@@ -458,7 +532,7 @@ struct i915_hdcp_component_ops mei_hdcp_ops = {
 	.initiate_locality_check = mei_initiate_locality_check,
 	.verify_lprime = mei_verify_lprime,
 	.get_session_key = mei_get_session_key,
-	.repeater_check_flow_prepare_ack = NULL,
+	.repeater_check_flow_prepare_ack = mei_repeater_check_flow_prepare_ack,
 	.verify_mprime = NULL,
 	.enable_hdcp_authentication = NULL,
 	.close_hdcp_session = NULL,
-- 
2.7.4

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply related	[flat|nested] 103+ messages in thread

* [PATCH v9 32/39] misc/mei/hdcp: Verify M_prime
  2018-12-13  4:01 [PATCH v9 00/39] drm/i915: Implement HDCP2.2 Ramalingam C
                   ` (30 preceding siblings ...)
  2018-12-13  4:01 ` [PATCH v9 31/39] misc/mei/hdcp: Repeater topology verification and ack Ramalingam C
@ 2018-12-13  4:01 ` Ramalingam C
  2018-12-13  4:01 ` [PATCH v9 33/39] misc/mei/hdcp: Enabling the HDCP authentication Ramalingam C
                   ` (10 subsequent siblings)
  42 siblings, 0 replies; 103+ messages in thread
From: Ramalingam C @ 2018-12-13  4:01 UTC (permalink / raw)
  To: intel-gfx, dri-devel, seanpaul, daniel.vetter, tomas.winkler,
	uma.shankar

Request to ME to verify the M_Prime received from the HDCP sink.

ME FW will calculate the M and compare with M_prime received
as part of RepeaterAuth_Stream_Ready, which is HDCP2.2 protocol msg.

On successful completion of this stage, downstream propagation of
the stream management info is completed.

v2: Rebased.
v3:
  cldev is passed as first parameter [Tomas]
  Redundant comments and cast are removed [Tomas]
v4:
  %zd for ssize_t [Alexander]
  %s/return -1/return -EIO [Alexander]
  endianness conversion func is moved to drm_hdcp.h [Uma]
v5: Rebased.
v6:
  Collected the Rb-ed by.
  Rebasing.
v7:
  Adjust to the new mei interface.
  Fix for Kdoc.
v8:
  K-Doc addition. [Tomas]
  drm_hdcp2_u32_to_seq_num() is used for u32 to seq_num.

Signed-off-by: Ramalingam C <ramalingam.c@intel.com>
Reviewed-by: Uma Shankar <uma.shankar@intel.com>
---
 drivers/misc/mei/hdcp/mei_hdcp.c | 66 +++++++++++++++++++++++++++++++++++++++-
 1 file changed, 65 insertions(+), 1 deletion(-)

diff --git a/drivers/misc/mei/hdcp/mei_hdcp.c b/drivers/misc/mei/hdcp/mei_hdcp.c
index b8c039107d0f..9f24a66e3260 100644
--- a/drivers/misc/mei/hdcp/mei_hdcp.c
+++ b/drivers/misc/mei/hdcp/mei_hdcp.c
@@ -522,6 +522,70 @@ mei_repeater_check_flow_prepare_ack(struct device *dev,
 	return 0;
 }
 
+/**
+ * mei_verify_mprime() - Verify mprime.
+ * @dev: device corresponding to the mei_cl_device
+ * @hdcp_data: Intel HW specific hdcp data
+ * @stream_ready: RepeaterAuth_Stream_Ready msg for ME FW verification.
+ *
+ * Return: 0 on Success, <0 on Failure
+ */
+static int mei_verify_mprime(struct device *dev, struct hdcp_port_data *data,
+			     struct hdcp2_rep_stream_ready *stream_ready)
+{
+	struct wired_cmd_repeater_auth_stream_req_in
+					verify_mprime_in = { { 0 } };
+	struct wired_cmd_repeater_auth_stream_req_out
+					verify_mprime_out = { { 0 } };
+	struct mei_cl_device *cldev;
+	ssize_t byte;
+
+	if (!dev || !stream_ready || !data)
+		return -EINVAL;
+
+	cldev = to_mei_cl_device(dev);
+
+	verify_mprime_in.header.api_version = HDCP_API_VERSION;
+	verify_mprime_in.header.command_id = WIRED_REPEATER_AUTH_STREAM_REQ;
+	verify_mprime_in.header.status = ME_HDCP_STATUS_SUCCESS;
+	verify_mprime_in.header.buffer_len =
+			WIRED_CMD_BUF_LEN_REPEATER_AUTH_STREAM_REQ_MIN_IN;
+
+	verify_mprime_in.port.integrated_port_type = data->port_type;
+	verify_mprime_in.port.physical_port = (u8)GET_MEI_DDI_INDEX(data->port);
+
+	memcpy(verify_mprime_in.m_prime, stream_ready->m_prime,
+	       HDCP_2_2_MPRIME_LEN);
+	drm_hdcp2_u32_to_seq_num(verify_mprime_in.seq_num_m, data->seq_num_m);
+	memcpy(verify_mprime_in.streams, data->streams,
+	       (data->k * sizeof(struct hdcp2_streamid_type)));
+
+	verify_mprime_in.k = __swab16(data->k);
+
+	byte = mei_cldev_send(cldev, (u8 *)&verify_mprime_in,
+			      sizeof(verify_mprime_in));
+	if (byte < 0) {
+		dev_dbg(dev, "mei_cldev_send failed. %zd\n", byte);
+		return byte;
+	}
+
+	byte = mei_cldev_recv(cldev, (u8 *)&verify_mprime_out,
+			      sizeof(verify_mprime_out));
+	if (byte < 0) {
+		dev_dbg(dev, "mei_cldev_recv failed. %zd\n", byte);
+		return byte;
+	}
+
+	if (verify_mprime_out.header.status != ME_HDCP_STATUS_SUCCESS) {
+		dev_dbg(dev, "ME cmd 0x%08X failed. status: 0x%X\n",
+			WIRED_REPEATER_AUTH_STREAM_REQ,
+			verify_mprime_out.header.status);
+		return -EIO;
+	}
+
+	return 0;
+}
+
 static __attribute__((unused))
 struct i915_hdcp_component_ops mei_hdcp_ops = {
 	.owner = THIS_MODULE,
@@ -533,7 +597,7 @@ struct i915_hdcp_component_ops mei_hdcp_ops = {
 	.verify_lprime = mei_verify_lprime,
 	.get_session_key = mei_get_session_key,
 	.repeater_check_flow_prepare_ack = mei_repeater_check_flow_prepare_ack,
-	.verify_mprime = NULL,
+	.verify_mprime = mei_verify_mprime,
 	.enable_hdcp_authentication = NULL,
 	.close_hdcp_session = NULL,
 };
-- 
2.7.4

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply related	[flat|nested] 103+ messages in thread

* [PATCH v9 33/39] misc/mei/hdcp: Enabling the HDCP authentication
  2018-12-13  4:01 [PATCH v9 00/39] drm/i915: Implement HDCP2.2 Ramalingam C
                   ` (31 preceding siblings ...)
  2018-12-13  4:01 ` [PATCH v9 32/39] misc/mei/hdcp: Verify M_prime Ramalingam C
@ 2018-12-13  4:01 ` Ramalingam C
  2018-12-13  4:01 ` [PATCH v9 34/39] misc/mei/hdcp: Closing wired HDCP2.2 Tx Session Ramalingam C
                   ` (9 subsequent siblings)
  42 siblings, 0 replies; 103+ messages in thread
From: Ramalingam C @ 2018-12-13  4:01 UTC (permalink / raw)
  To: intel-gfx, dri-devel, seanpaul, daniel.vetter, tomas.winkler,
	uma.shankar

Request to ME to configure a port as authenticated.

On Success, ME FW will mark the port as authenticated and provides
HDCP cipher with the encryption keys.

Enabling the Authentication can be requested once all stages of
HDCP2.2 authentication is completed by interacting with ME FW.

Only after this stage, driver can enable the HDCP encryption for
the port, through HW registers.

v2: Rebased.
v3:
  cldev is passed as first parameter [Tomas]
  Redundant comments and cast are removed [Tomas]
v4:
  %zd for ssize_t [Alexander]
  %s/return -1/return -EIO [Alexander]
  Style and typos fixed [Uma]
v5: Rebased.
v6:
  Collected the Rb-ed by.
  Rebased.
v7:
  Adjust to the new mei interface.
  Fix for Kdoc.
v8:
  K-Doc addition. [Tomas]

Signed-off-by: Ramalingam C <ramalingam.c@intel.com>
Reviewed-by: Uma Shankar <uma.shankar@intel.com>
---
 drivers/misc/mei/hdcp/mei_hdcp.c | 54 +++++++++++++++++++++++++++++++++++++++-
 1 file changed, 53 insertions(+), 1 deletion(-)

diff --git a/drivers/misc/mei/hdcp/mei_hdcp.c b/drivers/misc/mei/hdcp/mei_hdcp.c
index 9f24a66e3260..9569a5b85fd0 100644
--- a/drivers/misc/mei/hdcp/mei_hdcp.c
+++ b/drivers/misc/mei/hdcp/mei_hdcp.c
@@ -586,6 +586,58 @@ static int mei_verify_mprime(struct device *dev, struct hdcp_port_data *data,
 	return 0;
 }
 
+/**
+ * mei_enable_hdcp_authentication() - Mark a port as authenticated through ME FW
+ * @dev: device corresponding to the mei_cl_device
+ * @hdcp_data: Intel HW specific hdcp data
+ *
+ * Return: 0 on Success, <0 on Failure
+ */
+static int
+mei_enable_hdcp_authentication(struct device *dev, struct hdcp_port_data *data)
+{
+	struct wired_cmd_enable_auth_in enable_auth_in = { { 0 } };
+	struct wired_cmd_enable_auth_out enable_auth_out = { { 0 } };
+	struct mei_cl_device *cldev;
+	ssize_t byte;
+
+	if (!dev || !data)
+		return -EINVAL;
+
+	cldev = to_mei_cl_device(dev);
+
+	enable_auth_in.header.api_version = HDCP_API_VERSION;
+	enable_auth_in.header.command_id = WIRED_ENABLE_AUTH;
+	enable_auth_in.header.status = ME_HDCP_STATUS_SUCCESS;
+	enable_auth_in.header.buffer_len = WIRED_CMD_BUF_LEN_ENABLE_AUTH_IN;
+
+	enable_auth_in.port.integrated_port_type = data->port_type;
+	enable_auth_in.port.physical_port = (u8)GET_MEI_DDI_INDEX(data->port);
+	enable_auth_in.stream_type = data->streams[0].stream_type;
+
+	byte = mei_cldev_send(cldev, (u8 *)&enable_auth_in,
+			      sizeof(enable_auth_in));
+	if (byte < 0) {
+		dev_dbg(dev, "mei_cldev_send failed. %zd\n", byte);
+		return byte;
+	}
+
+	byte = mei_cldev_recv(cldev, (u8 *)&enable_auth_out,
+			      sizeof(enable_auth_out));
+	if (byte < 0) {
+		dev_dbg(dev, "mei_cldev_recv failed. %zd\n", byte);
+		return byte;
+	}
+
+	if (enable_auth_out.header.status != ME_HDCP_STATUS_SUCCESS) {
+		dev_dbg(dev, "ME cmd 0x%08X failed. status: 0x%X\n",
+			WIRED_ENABLE_AUTH, enable_auth_out.header.status);
+		return -EIO;
+	}
+
+	return 0;
+}
+
 static __attribute__((unused))
 struct i915_hdcp_component_ops mei_hdcp_ops = {
 	.owner = THIS_MODULE,
@@ -598,7 +650,7 @@ struct i915_hdcp_component_ops mei_hdcp_ops = {
 	.get_session_key = mei_get_session_key,
 	.repeater_check_flow_prepare_ack = mei_repeater_check_flow_prepare_ack,
 	.verify_mprime = mei_verify_mprime,
-	.enable_hdcp_authentication = NULL,
+	.enable_hdcp_authentication = mei_enable_hdcp_authentication,
 	.close_hdcp_session = NULL,
 };
 
-- 
2.7.4

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply related	[flat|nested] 103+ messages in thread

* [PATCH v9 34/39] misc/mei/hdcp: Closing wired HDCP2.2 Tx Session
  2018-12-13  4:01 [PATCH v9 00/39] drm/i915: Implement HDCP2.2 Ramalingam C
                   ` (32 preceding siblings ...)
  2018-12-13  4:01 ` [PATCH v9 33/39] misc/mei/hdcp: Enabling the HDCP authentication Ramalingam C
@ 2018-12-13  4:01 ` Ramalingam C
  2018-12-13  4:01 ` [PATCH v9 35/39] misc/mei/hdcp: Component framework for I915 Interface Ramalingam C
                   ` (8 subsequent siblings)
  42 siblings, 0 replies; 103+ messages in thread
From: Ramalingam C @ 2018-12-13  4:01 UTC (permalink / raw)
  To: intel-gfx, dri-devel, seanpaul, daniel.vetter, tomas.winkler,
	uma.shankar

Request the ME to terminate the HDCP2.2 session for a port.

On Success, ME FW will mark the intel port as Deauthenticated and
terminate the wired HDCP2.2 Tx session started due to the cmd
WIRED_INITIATE_HDCP2_SESSION.

v2: Rebased.
v3:
  cldev is passed as first parameter [Tomas]
  Redundant comments and cast are removed [Tomas]
v4:
  %zd for ssize_t [Alexander]
  %s/return -1/return -EIO [Alexander]
  Style and typos fixed [Uma]
v5:
  Extra line is removed.
v6:
  Collected the Rb-ed by.
  Rebased.
v7:
  Adjust to the new mei interface.
  Fix for Kdoc.
v8:
  K-Doc addition.[Tomas]

Signed-off-by: Ramalingam C <ramalingam.c@intel.com>
Reviewed-by: Uma Shankar <uma.shankar@intel.com>
---
 drivers/misc/mei/hdcp/mei_hdcp.c | 55 +++++++++++++++++++++++++++++++++++++++-
 1 file changed, 54 insertions(+), 1 deletion(-)

diff --git a/drivers/misc/mei/hdcp/mei_hdcp.c b/drivers/misc/mei/hdcp/mei_hdcp.c
index 9569a5b85fd0..b22a71e8c5d7 100644
--- a/drivers/misc/mei/hdcp/mei_hdcp.c
+++ b/drivers/misc/mei/hdcp/mei_hdcp.c
@@ -638,6 +638,59 @@ mei_enable_hdcp_authentication(struct device *dev, struct hdcp_port_data *data)
 	return 0;
 }
 
+/**
+ * mei_close_hdcp_session() - Close the Wired HDCP Tx session of ME FW per port.
+ * This also disables the authenticated state of the port.
+ * @dev: device corresponding to the mei_cl_device
+ * @hdcp_data: Intel HW specific hdcp data
+ *
+ * Return: 0 on Success, <0 on Failure
+ */
+static int
+mei_close_hdcp_session(struct device *dev, struct hdcp_port_data *data)
+{
+	struct wired_cmd_close_session_in session_close_in = { { 0 } };
+	struct wired_cmd_close_session_out session_close_out = { { 0 } };
+	struct mei_cl_device *cldev;
+	ssize_t byte;
+
+	if (!dev || !data)
+		return -EINVAL;
+
+	cldev = to_mei_cl_device(dev);
+
+	session_close_in.header.api_version = HDCP_API_VERSION;
+	session_close_in.header.command_id = WIRED_CLOSE_SESSION;
+	session_close_in.header.status = ME_HDCP_STATUS_SUCCESS;
+	session_close_in.header.buffer_len =
+				WIRED_CMD_BUF_LEN_CLOSE_SESSION_IN;
+
+	session_close_in.port.integrated_port_type = data->port_type;
+	session_close_in.port.physical_port = (u8)GET_MEI_DDI_INDEX(data->port);
+
+	byte = mei_cldev_send(cldev, (u8 *)&session_close_in,
+			      sizeof(session_close_in));
+	if (byte < 0) {
+		dev_dbg(dev, "mei_cldev_send failed. %zd\n", byte);
+		return byte;
+	}
+
+	byte = mei_cldev_recv(cldev, (u8 *)&session_close_out,
+			      sizeof(session_close_out));
+	if (byte < 0) {
+		dev_dbg(dev, "mei_cldev_recv failed. %zd\n", byte);
+		return byte;
+	}
+
+	if (session_close_out.header.status != ME_HDCP_STATUS_SUCCESS) {
+		dev_dbg(dev, "Session Close Failed. status: 0x%X\n",
+			session_close_out.header.status);
+		return -EIO;
+	}
+
+	return 0;
+}
+
 static __attribute__((unused))
 struct i915_hdcp_component_ops mei_hdcp_ops = {
 	.owner = THIS_MODULE,
@@ -651,7 +704,7 @@ struct i915_hdcp_component_ops mei_hdcp_ops = {
 	.repeater_check_flow_prepare_ack = mei_repeater_check_flow_prepare_ack,
 	.verify_mprime = mei_verify_mprime,
 	.enable_hdcp_authentication = mei_enable_hdcp_authentication,
-	.close_hdcp_session = NULL,
+	.close_hdcp_session = mei_close_hdcp_session,
 };
 
 static int mei_hdcp_probe(struct mei_cl_device *cldev,
-- 
2.7.4

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply related	[flat|nested] 103+ messages in thread

* [PATCH v9 35/39] misc/mei/hdcp: Component framework for I915 Interface
  2018-12-13  4:01 [PATCH v9 00/39] drm/i915: Implement HDCP2.2 Ramalingam C
                   ` (33 preceding siblings ...)
  2018-12-13  4:01 ` [PATCH v9 34/39] misc/mei/hdcp: Closing wired HDCP2.2 Tx Session Ramalingam C
@ 2018-12-13  4:01 ` Ramalingam C
  2018-12-13 12:36   ` C, Ramalingam
  2018-12-13  4:01 ` [PATCH v9 36/39] drm/i915: Commit CP without modeset Ramalingam C
                   ` (7 subsequent siblings)
  42 siblings, 1 reply; 103+ messages in thread
From: Ramalingam C @ 2018-12-13  4:01 UTC (permalink / raw)
  To: intel-gfx, dri-devel, seanpaul, daniel.vetter, tomas.winkler,
	uma.shankar

Mei hdcp driver is designed as component slave for the I915 component
master.

v2: Rebased.
v3:
  Notifier chain is adopted for cldev state update [Tomas]
v4:
  Made static dummy functions as inline in mei_hdcp.h
  API for polling client device status
  IS_ENABLED used in header, for config status for mei_hdcp.
v5:
  Replacing the notifier with component framework. [Daniel]
v6:
  Rebased on the I915 comp master redesign.
v7:
  mei_hdcp_component_registered is made static [Uma]
  Need for global static variable mei_cldev is removed.

Signed-off-by: Ramalingam C <ramalingam.c@intel.com>
Reviewed-by: Uma Shankar <uma.shankar@intel.com>
---
 drivers/misc/mei/hdcp/mei_hdcp.c | 67 +++++++++++++++++++++++++++++++++++++---
 1 file changed, 63 insertions(+), 4 deletions(-)

diff --git a/drivers/misc/mei/hdcp/mei_hdcp.c b/drivers/misc/mei/hdcp/mei_hdcp.c
index b22a71e8c5d7..3de1700dcc9f 100644
--- a/drivers/misc/mei/hdcp/mei_hdcp.c
+++ b/drivers/misc/mei/hdcp/mei_hdcp.c
@@ -23,11 +23,14 @@
 #include <linux/slab.h>
 #include <linux/uuid.h>
 #include <linux/mei_cl_bus.h>
+#include <linux/component.h>
 #include <drm/drm_connector.h>
 #include <drm/i915_component.h>
 
 #include "mei_hdcp.h"
 
+static bool mei_hdcp_component_registered;
+
 /**
  * mei_initiate_hdcp2_session() - Initiate a Wired HDCP2.2 Tx Session in ME FW
  * @dev: device corresponding to the mei_cl_device
@@ -691,8 +694,7 @@ mei_close_hdcp_session(struct device *dev, struct hdcp_port_data *data)
 	return 0;
 }
 
-static __attribute__((unused))
-struct i915_hdcp_component_ops mei_hdcp_ops = {
+static struct i915_hdcp_component_ops mei_hdcp_ops = {
 	.owner = THIS_MODULE,
 	.initiate_hdcp2_session = mei_initiate_hdcp2_session,
 	.verify_receiver_cert_prepare_km = mei_verify_receiver_cert_prepare_km,
@@ -707,20 +709,77 @@ struct i915_hdcp_component_ops mei_hdcp_ops = {
 	.close_hdcp_session = mei_close_hdcp_session,
 };
 
+static int mei_hdcp_component_bind(struct device *mei_kdev,
+				   struct device *i915_kdev, void *data)
+{
+	struct i915_component_master *master_comp = data;
+
+	dev_info(mei_kdev, "MEI HDCP comp bind\n");
+	WARN_ON(master_comp->hdcp_ops);
+	master_comp->hdcp_ops = &mei_hdcp_ops;
+	master_comp->mei_dev = mei_kdev;
+
+	return 0;
+}
+
+static void mei_hdcp_component_unbind(struct device *mei_kdev,
+				      struct device *i915_kdev, void *data)
+{
+	struct i915_component_master *master_comp = data;
+
+	dev_info(mei_kdev, "MEI HDCP comp unbind\n");
+	master_comp->hdcp_ops = NULL;
+	master_comp->mei_dev = NULL;
+}
+
+static const struct component_ops mei_hdcp_component_bind_ops = {
+	.bind	= mei_hdcp_component_bind,
+	.unbind	= mei_hdcp_component_unbind,
+};
+
+static void mei_hdcp_component_init(struct device *dev)
+{
+	int ret;
+
+	dev_info(dev, "MEI HDCP comp init\n");
+	ret = component_add(dev, &mei_hdcp_component_bind_ops);
+	if (ret < 0) {
+		dev_err(dev, "Failed to add MEI HDCP comp (%d)\n", ret);
+		return;
+	}
+
+	mei_hdcp_component_registered = true;
+}
+
+static void mei_hdcp_component_cleanup(struct device *dev)
+{
+	if (!mei_hdcp_component_registered)
+		return;
+
+	dev_info(dev, "MEI HDCP comp cleanup\n");
+	component_del(dev, &mei_hdcp_component_bind_ops);
+	mei_hdcp_component_registered = false;
+}
+
 static int mei_hdcp_probe(struct mei_cl_device *cldev,
 			  const struct mei_cl_device_id *id)
 {
 	int ret;
 
 	ret = mei_cldev_enable(cldev);
-	if (ret < 0)
+	if (ret < 0) {
 		dev_err(&cldev->dev, "mei_cldev_enable Failed. %d\n", ret);
+		return ret;
+	}
+	mei_hdcp_component_init(&cldev->dev);
 
-	return ret;
+	return 0;
 }
 
 static int mei_hdcp_remove(struct mei_cl_device *cldev)
 {
+	mei_hdcp_component_cleanup(&cldev->dev);
+
 	return mei_cldev_disable(cldev);
 }
 
-- 
2.7.4

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply related	[flat|nested] 103+ messages in thread

* [PATCH v9 36/39] drm/i915: Commit CP without modeset
  2018-12-13  4:01 [PATCH v9 00/39] drm/i915: Implement HDCP2.2 Ramalingam C
                   ` (34 preceding siblings ...)
  2018-12-13  4:01 ` [PATCH v9 35/39] misc/mei/hdcp: Component framework for I915 Interface Ramalingam C
@ 2018-12-13  4:01 ` Ramalingam C
  2018-12-13  4:01 ` [PATCH v9 37/39] drm/i915: Fix KBL HDCP2.2 encrypt status signalling Ramalingam C
                   ` (6 subsequent siblings)
  42 siblings, 0 replies; 103+ messages in thread
From: Ramalingam C @ 2018-12-13  4:01 UTC (permalink / raw)
  To: intel-gfx, dri-devel, seanpaul, daniel.vetter, tomas.winkler,
	uma.shankar

Commits the content protection change of a connector,
without crtc modeset. This improves the user experience.

Originally proposed by Sean Paul at v3 of HDCP1.4 framework
https://patchwork.freedesktop.org/patch/191759/. For some
reason this was dropped, but needed for the proper functionality
of HDCP encryption.

Signed-off-by: Ramalingam C <ramalingam.c@intel.com>
Suggested-by: Sean Paul <seanpaul@chromium.org>
---
 drivers/gpu/drm/i915/intel_ddi.c     |  7 -------
 drivers/gpu/drm/i915/intel_display.c | 10 ++++++++++
 drivers/gpu/drm/i915/intel_drv.h     |  5 +++++
 drivers/gpu/drm/i915/intel_hdcp.c    | 32 ++++++++++++++++++++++++++++----
 4 files changed, 43 insertions(+), 11 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c
index 92c0bf70fe09..feb78780976d 100644
--- a/drivers/gpu/drm/i915/intel_ddi.c
+++ b/drivers/gpu/drm/i915/intel_ddi.c
@@ -3548,11 +3548,6 @@ static void intel_enable_ddi(struct intel_encoder *encoder,
 		intel_enable_ddi_hdmi(encoder, crtc_state, conn_state);
 	else
 		intel_enable_ddi_dp(encoder, crtc_state, conn_state);
-
-	/* Enable hdcp if it's desired */
-	if (conn_state->content_protection ==
-	    DRM_MODE_CONTENT_PROTECTION_DESIRED)
-		intel_hdcp_enable(to_intel_connector(conn_state->connector));
 }
 
 static void intel_disable_ddi_dp(struct intel_encoder *encoder,
@@ -3595,8 +3590,6 @@ static void intel_disable_ddi(struct intel_encoder *encoder,
 			      const struct intel_crtc_state *old_crtc_state,
 			      const struct drm_connector_state *old_conn_state)
 {
-	intel_hdcp_disable(to_intel_connector(old_conn_state->connector));
-
 	if (intel_crtc_has_type(old_crtc_state, INTEL_OUTPUT_HDMI))
 		intel_disable_ddi_hdmi(encoder, old_crtc_state, old_conn_state);
 	else
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index 13e5650b6f31..05bae91512cd 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -12922,6 +12922,8 @@ static void intel_atomic_commit_tail(struct drm_atomic_state *state)
 	struct drm_i915_private *dev_priv = to_i915(dev);
 	struct drm_crtc_state *old_crtc_state, *new_crtc_state;
 	struct intel_crtc_state *new_intel_crtc_state, *old_intel_crtc_state;
+	struct drm_connector_state *old_conn_state, *new_conn_state;
+	struct drm_connector *connector;
 	struct drm_crtc *crtc;
 	struct intel_crtc *intel_crtc;
 	u64 put_domains[I915_MAX_PIPES] = {};
@@ -13015,9 +13017,17 @@ static void intel_atomic_commit_tail(struct drm_atomic_state *state)
 		}
 	}
 
+	for_each_oldnew_connector_in_state(state, connector, old_conn_state,
+					   new_conn_state, i)
+		intel_hdcp_atomic_pre_commit(connector, old_conn_state,
+					     new_conn_state);
+
 	/* Now enable the clocks, plane, pipe, and connectors that we set up. */
 	dev_priv->display.update_crtcs(state);
 
+	for_each_new_connector_in_state(state, connector, new_conn_state, i)
+		intel_hdcp_atomic_commit(connector, new_conn_state);
+
 	/* FIXME: We should call drm_atomic_helper_commit_hw_done() here
 	 * already, but still need the state for the delayed optimization. To
 	 * fix this:
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index 60d1359e55f4..40357e17324e 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -2100,6 +2100,11 @@ static inline void intel_backlight_device_unregister(struct intel_connector *con
 void intel_hdcp_atomic_check(struct drm_connector *connector,
 			     struct drm_connector_state *old_state,
 			     struct drm_connector_state *new_state);
+void intel_hdcp_atomic_pre_commit(struct drm_connector *connector,
+				  struct drm_connector_state *old_state,
+				  struct drm_connector_state *new_state);
+void intel_hdcp_atomic_commit(struct drm_connector *connector,
+			      struct drm_connector_state *new_state);
 int intel_hdcp_init(struct intel_connector *connector,
 		    const struct intel_hdcp_shim *hdcp_shim,
 		    bool hdcp2_supported);
diff --git a/drivers/gpu/drm/i915/intel_hdcp.c b/drivers/gpu/drm/i915/intel_hdcp.c
index cafda8903b50..42327ed30903 100644
--- a/drivers/gpu/drm/i915/intel_hdcp.c
+++ b/drivers/gpu/drm/i915/intel_hdcp.c
@@ -1760,7 +1760,6 @@ void intel_hdcp_atomic_check(struct drm_connector *connector,
 {
 	uint64_t old_cp = old_state->content_protection;
 	uint64_t new_cp = new_state->content_protection;
-	struct drm_crtc_state *crtc_state;
 
 	if (!new_state->crtc) {
 		/*
@@ -1781,10 +1780,35 @@ void intel_hdcp_atomic_check(struct drm_connector *connector,
 	    (old_cp == DRM_MODE_CONTENT_PROTECTION_DESIRED &&
 	     new_cp == DRM_MODE_CONTENT_PROTECTION_ENABLED))
 		return;
+}
+
+void intel_hdcp_atomic_pre_commit(struct drm_connector *connector,
+				  struct drm_connector_state *old_state,
+				  struct drm_connector_state *new_state)
+{
+	u64 old_cp = old_state->content_protection;
+	u64 new_cp = new_state->content_protection;
+
+	/*
+	 * Disable HDCP if the connector is becoming disabled, or if requested
+	 * via the property.
+	 */
+	if ((!new_state->crtc &&
+	     old_cp != DRM_MODE_CONTENT_PROTECTION_UNDESIRED) ||
+	    (new_state->crtc &&
+	     old_cp != DRM_MODE_CONTENT_PROTECTION_UNDESIRED &&
+	     new_cp == DRM_MODE_CONTENT_PROTECTION_UNDESIRED))
+		intel_hdcp_disable(to_intel_connector(connector));
+}
+
+void intel_hdcp_atomic_commit(struct drm_connector *connector,
+			      struct drm_connector_state *new_state)
+{
+	u64 new_cp = new_state->content_protection;
 
-	crtc_state = drm_atomic_get_new_crtc_state(new_state->state,
-						   new_state->crtc);
-	crtc_state->mode_changed = true;
+	/* Enable hdcp if it's desired */
+	if (new_state->crtc && new_cp == DRM_MODE_CONTENT_PROTECTION_DESIRED)
+		intel_hdcp_enable(to_intel_connector(connector));
 }
 
 /* Handles the CP_IRQ raised from the DP HDCP sink */
-- 
2.7.4

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply related	[flat|nested] 103+ messages in thread

* [PATCH v9 37/39] drm/i915: Fix KBL HDCP2.2 encrypt status signalling
  2018-12-13  4:01 [PATCH v9 00/39] drm/i915: Implement HDCP2.2 Ramalingam C
                   ` (35 preceding siblings ...)
  2018-12-13  4:01 ` [PATCH v9 36/39] drm/i915: Commit CP without modeset Ramalingam C
@ 2018-12-13  4:01 ` Ramalingam C
  2018-12-19 15:40   ` Daniel Vetter
  2018-12-13  4:01 ` [PATCH v9 38/39] FOR_TEST: i915/Kconfig: Select mei_hdcp by I915 Ramalingam C
                   ` (5 subsequent siblings)
  42 siblings, 1 reply; 103+ messages in thread
From: Ramalingam C @ 2018-12-13  4:01 UTC (permalink / raw)
  To: intel-gfx, dri-devel, seanpaul, daniel.vetter, tomas.winkler,
	uma.shankar

Implement the required WA sequence for KBL to fix the
incorrect positioning of the window of oppurtunity and enc_en
signalling.

Signed-off-by: Ramalingam C <ramalingam.c@intel.com>
---
 drivers/gpu/drm/i915/intel_hdcp.c | 29 +++++++++++++++++++++++++++++
 1 file changed, 29 insertions(+)

diff --git a/drivers/gpu/drm/i915/intel_hdcp.c b/drivers/gpu/drm/i915/intel_hdcp.c
index 42327ed30903..2b9e1b6d0b1e 100644
--- a/drivers/gpu/drm/i915/intel_hdcp.c
+++ b/drivers/gpu/drm/i915/intel_hdcp.c
@@ -12,6 +12,7 @@
 #include <linux/i2c.h>
 #include <linux/random.h>
 #include <linux/component.h>
+#include <linux/delay.h>
 
 #include "intel_drv.h"
 #include "i915_reg.h"
@@ -20,6 +21,27 @@
 #define ENCRYPT_STATUS_CHANGE_TIMEOUT_MS	50
 #define HDCP2_LC_RETRY_CNT			3
 
+static void kbl_repositioning_enc_en_signal(struct intel_connector *connector)
+{
+	struct drm_i915_private *dev_priv = to_i915(connector->base.dev);
+	struct intel_digital_port *intel_dig_port = conn_to_dig_port(connector);
+	struct intel_hdcp *hdcp = &connector->hdcp;
+	struct drm_crtc *crtc = connector->base.state->crtc;
+	struct intel_crtc *intel_crtc = container_of(crtc,
+						     struct intel_crtc, base);
+	u32 scanline;
+
+	for (;;) {
+		scanline = I915_READ(PIPEDSL(intel_crtc->pipe));
+		if (scanline > 100 && scanline < 200)
+			break;
+		usleep_range(25, 50);
+	}
+
+	hdcp->shim->toggle_signalling(intel_dig_port, false);
+	hdcp->shim->toggle_signalling(intel_dig_port, true);
+}
+
 static
 bool intel_hdcp_is_ksv_valid(u8 *ksv)
 {
@@ -1382,6 +1404,13 @@ static int hdcp2_enable_encryption(struct intel_connector *connector)
 	}
 
 	if (I915_READ(HDCP2_STATUS_DDI(port)) & LINK_AUTH_STATUS) {
+		/*
+		 * WA: To fix incorrect positioning of the window of
+		 * opportunity and enc_en signalling in KABYLAKE.
+		 */
+		if (IS_KABYLAKE(dev_priv) && hdcp->shim->toggle_signalling)
+			kbl_repositioning_enc_en_signal(connector);
+
 		/* Link is Authenticated. Now set for Encryption */
 		I915_WRITE(HDCP2_CTL_DDI(port),
 			   I915_READ(HDCP2_CTL_DDI(port)) |
-- 
2.7.4

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply related	[flat|nested] 103+ messages in thread

* [PATCH v9 38/39] FOR_TEST: i915/Kconfig: Select mei_hdcp by I915
  2018-12-13  4:01 [PATCH v9 00/39] drm/i915: Implement HDCP2.2 Ramalingam C
                   ` (36 preceding siblings ...)
  2018-12-13  4:01 ` [PATCH v9 37/39] drm/i915: Fix KBL HDCP2.2 encrypt status signalling Ramalingam C
@ 2018-12-13  4:01 ` Ramalingam C
  2018-12-13  4:01 ` [PATCH v9 39/39] FOR_TESTING_ONLY: debugfs: Excluding the LSPCon for HDCP1.4 Ramalingam C
                   ` (4 subsequent siblings)
  42 siblings, 0 replies; 103+ messages in thread
From: Ramalingam C @ 2018-12-13  4:01 UTC (permalink / raw)
  To: intel-gfx, dri-devel, seanpaul, daniel.vetter, tomas.winkler,
	uma.shankar

FOR TESTING PURPOSE ONLY.

By default INTEL_MEI_HDCP is set to y. This patch is created to
test the interface between I915 and MEI_HDCP.

Signed-off-by: Ramalingam C <ramalingam.c@intel.com>
---
 drivers/misc/mei/Kconfig | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/misc/mei/Kconfig b/drivers/misc/mei/Kconfig
index 9c518b7f0011..90ed55210447 100644
--- a/drivers/misc/mei/Kconfig
+++ b/drivers/misc/mei/Kconfig
@@ -48,5 +48,6 @@ config INTEL_MEI_HDCP
 	tristate "Intel HDCP2.2 services of ME Interface"
 	select INTEL_MEI_ME
 	depends on DRM_I915
+	default y
 	help
 	  MEI Support for HDCP2.2 Services on Intel SoCs.
-- 
2.7.4

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply related	[flat|nested] 103+ messages in thread

* [PATCH v9 39/39] FOR_TESTING_ONLY: debugfs: Excluding the LSPCon for HDCP1.4
  2018-12-13  4:01 [PATCH v9 00/39] drm/i915: Implement HDCP2.2 Ramalingam C
                   ` (37 preceding siblings ...)
  2018-12-13  4:01 ` [PATCH v9 38/39] FOR_TEST: i915/Kconfig: Select mei_hdcp by I915 Ramalingam C
@ 2018-12-13  4:01 ` Ramalingam C
  2018-12-13  4:17 ` ✗ Fi.CI.CHECKPATCH: warning for drm/i915: Implement HDCP2.2 (rev11) Patchwork
                   ` (3 subsequent siblings)
  42 siblings, 0 replies; 103+ messages in thread
From: Ramalingam C @ 2018-12-13  4:01 UTC (permalink / raw)
  To: intel-gfx, dri-devel, seanpaul, daniel.vetter, tomas.winkler,
	uma.shankar

Just excluding the LSPCon HDMI ports from the HDCP1.4 testing.

Signed-off-by: Ramalingam C <ramalingam.c@intel.com>
---
 drivers/gpu/drm/i915/i915_debugfs.c | 10 ++++++++--
 1 file changed, 8 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c
index 40a61ef9aac1..c4badca83523 100644
--- a/drivers/gpu/drm/i915/i915_debugfs.c
+++ b/drivers/gpu/drm/i915/i915_debugfs.c
@@ -5076,6 +5076,9 @@ static int i915_hdcp_sink_capability_show(struct seq_file *m, void *data)
 {
 	struct drm_connector *connector = m->private;
 	struct intel_connector *intel_connector = to_intel_connector(connector);
+	struct intel_digital_port *intel_dig_port =
+					conn_to_dig_port(intel_connector);
+	bool is_hdcp14;
 
 	if (connector->status != connector_status_connected)
 		return -ENODEV;
@@ -5086,8 +5089,11 @@ static int i915_hdcp_sink_capability_show(struct seq_file *m, void *data)
 
 	seq_printf(m, "%s:%d HDCP version: ", connector->name,
 		   connector->base.id);
-	seq_printf(m, "%s ", !intel_hdcp_capable(intel_connector) ?
-		   "None" : "HDCP1.4");
+
+	/* Excluding the Lspcon for Testing Purpose */
+	is_hdcp14 = intel_hdcp_capable(intel_connector) &&
+		    !intel_dig_port->lspcon.active;
+	seq_printf(m, "%s ", !is_hdcp14 ? "None" : "HDCP1.4");
 	seq_puts(m, "\n");
 
 	return 0;
-- 
2.7.4

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply related	[flat|nested] 103+ messages in thread

* ✗ Fi.CI.CHECKPATCH: warning for drm/i915: Implement HDCP2.2 (rev11)
  2018-12-13  4:01 [PATCH v9 00/39] drm/i915: Implement HDCP2.2 Ramalingam C
                   ` (38 preceding siblings ...)
  2018-12-13  4:01 ` [PATCH v9 39/39] FOR_TESTING_ONLY: debugfs: Excluding the LSPCon for HDCP1.4 Ramalingam C
@ 2018-12-13  4:17 ` Patchwork
  2018-12-13  4:27 ` ✗ Fi.CI.SPARSE: " Patchwork
                   ` (2 subsequent siblings)
  42 siblings, 0 replies; 103+ messages in thread
From: Patchwork @ 2018-12-13  4:17 UTC (permalink / raw)
  To: Ramalingam C; +Cc: intel-gfx

== Series Details ==

Series: drm/i915: Implement HDCP2.2 (rev11)
URL   : https://patchwork.freedesktop.org/series/38254/
State : warning

== Summary ==

$ dim checkpatch origin/drm-tip
bcb5b8686be3 drm/i915: Gathering the HDCP1.4 routines together
83df45d26858 drm: header for i915 - MEI_HDCP interface
-:11: WARNING:FILE_PATH_CHANGES: added, moved or deleted file(s), does MAINTAINERS need updating?
#11: 
new file mode 100644

total: 0 errors, 1 warnings, 0 checks, 132 lines checked
1272436b06c3 drivers/base: use a worker for sysfs unbind
c05bd8653488 component: alloc component_match without any comp to match
-:55: CHECK:PARENTHESIS_ALIGNMENT: Alignment should match open parenthesis
#55: FILE: drivers/base/component.c:321:
+void component_match_alloc(struct device *master,
+	struct component_match **matchptr)

-:90: CHECK:PARENTHESIS_ALIGNMENT: Alignment should match open parenthesis
#90: FILE: include/linux/component.h:41:
+void component_match_alloc(struct device *master,
+	struct component_match **matchptr);

total: 0 errors, 0 warnings, 2 checks, 44 lines checked
6fbcfc114e39 drm/i915: component master at i915 driver load
eecc07b8b347 drm/i915: Initialize HDCP2.2
8d8dd5f6d217 drm/i915: MEI interface definition
00cbaafe144c drm/i915: hdcp1.4 CP_IRQ handling and SW encryption tracking
7833fd7eaa30 drm/i915: Enable and Disable of HDCP2.2
9a394f2f3023 drm/i915: Implement HDCP2.2 receiver authentication
7d465cbe49b6 drm: helper functions for hdcp2 seq_num to from u32
7dc263a0b470 drm/i915: Implement HDCP2.2 repeater authentication
8fc1d866777d drm: HDCP2.2 link check related constants
c6f7ed8e14fc drm/i915: Implement HDCP2.2 link integrity check
aa7080cb29b8 drm/i915: Handle HDCP2.2 downstream topology change
d2c86d09a537 drm/i915: Implement the HDCP2.2 support for DP
329c1c9d0839 drm/i915: Implement the HDCP2.2 support for HDMI
e8441d06100d drm/i915: Add HDCP2.2 support for DP connectors
b9400ddf1f7d drm/i915: Add HDCP2.2 support for HDMI connectors
ec823f25607a mei: bus: whitelist hdcp client
224dc5b5cfae mei: bus: export to_mei_cl_device for mei client device drivers
4d17a22f645e misc/mei/hdcp: Client driver for HDCP application
-:73: WARNING:FILE_PATH_CHANGES: added, moved or deleted file(s), does MAINTAINERS need updating?
#73: 
new file mode 100644

-:91: WARNING:SPDX_LICENSE_TAG: Missing or malformed SPDX-License-Identifier tag in line 1
#91: FILE: drivers/misc/mei/hdcp/mei_hdcp.c:1:
+/* SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) */

total: 0 errors, 2 warnings, 0 checks, 87 lines checked
49daba8864d1 misc/mei/hdcp: Define ME FW interface for HDCP2.2
-:29: WARNING:FILE_PATH_CHANGES: added, moved or deleted file(s), does MAINTAINERS need updating?
#29: 
new file mode 100644

total: 0 errors, 1 warnings, 0 checks, 366 lines checked
c5d2659b3177 misc/mei/hdcp: Initiate Wired HDCP2.2 Tx Session
e635874a9ca8 misc/mei/hdcp: Verify Receiver Cert and prepare km
59ba26d4c7ca misc/mei/hdcp: Verify H_prime
121a0dbfc2ea misc/mei/hdcp: Store the HDCP Pairing info
b682919888ee misc/mei/hdcp: Initiate Locality check
43c1b2aeb67b misc/mei/hdcp: Verify L_prime
f1766ded1c0a misc/mei/hdcp: Prepare Session Key
e127a9d212cd misc/mei/hdcp: Repeater topology verification and ack
40ecac1cfc2d misc/mei/hdcp: Verify M_prime
5f7c7797c62f misc/mei/hdcp: Enabling the HDCP authentication
e470b2c2b13f misc/mei/hdcp: Closing wired HDCP2.2 Tx Session
7b32fd10999d misc/mei/hdcp: Component framework for I915 Interface
aee57816a8a6 drm/i915: Commit CP without modeset
446a760cbe18 drm/i915: Fix KBL HDCP2.2 encrypt status signalling
ef3c22a3dcc1 FOR_TEST: i915/Kconfig: Select mei_hdcp by I915
0fe879c951f8 FOR_TESTING_ONLY: debugfs: Excluding the LSPCon for HDCP1.4

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 103+ messages in thread

* ✗ Fi.CI.SPARSE: warning for drm/i915: Implement HDCP2.2 (rev11)
  2018-12-13  4:01 [PATCH v9 00/39] drm/i915: Implement HDCP2.2 Ramalingam C
                   ` (39 preceding siblings ...)
  2018-12-13  4:17 ` ✗ Fi.CI.CHECKPATCH: warning for drm/i915: Implement HDCP2.2 (rev11) Patchwork
@ 2018-12-13  4:27 ` Patchwork
  2018-12-13  4:44 ` ✗ Fi.CI.BAT: failure " Patchwork
  2018-12-20 16:58 ` ✗ Fi.CI.BAT: failure for drm/i915: Implement HDCP2.2 (rev12) Patchwork
  42 siblings, 0 replies; 103+ messages in thread
From: Patchwork @ 2018-12-13  4:27 UTC (permalink / raw)
  To: Ramalingam C; +Cc: intel-gfx

== Series Details ==

Series: drm/i915: Implement HDCP2.2 (rev11)
URL   : https://patchwork.freedesktop.org/series/38254/
State : warning

== Summary ==

$ dim sparse origin/drm-tip
Sparse version: v0.5.2
Commit: drm/i915: Gathering the HDCP1.4 routines together
Okay!

Commit: drm: header for i915 - MEI_HDCP interface
Okay!

Commit: drivers/base: use a worker for sysfs unbind
Okay!

Commit: component: alloc component_match without any comp to match
Okay!

Commit: drm/i915: component master at i915 driver load
-drivers/gpu/drm/i915/selftests/../i915_drv.h:3548:16: warning: expression using sizeof(void)
+drivers/gpu/drm/i915/selftests/../i915_drv.h:3551:16: warning: expression using sizeof(void)
+./include/linux/slab.h:332:43: warning: dubious: x & !y

Commit: drm/i915: Initialize HDCP2.2
Okay!

Commit: drm/i915: MEI interface definition
+./include/linux/slab.h:665:13: error: not a function <noident>

Commit: drm/i915: hdcp1.4 CP_IRQ handling and SW encryption tracking
+drivers/gpu/drm/i915/intel_hdcp.c:750:5: warning: symbol 'intel_hdcp_check_link' was not declared. Should it be static?

Commit: drm/i915: Enable and Disable of HDCP2.2
Okay!

Commit: drm/i915: Implement HDCP2.2 receiver authentication
Okay!

Commit: drm: helper functions for hdcp2 seq_num to from u32
Okay!

Commit: drm/i915: Implement HDCP2.2 repeater authentication
+drivers/gpu/drm/i915/intel_hdcp.c:1202:30: warning: incorrect type in assignment (different base types)

Commit: drm: HDCP2.2 link check related constants
Okay!

Commit: drm/i915: Implement HDCP2.2 link integrity check
Okay!

Commit: drm/i915: Handle HDCP2.2 downstream topology change
Okay!

Commit: drm/i915: Implement the HDCP2.2 support for DP
Okay!

Commit: drm/i915: Implement the HDCP2.2 support for HDMI
Okay!

Commit: drm/i915: Add HDCP2.2 support for DP connectors
Okay!

Commit: drm/i915: Add HDCP2.2 support for HDMI connectors
Okay!

Commit: mei: bus: whitelist hdcp client
Okay!

Commit: mei: bus: export to_mei_cl_device for mei client device drivers
Okay!

Commit: misc/mei/hdcp: Client driver for HDCP application
+Error in reading or end of file.

Commit: misc/mei/hdcp: Define ME FW interface for HDCP2.2
Okay!

Commit: misc/mei/hdcp: Initiate Wired HDCP2.2 Tx Session
Okay!

Commit: misc/mei/hdcp: Verify Receiver Cert and prepare km
Okay!

Commit: misc/mei/hdcp: Verify H_prime
Okay!

Commit: misc/mei/hdcp: Store the HDCP Pairing info
Okay!

Commit: misc/mei/hdcp: Initiate Locality check
Okay!

Commit: misc/mei/hdcp: Verify L_prime
Okay!

Commit: misc/mei/hdcp: Prepare Session Key
Okay!

Commit: misc/mei/hdcp: Repeater topology verification and ack
Okay!

Commit: misc/mei/hdcp: Verify M_prime
Okay!

Commit: misc/mei/hdcp: Enabling the HDCP authentication
Okay!

Commit: misc/mei/hdcp: Closing wired HDCP2.2 Tx Session
Okay!

Commit: misc/mei/hdcp: Component framework for I915 Interface
Okay!

Commit: drm/i915: Commit CP without modeset
Okay!

Commit: drm/i915: Fix KBL HDCP2.2 encrypt status signalling
Okay!

Commit: FOR_TEST: i915/Kconfig: Select mei_hdcp by I915
Okay!

Commit: FOR_TESTING_ONLY: debugfs: Excluding the LSPCon for HDCP1.4
Okay!

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 103+ messages in thread

* ✗ Fi.CI.BAT: failure for drm/i915: Implement HDCP2.2 (rev11)
  2018-12-13  4:01 [PATCH v9 00/39] drm/i915: Implement HDCP2.2 Ramalingam C
                   ` (40 preceding siblings ...)
  2018-12-13  4:27 ` ✗ Fi.CI.SPARSE: " Patchwork
@ 2018-12-13  4:44 ` Patchwork
  2018-12-20 16:58 ` ✗ Fi.CI.BAT: failure for drm/i915: Implement HDCP2.2 (rev12) Patchwork
  42 siblings, 0 replies; 103+ messages in thread
From: Patchwork @ 2018-12-13  4:44 UTC (permalink / raw)
  To: Ramalingam C; +Cc: intel-gfx

== Series Details ==

Series: drm/i915: Implement HDCP2.2 (rev11)
URL   : https://patchwork.freedesktop.org/series/38254/
State : failure

== Summary ==

CI Bug Log - changes from CI_DRM_5310 -> Patchwork_11081
====================================================

Summary
-------

  **FAILURE**

  Serious unknown changes coming with Patchwork_11081 absolutely need to be
  verified manually.
  
  If you think the reported changes have nothing to do with the changes
  introduced in Patchwork_11081, please notify your bug team to allow them
  to document this new failure mode, which will reduce false positives in CI.

  External URL: https://patchwork.freedesktop.org/api/1.0/series/38254/revisions/11/mbox/

Possible new issues
-------------------

  Here are the unknown changes that may have been introduced in Patchwork_11081:

### IGT changes ###

#### Possible regressions ####

  * igt@amdgpu/amd_prime@amd-to-i915:
    - fi-kbl-8809g:       NOTRUN -> FAIL

  * igt@gem_exec_suspend@basic-s3:
    - fi-kbl-r:           PASS -> DMESG-WARN
    - fi-kbl-7567u:       PASS -> DMESG-WARN
    - fi-glk-j4005:       PASS -> DMESG-WARN
    - fi-glk-dsi:         PASS -> DMESG-WARN
    - fi-kbl-7500u:       PASS -> DMESG-FAIL
    - fi-kbl-guc:         PASS -> DMESG-WARN
    - fi-kbl-7560u:       PASS -> DMESG-WARN

  * igt@gem_mmap_gtt@basic-write:
    - fi-kbl-7500u:       PASS -> DMESG-WARN

  * igt@i915_hangman@error-state-basic:
    - fi-kbl-guc:         PASS -> INCOMPLETE

  * igt@i915_module_load@reload:
    - fi-kbl-x1275:       PASS -> DMESG-FAIL

  * {igt@runner@aborted}:
    - fi-glk-dsi:         NOTRUN -> FAIL
    - fi-kbl-7500u:       NOTRUN -> FAIL
    - fi-kbl-7560u:       NOTRUN -> FAIL
    - fi-glk-j4005:       NOTRUN -> FAIL
    - fi-kbl-7567u:       NOTRUN -> FAIL
    - fi-kbl-x1275:       NOTRUN -> FAIL
    - fi-kbl-r:           NOTRUN -> FAIL
    - fi-kbl-guc:         NOTRUN -> FAIL

  
#### Warnings ####

  * igt@gem_mmap_gtt@basic-small-bo:
    - fi-kbl-7500u:       PASS -> SKIP +21

  * igt@kms_chamelium@hdmi-hpd-fast:
    - fi-icl-u2:          PASS -> SKIP +171

  * igt@kms_flip@basic-flip-vs-modeset:
    - fi-kbl-x1275:       PASS -> SKIP +225

  
Known issues
------------

  Here are the changes found in Patchwork_11081 that come from known issues:

### IGT changes ###

#### Issues hit ####

  * igt@amdgpu/amd_basic@cs-compute:
    - fi-kbl-8809g:       NOTRUN -> FAIL [fdo#108094]

  * igt@gem_exec_suspend@basic-s3:
    - fi-blb-e6850:       PASS -> INCOMPLETE [fdo#107718]

  * igt@i915_module_load@reload:
    - fi-icl-u2:          NOTRUN -> DMESG-FAIL [fdo#107732]

  
#### Possible fixes ####

  * igt@amdgpu/amd_basic@userptr:
    - fi-kbl-8809g:       DMESG-WARN [fdo#108965] -> PASS

  * igt@i915_selftest@live_hangcheck:
    - fi-bwr-2160:        DMESG-FAIL [fdo#108735] -> PASS

  * igt@kms_busy@basic-flip-b:
    - fi-bdw-gvtdvm:      FAIL [fdo#103182] -> PASS

  * igt@kms_chamelium@common-hpd-after-suspend:
    - fi-icl-u2:          DMESG-FAIL [fdo#103375] / [fdo#107732] / [fdo#108070] / [fdo#108924] -> SKIP

  * igt@kms_pipe_crc_basic@nonblocking-crc-pipe-a-frame-sequence:
    - fi-byt-clapper:     FAIL [fdo#103191] / [fdo#107362] -> PASS

  
  {name}: This element is suppressed. This means it is ignored when computing
          the status of the difference (SUCCESS, WARNING, or FAILURE).

  [fdo#103182]: https://bugs.freedesktop.org/show_bug.cgi?id=103182
  [fdo#103191]: https://bugs.freedesktop.org/show_bug.cgi?id=103191
  [fdo#103375]: https://bugs.freedesktop.org/show_bug.cgi?id=103375
  [fdo#107362]: https://bugs.freedesktop.org/show_bug.cgi?id=107362
  [fdo#107718]: https://bugs.freedesktop.org/show_bug.cgi?id=107718
  [fdo#107732]: https://bugs.freedesktop.org/show_bug.cgi?id=107732
  [fdo#108070]: https://bugs.freedesktop.org/show_bug.cgi?id=108070
  [fdo#108094]: https://bugs.freedesktop.org/show_bug.cgi?id=108094
  [fdo#108735]: https://bugs.freedesktop.org/show_bug.cgi?id=108735
  [fdo#108924]: https://bugs.freedesktop.org/show_bug.cgi?id=108924
  [fdo#108965]: https://bugs.freedesktop.org/show_bug.cgi?id=108965


Participating hosts (47 -> 43)
------------------------------

  Missing    (4): fi-kbl-soraka fi-ctg-p8600 fi-ilk-m540 fi-hsw-4200u 


Build changes
-------------

    * Linux: CI_DRM_5310 -> Patchwork_11081

  CI_DRM_5310: 1f86f1fb70f082ed93450c328e518d8013d23953 @ git://anongit.freedesktop.org/gfx-ci/linux
  IGT_4746: 2c793666d8c8328733f5769b16ae5858fee97f3f @ git://anongit.freedesktop.org/xorg/app/intel-gpu-tools
  Patchwork_11081: 0fe879c951f81adcc08648928535f1f8af2fad1b @ git://anongit.freedesktop.org/gfx-ci/linux


== Linux commits ==

0fe879c951f8 FOR_TESTING_ONLY: debugfs: Excluding the LSPCon for HDCP1.4
ef3c22a3dcc1 FOR_TEST: i915/Kconfig: Select mei_hdcp by I915
446a760cbe18 drm/i915: Fix KBL HDCP2.2 encrypt status signalling
aee57816a8a6 drm/i915: Commit CP without modeset
7b32fd10999d misc/mei/hdcp: Component framework for I915 Interface
e470b2c2b13f misc/mei/hdcp: Closing wired HDCP2.2 Tx Session
5f7c7797c62f misc/mei/hdcp: Enabling the HDCP authentication
40ecac1cfc2d misc/mei/hdcp: Verify M_prime
e127a9d212cd misc/mei/hdcp: Repeater topology verification and ack
f1766ded1c0a misc/mei/hdcp: Prepare Session Key
43c1b2aeb67b misc/mei/hdcp: Verify L_prime
b682919888ee misc/mei/hdcp: Initiate Locality check
121a0dbfc2ea misc/mei/hdcp: Store the HDCP Pairing info
59ba26d4c7ca misc/mei/hdcp: Verify H_prime
e635874a9ca8 misc/mei/hdcp: Verify Receiver Cert and prepare km
c5d2659b3177 misc/mei/hdcp: Initiate Wired HDCP2.2 Tx Session
49daba8864d1 misc/mei/hdcp: Define ME FW interface for HDCP2.2
4d17a22f645e misc/mei/hdcp: Client driver for HDCP application
224dc5b5cfae mei: bus: export to_mei_cl_device for mei client device drivers
ec823f25607a mei: bus: whitelist hdcp client
b9400ddf1f7d drm/i915: Add HDCP2.2 support for HDMI connectors
e8441d06100d drm/i915: Add HDCP2.2 support for DP connectors
329c1c9d0839 drm/i915: Implement the HDCP2.2 support for HDMI
d2c86d09a537 drm/i915: Implement the HDCP2.2 support for DP
aa7080cb29b8 drm/i915: Handle HDCP2.2 downstream topology change
c6f7ed8e14fc drm/i915: Implement HDCP2.2 link integrity check
8fc1d866777d drm: HDCP2.2 link check related constants
7dc263a0b470 drm/i915: Implement HDCP2.2 repeater authentication
7d465cbe49b6 drm: helper functions for hdcp2 seq_num to from u32
9a394f2f3023 drm/i915: Implement HDCP2.2 receiver authentication
7833fd7eaa30 drm/i915: Enable and Disable of HDCP2.2
00cbaafe144c drm/i915: hdcp1.4 CP_IRQ handling and SW encryption tracking
8d8dd5f6d217 drm/i915: MEI interface definition
eecc07b8b347 drm/i915: Initialize HDCP2.2
6fbcfc114e39 drm/i915: component master at i915 driver load
c05bd8653488 component: alloc component_match without any comp to match
1272436b06c3 drivers/base: use a worker for sysfs unbind
83df45d26858 drm: header for i915 - MEI_HDCP interface
bcb5b8686be3 drm/i915: Gathering the HDCP1.4 routines together

== Logs ==

For more details see: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_11081/
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 103+ messages in thread

* RE: [PATCH v9 01/39] drm/i915: Gathering the HDCP1.4 routines together
  2018-12-13  4:01 ` [PATCH v9 01/39] drm/i915: Gathering the HDCP1.4 routines together Ramalingam C
@ 2018-12-13  8:17   ` Winkler, Tomas
  2018-12-13 11:21     ` C, Ramalingam
  2018-12-19 13:35   ` Daniel Vetter
  1 sibling, 1 reply; 103+ messages in thread
From: Winkler, Tomas @ 2018-12-13  8:17 UTC (permalink / raw)
  To: C, Ramalingam, intel-gfx, dri-devel, seanpaul, daniel.vetter,
	Shankar, Uma



> 
> All HDCP1.4 routines are gathered together, followed by the generic functions
> those can be extended for HDCP2.2 too.
> 
> Signed-off-by: Ramalingam C <ramalingam.c@intel.com>
> ---
>  drivers/gpu/drm/i915/intel_hdcp.c | 118 +++++++++++++++++++------------------
> -
>  1 file changed, 59 insertions(+), 59 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/intel_hdcp.c
> b/drivers/gpu/drm/i915/intel_hdcp.c
> index e000e54ad569..506b4cc6f46b 100644
> --- a/drivers/gpu/drm/i915/intel_hdcp.c
> +++ b/drivers/gpu/drm/i915/intel_hdcp.c
> @@ -731,6 +731,65 @@ struct intel_connector
> *intel_hdcp_to_connector(struct intel_hdcp *hdcp)
>  	return container_of(hdcp, struct intel_connector, hdcp);  }
> 
> +/* Implements Part 3 of the HDCP authorization procedure */ int
> +intel_hdcp_check_link(struct intel_connector *connector) {


Should be static

> +	struct intel_hdcp *hdcp = &connector->hdcp;
> +	struct drm_i915_private *dev_priv = connector->base.dev-
> >dev_private;
> +	struct intel_digital_port *intel_dig_port =
> conn_to_dig_port(connector);
> +	enum port port = intel_dig_port->base.port;
> +	int ret = 0;
> +
> +	if (!hdcp->shim)
> +		return -ENOENT;
> +
> +	mutex_lock(&hdcp->mutex);
> +
> +	if (hdcp->value == DRM_MODE_CONTENT_PROTECTION_UNDESIRED)
> +		goto out;
> +
> +	if (!(I915_READ(PORT_HDCP_STATUS(port)) & HDCP_STATUS_ENC)) {
> +		DRM_ERROR("%s:%d HDCP check failed: link is not
> encrypted,%x\n",
> +			  connector->base.name, connector->base.base.id,
> +			  I915_READ(PORT_HDCP_STATUS(port)));
> +		ret = -ENXIO;
> +		hdcp->value = DRM_MODE_CONTENT_PROTECTION_DESIRED;
> +		schedule_work(&hdcp->prop_work);
> +		goto out;
> +	}
> +
> +	if (hdcp->shim->check_link(intel_dig_port)) {
> +		if (hdcp->value !=
> DRM_MODE_CONTENT_PROTECTION_UNDESIRED) {
> +			hdcp->value =
> DRM_MODE_CONTENT_PROTECTION_ENABLED;
> +			schedule_work(&hdcp->prop_work);
> +		}
> +		goto out;
> +	}
> +
> +	DRM_DEBUG_KMS("[%s:%d] HDCP link failed, retrying
> authentication\n",
> +		      connector->base.name, connector->base.base.id);
> +
> +	ret = _intel_hdcp_disable(connector);
> +	if (ret) {
> +		DRM_ERROR("Failed to disable hdcp (%d)\n", ret);
> +		hdcp->value = DRM_MODE_CONTENT_PROTECTION_DESIRED;
> +		schedule_work(&hdcp->prop_work);
> +		goto out;
> +	}
> +
> +	ret = _intel_hdcp_enable(connector);
> +	if (ret) {
> +		DRM_ERROR("Failed to enable hdcp (%d)\n", ret);
> +		hdcp->value = DRM_MODE_CONTENT_PROTECTION_DESIRED;
> +		schedule_work(&hdcp->prop_work);
> +		goto out;
> +	}
> +
> +out:
> +	mutex_unlock(&hdcp->mutex);
> +	return ret;
> +}
> +
>  static void intel_hdcp_check_work(struct work_struct *work)  {
>  	struct intel_hdcp *hdcp = container_of(to_delayed_work(work),
> @@ -867,62 +926,3 @@ void intel_hdcp_atomic_check(struct drm_connector
> *connector,
>  						   new_state->crtc);
>  	crtc_state->mode_changed = true;
>  }
> -
> -/* Implements Part 3 of the HDCP authorization procedure */ -int
> intel_hdcp_check_link(struct intel_connector *connector) -{
> -	struct intel_hdcp *hdcp = &connector->hdcp;
> -	struct drm_i915_private *dev_priv = connector->base.dev-
> >dev_private;
> -	struct intel_digital_port *intel_dig_port =
> conn_to_dig_port(connector);
> -	enum port port = intel_dig_port->base.port;
> -	int ret = 0;
> -
> -	if (!hdcp->shim)
> -		return -ENOENT;
> -
> -	mutex_lock(&hdcp->mutex);
> -
> -	if (hdcp->value == DRM_MODE_CONTENT_PROTECTION_UNDESIRED)
> -		goto out;
> -
> -	if (!(I915_READ(PORT_HDCP_STATUS(port)) & HDCP_STATUS_ENC)) {
> -		DRM_ERROR("%s:%d HDCP check failed: link is not
> encrypted,%x\n",
> -			  connector->base.name, connector->base.base.id,
> -			  I915_READ(PORT_HDCP_STATUS(port)));
> -		ret = -ENXIO;
> -		hdcp->value = DRM_MODE_CONTENT_PROTECTION_DESIRED;
> -		schedule_work(&hdcp->prop_work);
> -		goto out;
> -	}
> -
> -	if (hdcp->shim->check_link(intel_dig_port)) {
> -		if (hdcp->value !=
> DRM_MODE_CONTENT_PROTECTION_UNDESIRED) {
> -			hdcp->value =
> DRM_MODE_CONTENT_PROTECTION_ENABLED;
> -			schedule_work(&hdcp->prop_work);
> -		}
> -		goto out;
> -	}
> -
> -	DRM_DEBUG_KMS("[%s:%d] HDCP link failed, retrying
> authentication\n",
> -		      connector->base.name, connector->base.base.id);
> -
> -	ret = _intel_hdcp_disable(connector);
> -	if (ret) {
> -		DRM_ERROR("Failed to disable hdcp (%d)\n", ret);
> -		hdcp->value = DRM_MODE_CONTENT_PROTECTION_DESIRED;
> -		schedule_work(&hdcp->prop_work);
> -		goto out;
> -	}
> -
> -	ret = _intel_hdcp_enable(connector);
> -	if (ret) {
> -		DRM_DEBUG_KMS("Failed to enable hdcp (%d)\n", ret);
> -		hdcp->value = DRM_MODE_CONTENT_PROTECTION_DESIRED;
> -		schedule_work(&hdcp->prop_work);
> -		goto out;
> -	}
> -
> -out:
> -	mutex_unlock(&hdcp->mutex);
> -	return ret;
> -}
> --
> 2.7.4

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 103+ messages in thread

* Re: [PATCH v9 12/39] drm/i915: Implement HDCP2.2 repeater authentication
  2018-12-13  4:01 ` [PATCH v9 12/39] drm/i915: Implement HDCP2.2 repeater authentication Ramalingam C
@ 2018-12-13  8:22   ` Winkler, Tomas
  2018-12-13 11:18     ` C, Ramalingam
  2018-12-19 14:48   ` Daniel Vetter
  1 sibling, 1 reply; 103+ messages in thread
From: Winkler, Tomas @ 2018-12-13  8:22 UTC (permalink / raw)
  To: C, Ramalingam, intel-gfx, dri-devel, seanpaul, daniel.vetter,
	Shankar, Uma

> 
> Implements the HDCP2.2 repeaters authentication steps such as verifying the
> downstream topology and sending stream management information.
> 
> v2: Rebased.
> v3:
>   -EINVAL is returned for topology error and rollover scenario.
>   Endianness conversion func from drm_hdcp.h is used [Uma]
> v4:
>   Rebased as part of patches reordering.
>   Defined the mei service functions [Daniel]
> v5:
>   Redefined the mei service functions as per comp redesign.
> v6:
>   %s/uintxx_t/uxx
>   Check for comp_master is removed.
> v7:
>   Adjust to the new mei interface.
>   style issue fixed.
> v8:
>   drm_hdcp.h change is moved into separate patch [Daniel]
> 
> Signed-off-by: Ramalingam C <ramalingam.c@intel.com>
> ---
>  drivers/gpu/drm/i915/intel_hdcp.c | 123
> +++++++++++++++++++++++++++++++++++++-
>  1 file changed, 121 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/intel_hdcp.c
> b/drivers/gpu/drm/i915/intel_hdcp.c
> index f1f0ef294e20..b52da5c3159d 100644
> --- a/drivers/gpu/drm/i915/intel_hdcp.c
> +++ b/drivers/gpu/drm/i915/intel_hdcp.c
> @@ -978,7 +978,7 @@ static int hdcp2_prepare_skey(struct intel_connector
> *connector,
>  	return ret;
>  }
> 
> -static __attribute__((unused)) int
> +static int
>  hdcp2_verify_rep_topology_prepare_ack(struct intel_connector *connector,
>  				      struct hdcp2_rep_send_receiverid_list
> 
> 	*rep_topology,
> @@ -999,7 +999,7 @@ hdcp2_verify_rep_topology_prepare_ack(struct
> intel_connector *connector,
>  	return ret;
>  }
> 
> -static __attribute__((unused)) int
> +static int
>  hdcp2_verify_mprime(struct intel_connector *connector,
>  		    struct hdcp2_rep_stream_ready *stream_ready)  { @@ -
> 1182,6 +1182,119 @@ static int hdcp2_session_key_exchange(struct
> intel_connector *connector)
>  	return 0;
>  }
> 
> +static
> +int hdcp2_propagate_stream_management_info(struct intel_connector
> +*connector) {
> +	struct intel_digital_port *intel_dig_port =
> conn_to_dig_port(connector);
> +	struct intel_hdcp *hdcp = &connector->hdcp;
> +	union {
> +		struct hdcp2_rep_stream_manage stream_manage;
> +		struct hdcp2_rep_stream_ready stream_ready;
> +	} msgs;
> +	const struct intel_hdcp_shim *shim = hdcp->shim;
> +	int ret;
> +
> +	/* Prepare RepeaterAuth_Stream_Manage msg */
> +	msgs.stream_manage.msg_id = HDCP_2_2_REP_STREAM_MANAGE;
> +	drm_hdcp2_u32_to_seq_num(msgs.stream_manage.seq_num_m,
> +hdcp->seq_num_m);
> +
> +	/* K no of streams is fixed as 1. Stored as big-endian. */
> +	msgs.stream_manage.k = __swab16(1);

                                                       cpu_to_be16(1);

> +
> +	/* For HDMI this is forced to be 0x0. For DP SST also this is 0x0. */
> +	msgs.stream_manage.streams[0].stream_id = 0;
> +	msgs.stream_manage.streams[0].stream_type = hdcp->content_type;
> +
> +	/* Send it to Repeater */
> +	ret = shim->write_2_2_msg(intel_dig_port, &msgs.stream_manage,
> +				  sizeof(msgs.stream_manage));
> +	if (ret < 0)
> +		return ret;
> +
> +	ret = shim->read_2_2_msg(intel_dig_port,
> HDCP_2_2_REP_STREAM_READY,
> +				 &msgs.stream_ready,
> sizeof(msgs.stream_ready));
> +	if (ret < 0)
> +		return ret;
> +
> +	hdcp->port_data.seq_num_m = hdcp->seq_num_m;
> +	hdcp->port_data.streams[0].stream_type = hdcp->content_type;
> +
> +	ret = hdcp2_verify_mprime(connector, &msgs.stream_ready);
> +	if (ret < 0)
> +		return ret;
> +
> +	hdcp->seq_num_m++;
> +
> +	if (hdcp->seq_num_m > HDCP_2_2_SEQ_NUM_MAX) {
> +		DRM_DEBUG_KMS("seq_num_m roll over.\n");
> +		return -1;
> +	}
> +
> +	return 0;
> +}
> +
> +static
> +int hdcp2_authenticate_repeater_topology(struct intel_connector
> +*connector) {
> +	struct intel_digital_port *intel_dig_port =
> conn_to_dig_port(connector);
> +	struct intel_hdcp *hdcp = &connector->hdcp;
> +	union {
> +		struct hdcp2_rep_send_receiverid_list recvid_list;
> +		struct hdcp2_rep_send_ack rep_ack;
> +	} msgs;
> +	const struct intel_hdcp_shim *shim = hdcp->shim;
> +	u8 *rx_info;
> +	u32 seq_num_v;
> +	int ret;
> +
> +	ret = shim->read_2_2_msg(intel_dig_port,
> HDCP_2_2_REP_SEND_RECVID_LIST,
> +				 &msgs.recvid_list, sizeof(msgs.recvid_list));
> +	if (ret < 0)
> +		return ret;
> +
> +	rx_info = msgs.recvid_list.rx_info;
> +
> +	if (HDCP_2_2_MAX_CASCADE_EXCEEDED(rx_info[1]) ||
> +	    HDCP_2_2_MAX_DEVS_EXCEEDED(rx_info[1])) {
> +		DRM_DEBUG_KMS("Topology Max Size Exceeded\n");
> +		return -EINVAL;
> +	}
> +
> +	/* Converting and Storing the seq_num_v to local variable as DWORD
> */
> +	drm_hdcp2_seq_num_to_u32(&seq_num_v,
> msgs.recvid_list.seq_num_v);
> +
> +	if (seq_num_v < hdcp->seq_num_v) {
> +		/* Roll over of the seq_num_v from repeater. Reauthenticate.
> */
> +		DRM_DEBUG_KMS("Seq_num_v roll over.\n");
> +		return -EINVAL;
> +	}
> +
> +	ret = hdcp2_verify_rep_topology_prepare_ack(connector,
> +						    &msgs.recvid_list,
> +						    &msgs.rep_ack);
> +	if (ret < 0)
> +		return ret;
> +
> +	hdcp->seq_num_v = seq_num_v;
> +	ret = shim->write_2_2_msg(intel_dig_port, &msgs.rep_ack,
> +				  sizeof(msgs.rep_ack));
> +	if (ret < 0)
> +		return ret;
> +
> +	return 0;
> +}
> +
> +static int hdcp2_authenticate_repeater(struct intel_connector
> +*connector) {
> +	int ret;
> +
> +	ret = hdcp2_authenticate_repeater_topology(connector);
> +	if (ret < 0)
> +		return ret;
> +
> +	return hdcp2_propagate_stream_management_info(connector);
> +}
> +
>  static int hdcp2_authenticate_sink(struct intel_connector *connector)  {
>  	struct intel_digital_port *intel_dig_port =
> conn_to_dig_port(connector); @@ -1223,6 +1336,12 @@ static int
> hdcp2_authenticate_sink(struct intel_connector *connector)
>  					       sizeof(stream_type_msg));
>  		if (ret < 0)
>  			return ret;
> +	} else if (hdcp->is_repeater) {
> +		ret = hdcp2_authenticate_repeater(connector);
> +		if (ret < 0) {
> +			DRM_DEBUG_KMS("Repeater Auth Failed. Err: %d\n",
> ret);
> +			return ret;
> +		}
>  	}
> 
>  	hdcp->port_data.streams[0].stream_type = hdcp->content_type;
> --
> 2.7.4

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 103+ messages in thread

* Re: [PATCH v9 12/39] drm/i915: Implement HDCP2.2 repeater authentication
  2018-12-13  8:22   ` Winkler, Tomas
@ 2018-12-13 11:18     ` C, Ramalingam
  0 siblings, 0 replies; 103+ messages in thread
From: C, Ramalingam @ 2018-12-13 11:18 UTC (permalink / raw)
  To: Winkler, Tomas, intel-gfx, dri-devel, seanpaul, daniel.vetter,
	Shankar, Uma


[-- Attachment #1.1: Type: text/plain, Size: 6304 bytes --]


On 12/13/2018 1:52 PM, Winkler, Tomas wrote:
>> Implements the HDCP2.2 repeaters authentication steps such as verifying the
>> downstream topology and sending stream management information.
>>
>> v2: Rebased.
>> v3:
>>    -EINVAL is returned for topology error and rollover scenario.
>>    Endianness conversion func from drm_hdcp.h is used [Uma]
>> v4:
>>    Rebased as part of patches reordering.
>>    Defined the mei service functions [Daniel]
>> v5:
>>    Redefined the mei service functions as per comp redesign.
>> v6:
>>    %s/uintxx_t/uxx
>>    Check for comp_master is removed.
>> v7:
>>    Adjust to the new mei interface.
>>    style issue fixed.
>> v8:
>>    drm_hdcp.h change is moved into separate patch [Daniel]
>>
>> Signed-off-by: Ramalingam C <ramalingam.c@intel.com>
>> ---
>>   drivers/gpu/drm/i915/intel_hdcp.c | 123
>> +++++++++++++++++++++++++++++++++++++-
>>   1 file changed, 121 insertions(+), 2 deletions(-)
>>
>> diff --git a/drivers/gpu/drm/i915/intel_hdcp.c
>> b/drivers/gpu/drm/i915/intel_hdcp.c
>> index f1f0ef294e20..b52da5c3159d 100644
>> --- a/drivers/gpu/drm/i915/intel_hdcp.c
>> +++ b/drivers/gpu/drm/i915/intel_hdcp.c
>> @@ -978,7 +978,7 @@ static int hdcp2_prepare_skey(struct intel_connector
>> *connector,
>>   	return ret;
>>   }
>>
>> -static __attribute__((unused)) int
>> +static int
>>   hdcp2_verify_rep_topology_prepare_ack(struct intel_connector *connector,
>>   				      struct hdcp2_rep_send_receiverid_list
>>
>> 	*rep_topology,
>> @@ -999,7 +999,7 @@ hdcp2_verify_rep_topology_prepare_ack(struct
>> intel_connector *connector,
>>   	return ret;
>>   }
>>
>> -static __attribute__((unused)) int
>> +static int
>>   hdcp2_verify_mprime(struct intel_connector *connector,
>>   		    struct hdcp2_rep_stream_ready *stream_ready)  { @@ -
>> 1182,6 +1182,119 @@ static int hdcp2_session_key_exchange(struct
>> intel_connector *connector)
>>   	return 0;
>>   }
>>
>> +static
>> +int hdcp2_propagate_stream_management_info(struct intel_connector
>> +*connector) {
>> +	struct intel_digital_port *intel_dig_port =
>> conn_to_dig_port(connector);
>> +	struct intel_hdcp *hdcp = &connector->hdcp;
>> +	union {
>> +		struct hdcp2_rep_stream_manage stream_manage;
>> +		struct hdcp2_rep_stream_ready stream_ready;
>> +	} msgs;
>> +	const struct intel_hdcp_shim *shim = hdcp->shim;
>> +	int ret;
>> +
>> +	/* Prepare RepeaterAuth_Stream_Manage msg */
>> +	msgs.stream_manage.msg_id = HDCP_2_2_REP_STREAM_MANAGE;
>> +	drm_hdcp2_u32_to_seq_num(msgs.stream_manage.seq_num_m,
>> +hdcp->seq_num_m);
>> +
>> +	/* K no of streams is fixed as 1. Stored as big-endian. */
>> +	msgs.stream_manage.k = __swab16(1);
>                                                         cpu_to_be16(1);

Sure. Tomas. That will suit better.
BTW, whether current mei- i915 interface suits to your preference?

Thanks
Ram

>> +
>> +	/* For HDMI this is forced to be 0x0. For DP SST also this is 0x0. */
>> +	msgs.stream_manage.streams[0].stream_id = 0;
>> +	msgs.stream_manage.streams[0].stream_type = hdcp->content_type;
>> +
>> +	/* Send it to Repeater */
>> +	ret = shim->write_2_2_msg(intel_dig_port, &msgs.stream_manage,
>> +				  sizeof(msgs.stream_manage));
>> +	if (ret < 0)
>> +		return ret;
>> +
>> +	ret = shim->read_2_2_msg(intel_dig_port,
>> HDCP_2_2_REP_STREAM_READY,
>> +				 &msgs.stream_ready,
>> sizeof(msgs.stream_ready));
>> +	if (ret < 0)
>> +		return ret;
>> +
>> +	hdcp->port_data.seq_num_m = hdcp->seq_num_m;
>> +	hdcp->port_data.streams[0].stream_type = hdcp->content_type;
>> +
>> +	ret = hdcp2_verify_mprime(connector, &msgs.stream_ready);
>> +	if (ret < 0)
>> +		return ret;
>> +
>> +	hdcp->seq_num_m++;
>> +
>> +	if (hdcp->seq_num_m > HDCP_2_2_SEQ_NUM_MAX) {
>> +		DRM_DEBUG_KMS("seq_num_m roll over.\n");
>> +		return -1;
>> +	}
>> +
>> +	return 0;
>> +}
>> +
>> +static
>> +int hdcp2_authenticate_repeater_topology(struct intel_connector
>> +*connector) {
>> +	struct intel_digital_port *intel_dig_port =
>> conn_to_dig_port(connector);
>> +	struct intel_hdcp *hdcp = &connector->hdcp;
>> +	union {
>> +		struct hdcp2_rep_send_receiverid_list recvid_list;
>> +		struct hdcp2_rep_send_ack rep_ack;
>> +	} msgs;
>> +	const struct intel_hdcp_shim *shim = hdcp->shim;
>> +	u8 *rx_info;
>> +	u32 seq_num_v;
>> +	int ret;
>> +
>> +	ret = shim->read_2_2_msg(intel_dig_port,
>> HDCP_2_2_REP_SEND_RECVID_LIST,
>> +				 &msgs.recvid_list, sizeof(msgs.recvid_list));
>> +	if (ret < 0)
>> +		return ret;
>> +
>> +	rx_info = msgs.recvid_list.rx_info;
>> +
>> +	if (HDCP_2_2_MAX_CASCADE_EXCEEDED(rx_info[1]) ||
>> +	    HDCP_2_2_MAX_DEVS_EXCEEDED(rx_info[1])) {
>> +		DRM_DEBUG_KMS("Topology Max Size Exceeded\n");
>> +		return -EINVAL;
>> +	}
>> +
>> +	/* Converting and Storing the seq_num_v to local variable as DWORD
>> */
>> +	drm_hdcp2_seq_num_to_u32(&seq_num_v,
>> msgs.recvid_list.seq_num_v);
>> +
>> +	if (seq_num_v < hdcp->seq_num_v) {
>> +		/* Roll over of the seq_num_v from repeater. Reauthenticate.
>> */
>> +		DRM_DEBUG_KMS("Seq_num_v roll over.\n");
>> +		return -EINVAL;
>> +	}
>> +
>> +	ret = hdcp2_verify_rep_topology_prepare_ack(connector,
>> +						    &msgs.recvid_list,
>> +						    &msgs.rep_ack);
>> +	if (ret < 0)
>> +		return ret;
>> +
>> +	hdcp->seq_num_v = seq_num_v;
>> +	ret = shim->write_2_2_msg(intel_dig_port, &msgs.rep_ack,
>> +				  sizeof(msgs.rep_ack));
>> +	if (ret < 0)
>> +		return ret;
>> +
>> +	return 0;
>> +}
>> +
>> +static int hdcp2_authenticate_repeater(struct intel_connector
>> +*connector) {
>> +	int ret;
>> +
>> +	ret = hdcp2_authenticate_repeater_topology(connector);
>> +	if (ret < 0)
>> +		return ret;
>> +
>> +	return hdcp2_propagate_stream_management_info(connector);
>> +}
>> +
>>   static int hdcp2_authenticate_sink(struct intel_connector *connector)  {
>>   	struct intel_digital_port *intel_dig_port =
>> conn_to_dig_port(connector); @@ -1223,6 +1336,12 @@ static int
>> hdcp2_authenticate_sink(struct intel_connector *connector)
>>   					       sizeof(stream_type_msg));
>>   		if (ret < 0)
>>   			return ret;
>> +	} else if (hdcp->is_repeater) {
>> +		ret = hdcp2_authenticate_repeater(connector);
>> +		if (ret < 0) {
>> +			DRM_DEBUG_KMS("Repeater Auth Failed. Err: %d\n",
>> ret);
>> +			return ret;
>> +		}
>>   	}
>>
>>   	hdcp->port_data.streams[0].stream_type = hdcp->content_type;
>> --
>> 2.7.4

[-- Attachment #1.2: Type: text/html, Size: 6719 bytes --]

[-- Attachment #2: Type: text/plain, Size: 160 bytes --]

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 103+ messages in thread

* Re: [PATCH v9 01/39] drm/i915: Gathering the HDCP1.4 routines together
  2018-12-13  8:17   ` Winkler, Tomas
@ 2018-12-13 11:21     ` C, Ramalingam
  0 siblings, 0 replies; 103+ messages in thread
From: C, Ramalingam @ 2018-12-13 11:21 UTC (permalink / raw)
  To: Winkler, Tomas, intel-gfx, dri-devel, seanpaul, daniel.vetter,
	Shankar, Uma


[-- Attachment #1.1: Type: text/plain, Size: 5082 bytes --]


On 12/13/2018 1:47 PM, Winkler, Tomas wrote:
>
>> All HDCP1.4 routines are gathered together, followed by the generic functions
>> those can be extended for HDCP2.2 too.
>>
>> Signed-off-by: Ramalingam C <ramalingam.c@intel.com>
>> ---
>>   drivers/gpu/drm/i915/intel_hdcp.c | 118 +++++++++++++++++++------------------
>> -
>>   1 file changed, 59 insertions(+), 59 deletions(-)
>>
>> diff --git a/drivers/gpu/drm/i915/intel_hdcp.c
>> b/drivers/gpu/drm/i915/intel_hdcp.c
>> index e000e54ad569..506b4cc6f46b 100644
>> --- a/drivers/gpu/drm/i915/intel_hdcp.c
>> +++ b/drivers/gpu/drm/i915/intel_hdcp.c
>> @@ -731,6 +731,65 @@ struct intel_connector
>> *intel_hdcp_to_connector(struct intel_hdcp *hdcp)
>>   	return container_of(hdcp, struct intel_connector, hdcp);  }
>>
>> +/* Implements Part 3 of the HDCP authorization procedure */ int
>> +intel_hdcp_check_link(struct intel_connector *connector) {
>
> Should be static

At this point in time, invoked from intel_dp.c. But at later part of
this series this function can be defined as static. Will do it then.

-Ram

>
>> +	struct intel_hdcp *hdcp = &connector->hdcp;
>> +	struct drm_i915_private *dev_priv = connector->base.dev-
>>> dev_private;
>> +	struct intel_digital_port *intel_dig_port =
>> conn_to_dig_port(connector);
>> +	enum port port = intel_dig_port->base.port;
>> +	int ret = 0;
>> +
>> +	if (!hdcp->shim)
>> +		return -ENOENT;
>> +
>> +	mutex_lock(&hdcp->mutex);
>> +
>> +	if (hdcp->value == DRM_MODE_CONTENT_PROTECTION_UNDESIRED)
>> +		goto out;
>> +
>> +	if (!(I915_READ(PORT_HDCP_STATUS(port)) & HDCP_STATUS_ENC)) {
>> +		DRM_ERROR("%s:%d HDCP check failed: link is not
>> encrypted,%x\n",
>> +			  connector->base.name, connector->base.base.id,
>> +			  I915_READ(PORT_HDCP_STATUS(port)));
>> +		ret = -ENXIO;
>> +		hdcp->value = DRM_MODE_CONTENT_PROTECTION_DESIRED;
>> +		schedule_work(&hdcp->prop_work);
>> +		goto out;
>> +	}
>> +
>> +	if (hdcp->shim->check_link(intel_dig_port)) {
>> +		if (hdcp->value !=
>> DRM_MODE_CONTENT_PROTECTION_UNDESIRED) {
>> +			hdcp->value =
>> DRM_MODE_CONTENT_PROTECTION_ENABLED;
>> +			schedule_work(&hdcp->prop_work);
>> +		}
>> +		goto out;
>> +	}
>> +
>> +	DRM_DEBUG_KMS("[%s:%d] HDCP link failed, retrying
>> authentication\n",
>> +		      connector->base.name, connector->base.base.id);
>> +
>> +	ret = _intel_hdcp_disable(connector);
>> +	if (ret) {
>> +		DRM_ERROR("Failed to disable hdcp (%d)\n", ret);
>> +		hdcp->value = DRM_MODE_CONTENT_PROTECTION_DESIRED;
>> +		schedule_work(&hdcp->prop_work);
>> +		goto out;
>> +	}
>> +
>> +	ret = _intel_hdcp_enable(connector);
>> +	if (ret) {
>> +		DRM_ERROR("Failed to enable hdcp (%d)\n", ret);
>> +		hdcp->value = DRM_MODE_CONTENT_PROTECTION_DESIRED;
>> +		schedule_work(&hdcp->prop_work);
>> +		goto out;
>> +	}
>> +
>> +out:
>> +	mutex_unlock(&hdcp->mutex);
>> +	return ret;
>> +}
>> +
>>   static void intel_hdcp_check_work(struct work_struct *work)  {
>>   	struct intel_hdcp *hdcp = container_of(to_delayed_work(work),
>> @@ -867,62 +926,3 @@ void intel_hdcp_atomic_check(struct drm_connector
>> *connector,
>>   						   new_state->crtc);
>>   	crtc_state->mode_changed = true;
>>   }
>> -
>> -/* Implements Part 3 of the HDCP authorization procedure */ -int
>> intel_hdcp_check_link(struct intel_connector *connector) -{
>> -	struct intel_hdcp *hdcp = &connector->hdcp;
>> -	struct drm_i915_private *dev_priv = connector->base.dev-
>>> dev_private;
>> -	struct intel_digital_port *intel_dig_port =
>> conn_to_dig_port(connector);
>> -	enum port port = intel_dig_port->base.port;
>> -	int ret = 0;
>> -
>> -	if (!hdcp->shim)
>> -		return -ENOENT;
>> -
>> -	mutex_lock(&hdcp->mutex);
>> -
>> -	if (hdcp->value == DRM_MODE_CONTENT_PROTECTION_UNDESIRED)
>> -		goto out;
>> -
>> -	if (!(I915_READ(PORT_HDCP_STATUS(port)) & HDCP_STATUS_ENC)) {
>> -		DRM_ERROR("%s:%d HDCP check failed: link is not
>> encrypted,%x\n",
>> -			  connector->base.name, connector->base.base.id,
>> -			  I915_READ(PORT_HDCP_STATUS(port)));
>> -		ret = -ENXIO;
>> -		hdcp->value = DRM_MODE_CONTENT_PROTECTION_DESIRED;
>> -		schedule_work(&hdcp->prop_work);
>> -		goto out;
>> -	}
>> -
>> -	if (hdcp->shim->check_link(intel_dig_port)) {
>> -		if (hdcp->value !=
>> DRM_MODE_CONTENT_PROTECTION_UNDESIRED) {
>> -			hdcp->value =
>> DRM_MODE_CONTENT_PROTECTION_ENABLED;
>> -			schedule_work(&hdcp->prop_work);
>> -		}
>> -		goto out;
>> -	}
>> -
>> -	DRM_DEBUG_KMS("[%s:%d] HDCP link failed, retrying
>> authentication\n",
>> -		      connector->base.name, connector->base.base.id);
>> -
>> -	ret = _intel_hdcp_disable(connector);
>> -	if (ret) {
>> -		DRM_ERROR("Failed to disable hdcp (%d)\n", ret);
>> -		hdcp->value = DRM_MODE_CONTENT_PROTECTION_DESIRED;
>> -		schedule_work(&hdcp->prop_work);
>> -		goto out;
>> -	}
>> -
>> -	ret = _intel_hdcp_enable(connector);
>> -	if (ret) {
>> -		DRM_DEBUG_KMS("Failed to enable hdcp (%d)\n", ret);
>> -		hdcp->value = DRM_MODE_CONTENT_PROTECTION_DESIRED;
>> -		schedule_work(&hdcp->prop_work);
>> -		goto out;
>> -	}
>> -
>> -out:
>> -	mutex_unlock(&hdcp->mutex);
>> -	return ret;
>> -}
>> --
>> 2.7.4

[-- Attachment #1.2: Type: text/html, Size: 6101 bytes --]

[-- Attachment #2: Type: text/plain, Size: 160 bytes --]

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 103+ messages in thread

* Re: [PATCH v9 35/39] misc/mei/hdcp: Component framework for I915 Interface
  2018-12-13  4:01 ` [PATCH v9 35/39] misc/mei/hdcp: Component framework for I915 Interface Ramalingam C
@ 2018-12-13 12:36   ` C, Ramalingam
  2018-12-13 16:11     ` Daniel Vetter
  0 siblings, 1 reply; 103+ messages in thread
From: C, Ramalingam @ 2018-12-13 12:36 UTC (permalink / raw)
  To: intel-gfx, dri-devel, Sean Paul, daniel.vetter, tomas.winkler,
	uma.shankar


[-- Attachment #1.1: Type: text/plain, Size: 5330 bytes --]

Tomas and Daniel,

We got an issue here.

The relationship that we try to build between I915 and mei_hdcp is as follows:

  * We are using the components to establish the relationship.
  * I915 is component master where as mei_hdcp is component.
  * I915 adds the component master during the module load. mei_hdcp adds
    the component when the driver->probe is called (on device driver
    binding).
  * I915 forces itself such that until mei_hdcp component is added
    I915_load wont be complete.
  * Similarly on complete system, if mei_hdcp component is removed,
    immediately I915 unregister itself and HW will be shutdown.

This is completely fine when the modules are loaded and unloaded.

But during suspend, mei device disappears and mei bus handles it by unbinding device and driver by calling driver->remove.
This in-turn removes the component and triggers the master unbind of I915 where, I915 unregister itself.
This cause the HW state mismatch during the suspend and resume.

Please check the powerwell mismatch errors at CI report for v9
https://intel-gfx-ci.01.org/tree/drm-tip/Trybot_3412/fi-glk-j4005/igt@gem_exec_suspend@basic-s3.html

More over unregistering I915 during the suspend is not expected. So how do we handle this?

-Ram

On 12/13/2018 9:31 AM, Ramalingam C wrote:
> Mei hdcp driver is designed as component slave for the I915 component
> master.
>
> v2: Rebased.
> v3:
>    Notifier chain is adopted for cldev state update [Tomas]
> v4:
>    Made static dummy functions as inline in mei_hdcp.h
>    API for polling client device status
>    IS_ENABLED used in header, for config status for mei_hdcp.
> v5:
>    Replacing the notifier with component framework. [Daniel]
> v6:
>    Rebased on the I915 comp master redesign.
> v7:
>    mei_hdcp_component_registered is made static [Uma]
>    Need for global static variable mei_cldev is removed.
>
> Signed-off-by: Ramalingam C <ramalingam.c@intel.com>
> Reviewed-by: Uma Shankar <uma.shankar@intel.com>
> ---
>   drivers/misc/mei/hdcp/mei_hdcp.c | 67 +++++++++++++++++++++++++++++++++++++---
>   1 file changed, 63 insertions(+), 4 deletions(-)
>
> diff --git a/drivers/misc/mei/hdcp/mei_hdcp.c b/drivers/misc/mei/hdcp/mei_hdcp.c
> index b22a71e8c5d7..3de1700dcc9f 100644
> --- a/drivers/misc/mei/hdcp/mei_hdcp.c
> +++ b/drivers/misc/mei/hdcp/mei_hdcp.c
> @@ -23,11 +23,14 @@
>   #include <linux/slab.h>
>   #include <linux/uuid.h>
>   #include <linux/mei_cl_bus.h>
> +#include <linux/component.h>
>   #include <drm/drm_connector.h>
>   #include <drm/i915_component.h>
>   
>   #include "mei_hdcp.h"
>   
> +static bool mei_hdcp_component_registered;
> +
>   /**
>    * mei_initiate_hdcp2_session() - Initiate a Wired HDCP2.2 Tx Session in ME FW
>    * @dev: device corresponding to the mei_cl_device
> @@ -691,8 +694,7 @@ mei_close_hdcp_session(struct device *dev, struct hdcp_port_data *data)
>   	return 0;
>   }
>   
> -static __attribute__((unused))
> -struct i915_hdcp_component_ops mei_hdcp_ops = {
> +static struct i915_hdcp_component_ops mei_hdcp_ops = {
>   	.owner = THIS_MODULE,
>   	.initiate_hdcp2_session = mei_initiate_hdcp2_session,
>   	.verify_receiver_cert_prepare_km = mei_verify_receiver_cert_prepare_km,
> @@ -707,20 +709,77 @@ struct i915_hdcp_component_ops mei_hdcp_ops = {
>   	.close_hdcp_session = mei_close_hdcp_session,
>   };
>   
> +static int mei_hdcp_component_bind(struct device *mei_kdev,
> +				   struct device *i915_kdev, void *data)
> +{
> +	struct i915_component_master *master_comp = data;
> +
> +	dev_info(mei_kdev, "MEI HDCP comp bind\n");
> +	WARN_ON(master_comp->hdcp_ops);
> +	master_comp->hdcp_ops = &mei_hdcp_ops;
> +	master_comp->mei_dev = mei_kdev;
> +
> +	return 0;
> +}
> +
> +static void mei_hdcp_component_unbind(struct device *mei_kdev,
> +				      struct device *i915_kdev, void *data)
> +{
> +	struct i915_component_master *master_comp = data;
> +
> +	dev_info(mei_kdev, "MEI HDCP comp unbind\n");
> +	master_comp->hdcp_ops = NULL;
> +	master_comp->mei_dev = NULL;
> +}
> +
> +static const struct component_ops mei_hdcp_component_bind_ops = {
> +	.bind	= mei_hdcp_component_bind,
> +	.unbind	= mei_hdcp_component_unbind,
> +};
> +
> +static void mei_hdcp_component_init(struct device *dev)
> +{
> +	int ret;
> +
> +	dev_info(dev, "MEI HDCP comp init\n");
> +	ret = component_add(dev, &mei_hdcp_component_bind_ops);
> +	if (ret < 0) {
> +		dev_err(dev, "Failed to add MEI HDCP comp (%d)\n", ret);
> +		return;
> +	}
> +
> +	mei_hdcp_component_registered = true;
> +}
> +
> +static void mei_hdcp_component_cleanup(struct device *dev)
> +{
> +	if (!mei_hdcp_component_registered)
> +		return;
> +
> +	dev_info(dev, "MEI HDCP comp cleanup\n");
> +	component_del(dev, &mei_hdcp_component_bind_ops);
> +	mei_hdcp_component_registered = false;
> +}
> +
>   static int mei_hdcp_probe(struct mei_cl_device *cldev,
>   			  const struct mei_cl_device_id *id)
>   {
>   	int ret;
>   
>   	ret = mei_cldev_enable(cldev);
> -	if (ret < 0)
> +	if (ret < 0) {
>   		dev_err(&cldev->dev, "mei_cldev_enable Failed. %d\n", ret);
> +		return ret;
> +	}
> +	mei_hdcp_component_init(&cldev->dev);
>   
> -	return ret;
> +	return 0;
>   }
>   
>   static int mei_hdcp_remove(struct mei_cl_device *cldev)
>   {
> +	mei_hdcp_component_cleanup(&cldev->dev);
> +
>   	return mei_cldev_disable(cldev);
>   }
>   

[-- Attachment #1.2: Type: text/html, Size: 5971 bytes --]

[-- Attachment #2: Type: text/plain, Size: 160 bytes --]

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 103+ messages in thread

* Re: [PATCH v9 35/39] misc/mei/hdcp: Component framework for I915 Interface
  2018-12-13 12:36   ` C, Ramalingam
@ 2018-12-13 16:11     ` Daniel Vetter
  2018-12-13 16:27       ` Winkler, Tomas
  0 siblings, 1 reply; 103+ messages in thread
From: Daniel Vetter @ 2018-12-13 16:11 UTC (permalink / raw)
  To: Ramalingam C, Greg KH, Rafael J. Wysocki
  Cc: intel-gfx, dri-devel, Uma Shankar, Sean Paul, Tomas Winkler

On Thu, Dec 13, 2018 at 1:36 PM C, Ramalingam <ramalingam.c@intel.com> wrote:
>
> Tomas and Daniel,
>
> We got an issue here.
>
> The relationship that we try to build between I915 and mei_hdcp is as follows:
>
> We are using the components to establish the relationship.
> I915 is component master where as mei_hdcp is component.
> I915 adds the component master during the module load. mei_hdcp adds the component when the driver->probe is called (on device driver binding).
> I915 forces itself such that until mei_hdcp component is added I915_load wont be complete.
> Similarly on complete system, if mei_hdcp component is removed, immediately I915 unregister itself and HW will be shutdown.
>
> This is completely fine when the modules are loaded and unloaded.
>
> But during suspend, mei device disappears and mei bus handles it by unbinding device and driver by calling driver->remove.
> This in-turn removes the component and triggers the master unbind of I915 where, I915 unregister itself.
> This cause the HW state mismatch during the suspend and resume.
>
> Please check the powerwell mismatch errors at CI report for v9
> https://intel-gfx-ci.01.org/tree/drm-tip/Trybot_3412/fi-glk-j4005/igt@gem_exec_suspend@basic-s3.html
>
> More over unregistering I915 during the suspend is not expected. So how do we handle this?

Bit more context from our irc discussion with Ram:

I found this very surprising, since I don't know of any other
subsystems where the devices get outright removed when going through a
suspend/resume cycle. The device model was built to handle this stuff
correctly: First clients/devices/interfaces get suspend, then the
parent/bridge/bus. Same dance in reverse when resuming. This even
holds for lots of hotpluggable buses, where child devices could indeed
disappear on resume, but as long as they don't, everything stays the
same. It's really surprising for something that's soldered onto the
board like ME.

Aside: We'll probably need a device_link to make sure mei_hdcp is
fully resumed before i915 gets resumed, but that's kinda a detail for
later on.

Tomas, can you pls explain why mei is designed like this? Or is there
something else we're missing (I didn't dig through the mei bus in
detail at all, so not clear on what exactly is going on there).

Also pulling in device model and suspend/resume experts.

Thanks, Daniel

>
> -Ram
>
> On 12/13/2018 9:31 AM, Ramalingam C wrote:
>
> Mei hdcp driver is designed as component slave for the I915 component
> master.
>
> v2: Rebased.
> v3:
>   Notifier chain is adopted for cldev state update [Tomas]
> v4:
>   Made static dummy functions as inline in mei_hdcp.h
>   API for polling client device status
>   IS_ENABLED used in header, for config status for mei_hdcp.
> v5:
>   Replacing the notifier with component framework. [Daniel]
> v6:
>   Rebased on the I915 comp master redesign.
> v7:
>   mei_hdcp_component_registered is made static [Uma]
>   Need for global static variable mei_cldev is removed.
>
> Signed-off-by: Ramalingam C <ramalingam.c@intel.com>
> Reviewed-by: Uma Shankar <uma.shankar@intel.com>
> ---
>  drivers/misc/mei/hdcp/mei_hdcp.c | 67 +++++++++++++++++++++++++++++++++++++---
>  1 file changed, 63 insertions(+), 4 deletions(-)
>
> diff --git a/drivers/misc/mei/hdcp/mei_hdcp.c b/drivers/misc/mei/hdcp/mei_hdcp.c
> index b22a71e8c5d7..3de1700dcc9f 100644
> --- a/drivers/misc/mei/hdcp/mei_hdcp.c
> +++ b/drivers/misc/mei/hdcp/mei_hdcp.c
> @@ -23,11 +23,14 @@
>  #include <linux/slab.h>
>  #include <linux/uuid.h>
>  #include <linux/mei_cl_bus.h>
> +#include <linux/component.h>
>  #include <drm/drm_connector.h>
>  #include <drm/i915_component.h>
>
>  #include "mei_hdcp.h"
>
> +static bool mei_hdcp_component_registered;
> +
>  /**
>   * mei_initiate_hdcp2_session() - Initiate a Wired HDCP2.2 Tx Session in ME FW
>   * @dev: device corresponding to the mei_cl_device
> @@ -691,8 +694,7 @@ mei_close_hdcp_session(struct device *dev, struct hdcp_port_data *data)
>   return 0;
>  }
>
> -static __attribute__((unused))
> -struct i915_hdcp_component_ops mei_hdcp_ops = {
> +static struct i915_hdcp_component_ops mei_hdcp_ops = {
>   .owner = THIS_MODULE,
>   .initiate_hdcp2_session = mei_initiate_hdcp2_session,
>   .verify_receiver_cert_prepare_km = mei_verify_receiver_cert_prepare_km,
> @@ -707,20 +709,77 @@ struct i915_hdcp_component_ops mei_hdcp_ops = {
>   .close_hdcp_session = mei_close_hdcp_session,
>  };
>
> +static int mei_hdcp_component_bind(struct device *mei_kdev,
> +   struct device *i915_kdev, void *data)
> +{
> + struct i915_component_master *master_comp = data;
> +
> + dev_info(mei_kdev, "MEI HDCP comp bind\n");
> + WARN_ON(master_comp->hdcp_ops);
> + master_comp->hdcp_ops = &mei_hdcp_ops;
> + master_comp->mei_dev = mei_kdev;
> +
> + return 0;
> +}
> +
> +static void mei_hdcp_component_unbind(struct device *mei_kdev,
> +      struct device *i915_kdev, void *data)
> +{
> + struct i915_component_master *master_comp = data;
> +
> + dev_info(mei_kdev, "MEI HDCP comp unbind\n");
> + master_comp->hdcp_ops = NULL;
> + master_comp->mei_dev = NULL;
> +}
> +
> +static const struct component_ops mei_hdcp_component_bind_ops = {
> + .bind = mei_hdcp_component_bind,
> + .unbind = mei_hdcp_component_unbind,
> +};
> +
> +static void mei_hdcp_component_init(struct device *dev)
> +{
> + int ret;
> +
> + dev_info(dev, "MEI HDCP comp init\n");
> + ret = component_add(dev, &mei_hdcp_component_bind_ops);
> + if (ret < 0) {
> + dev_err(dev, "Failed to add MEI HDCP comp (%d)\n", ret);
> + return;
> + }
> +
> + mei_hdcp_component_registered = true;
> +}
> +
> +static void mei_hdcp_component_cleanup(struct device *dev)
> +{
> + if (!mei_hdcp_component_registered)
> + return;
> +
> + dev_info(dev, "MEI HDCP comp cleanup\n");
> + component_del(dev, &mei_hdcp_component_bind_ops);
> + mei_hdcp_component_registered = false;
> +}
> +
>  static int mei_hdcp_probe(struct mei_cl_device *cldev,
>    const struct mei_cl_device_id *id)
>  {
>   int ret;
>
>   ret = mei_cldev_enable(cldev);
> - if (ret < 0)
> + if (ret < 0) {
>   dev_err(&cldev->dev, "mei_cldev_enable Failed. %d\n", ret);
> + return ret;
> + }
> + mei_hdcp_component_init(&cldev->dev);
>
> - return ret;
> + return 0;
>  }
>
>  static int mei_hdcp_remove(struct mei_cl_device *cldev)
>  {
> + mei_hdcp_component_cleanup(&cldev->dev);
> +
>   return mei_cldev_disable(cldev);
>  }
>



-- 
Daniel Vetter
Software Engineer, Intel Corporation
+41 (0) 79 365 57 48 - http://blog.ffwll.ch
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 103+ messages in thread

* Re: [PATCH v9 35/39] misc/mei/hdcp: Component framework for I915 Interface
  2018-12-13 16:11     ` Daniel Vetter
@ 2018-12-13 16:27       ` Winkler, Tomas
  2018-12-13 17:35         ` Daniel Vetter
  0 siblings, 1 reply; 103+ messages in thread
From: Winkler, Tomas @ 2018-12-13 16:27 UTC (permalink / raw)
  To: Daniel Vetter, C, Ramalingam, Greg KH, Rafael J. Wysocki
  Cc: intel-gfx, dri-devel, Sean Paul

> On Thu, Dec 13, 2018 at 1:36 PM C, Ramalingam <ramalingam.c@intel.com>
> wrote:
> >
> > Tomas and Daniel,
> >
> > We got an issue here.
> >
> > The relationship that we try to build between I915 and mei_hdcp is as follows:
> >
> > We are using the components to establish the relationship.
> > I915 is component master where as mei_hdcp is component.
> > I915 adds the component master during the module load. mei_hdcp adds the
> component when the driver->probe is called (on device driver binding).
> > I915 forces itself such that until mei_hdcp component is added I915_load
> wont be complete.
> > Similarly on complete system, if mei_hdcp component is removed,
> immediately I915 unregister itself and HW will be shutdown.
> >
> > This is completely fine when the modules are loaded and unloaded.
> >
> > But during suspend, mei device disappears and mei bus handles it by
> unbinding device and driver by calling driver->remove.
> > This in-turn removes the component and triggers the master unbind of I915
> where, I915 unregister itself.
> > This cause the HW state mismatch during the suspend and resume.
> >
> > Please check the powerwell mismatch errors at CI report for v9
> > https://intel-gfx-ci.01.org/tree/drm-tip/Trybot_3412/fi-glk-j4005/igt@
> > gem_exec_suspend@basic-s3.html
> >
> > More over unregistering I915 during the suspend is not expected. So how do
> we handle this?
> 
> Bit more context from our irc discussion with Ram:
> 
> I found this very surprising, since I don't know of any other subsystems where
> the devices get outright removed when going through a suspend/resume cycle.
> The device model was built to handle this stuff
> correctly: First clients/devices/interfaces get suspend, then the
> parent/bridge/bus. Same dance in reverse when resuming. This even holds for
> lots of hotpluggable buses, where child devices could indeed disappear on
> resume, but as long as they don't, everything stays the same. It's really
> surprising for something that's soldered onto the board like ME.

HDCP is an application in the ME it's not ME itself..  On the linux side HDCP2 is a virtual device  on mei client virtual bus, 
the bus  is teared down on ME reset, which mostly happen  on power transitions. 
Theoretically,  we could keep it up during power transitions, but so fare it was not necessary
and second it's not guarantie that the all ME applications will reappear after reset.

> 
> Aside: We'll probably need a device_link to make sure mei_hdcp is fully
> resumed before i915 gets resumed, but that's kinda a detail for later on.

Frankly I don’t believe there is currently exact abstraction that supports this model,
neither components nor device_link . 
So fare we used class interface for other purposes, it worked well.

> 
> Tomas, can you pls explain why mei is designed like this? Or is there something
> else we're missing (I didn't dig through the mei bus in detail at all, so not clear
> on what exactly is going on there).
Above.
> 
> Also pulling in device model and suspend/resume experts.
> 
> Thanks, Daniel
> 
> >
> > -Ram
> >
> > On 12/13/2018 9:31 AM, Ramalingam C wrote:
> >
> > Mei hdcp driver is designed as component slave for the I915 component
> > master.
> >
> > v2: Rebased.
> > v3:
> >   Notifier chain is adopted for cldev state update [Tomas]
> > v4:
> >   Made static dummy functions as inline in mei_hdcp.h
> >   API for polling client device status
> >   IS_ENABLED used in header, for config status for mei_hdcp.
> > v5:
> >   Replacing the notifier with component framework. [Daniel]
> > v6:
> >   Rebased on the I915 comp master redesign.
> > v7:
> >   mei_hdcp_component_registered is made static [Uma]
> >   Need for global static variable mei_cldev is removed.
> >
> > Signed-off-by: Ramalingam C <ramalingam.c@intel.com>
> > Reviewed-by: Uma Shankar <uma.shankar@intel.com>
> > ---
> >  drivers/misc/mei/hdcp/mei_hdcp.c | 67
> > +++++++++++++++++++++++++++++++++++++---
> >  1 file changed, 63 insertions(+), 4 deletions(-)
> >
> > diff --git a/drivers/misc/mei/hdcp/mei_hdcp.c
> > b/drivers/misc/mei/hdcp/mei_hdcp.c
> > index b22a71e8c5d7..3de1700dcc9f 100644
> > --- a/drivers/misc/mei/hdcp/mei_hdcp.c
> > +++ b/drivers/misc/mei/hdcp/mei_hdcp.c
> > @@ -23,11 +23,14 @@
> >  #include <linux/slab.h>
> >  #include <linux/uuid.h>
> >  #include <linux/mei_cl_bus.h>
> > +#include <linux/component.h>
> >  #include <drm/drm_connector.h>
> >  #include <drm/i915_component.h>
> >
> >  #include "mei_hdcp.h"
> >
> > +static bool mei_hdcp_component_registered;
> > +
> >  /**
> >   * mei_initiate_hdcp2_session() - Initiate a Wired HDCP2.2 Tx Session in ME
> FW
> >   * @dev: device corresponding to the mei_cl_device @@ -691,8 +694,7
> > @@ mei_close_hdcp_session(struct device *dev, struct hdcp_port_data
> *data)
> >   return 0;
> >  }
> >
> > -static __attribute__((unused))
> > -struct i915_hdcp_component_ops mei_hdcp_ops = {
> > +static struct i915_hdcp_component_ops mei_hdcp_ops = {
> >   .owner = THIS_MODULE,
> >   .initiate_hdcp2_session = mei_initiate_hdcp2_session,
> >   .verify_receiver_cert_prepare_km =
> > mei_verify_receiver_cert_prepare_km,
> > @@ -707,20 +709,77 @@ struct i915_hdcp_component_ops mei_hdcp_ops =
> {
> >   .close_hdcp_session = mei_close_hdcp_session,  };
> >
> > +static int mei_hdcp_component_bind(struct device *mei_kdev,
> > +   struct device *i915_kdev, void *data) {  struct
> > +i915_component_master *master_comp = data;
> > +
> > + dev_info(mei_kdev, "MEI HDCP comp bind\n");
> > + WARN_ON(master_comp->hdcp_ops); master_comp->hdcp_ops =
> > + &mei_hdcp_ops; master_comp->mei_dev = mei_kdev;
> > +
> > + return 0;
> > +}
> > +
> > +static void mei_hdcp_component_unbind(struct device *mei_kdev,
> > +      struct device *i915_kdev, void *data) {  struct
> > +i915_component_master *master_comp = data;
> > +
> > + dev_info(mei_kdev, "MEI HDCP comp unbind\n");  master_comp->hdcp_ops
> > += NULL;  master_comp->mei_dev = NULL; }
> > +
> > +static const struct component_ops mei_hdcp_component_bind_ops = {
> > +.bind = mei_hdcp_component_bind,  .unbind =
> > +mei_hdcp_component_unbind, };
> > +
> > +static void mei_hdcp_component_init(struct device *dev) {  int ret;
> > +
> > + dev_info(dev, "MEI HDCP comp init\n"); ret = component_add(dev,
> > + &mei_hdcp_component_bind_ops); if (ret < 0) { dev_err(dev, "Failed
> > + to add MEI HDCP comp (%d)\n", ret); return; }
> > +
> > + mei_hdcp_component_registered = true; }
> > +
> > +static void mei_hdcp_component_cleanup(struct device *dev) {  if
> > +(!mei_hdcp_component_registered)  return;
> > +
> > + dev_info(dev, "MEI HDCP comp cleanup\n");  component_del(dev,
> > +&mei_hdcp_component_bind_ops);  mei_hdcp_component_registered =
> > +false; }
> > +
> >  static int mei_hdcp_probe(struct mei_cl_device *cldev,
> >    const struct mei_cl_device_id *id)
> >  {
> >   int ret;
> >
> >   ret = mei_cldev_enable(cldev);
> > - if (ret < 0)
> > + if (ret < 0) {
> >   dev_err(&cldev->dev, "mei_cldev_enable Failed. %d\n", ret);
> > + return ret;
> > + }
> > + mei_hdcp_component_init(&cldev->dev);
> >
> > - return ret;
> > + return 0;
> >  }
> >
> >  static int mei_hdcp_remove(struct mei_cl_device *cldev)  {
> > + mei_hdcp_component_cleanup(&cldev->dev);
> > +
> >   return mei_cldev_disable(cldev);
> >  }
> >
> 
> 
> 
> --
> Daniel Vetter
> Software Engineer, Intel Corporation
> +41 (0) 79 365 57 48 - http://blog.ffwll.ch
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 103+ messages in thread

* Re: [PATCH v9 35/39] misc/mei/hdcp: Component framework for I915 Interface
  2018-12-13 16:27       ` Winkler, Tomas
@ 2018-12-13 17:35         ` Daniel Vetter
  2018-12-15 21:20           ` Winkler, Tomas
  0 siblings, 1 reply; 103+ messages in thread
From: Daniel Vetter @ 2018-12-13 17:35 UTC (permalink / raw)
  To: Tomas Winkler; +Cc: Rafael J. Wysocki, intel-gfx, dri-devel, Sean Paul, Greg KH

On Thu, Dec 13, 2018 at 5:27 PM Winkler, Tomas <tomas.winkler@intel.com> wrote:
>
> > On Thu, Dec 13, 2018 at 1:36 PM C, Ramalingam <ramalingam.c@intel.com>
> > wrote:
> > >
> > > Tomas and Daniel,
> > >
> > > We got an issue here.
> > >
> > > The relationship that we try to build between I915 and mei_hdcp is as follows:
> > >
> > > We are using the components to establish the relationship.
> > > I915 is component master where as mei_hdcp is component.
> > > I915 adds the component master during the module load. mei_hdcp adds the
> > component when the driver->probe is called (on device driver binding).
> > > I915 forces itself such that until mei_hdcp component is added I915_load
> > wont be complete.
> > > Similarly on complete system, if mei_hdcp component is removed,
> > immediately I915 unregister itself and HW will be shutdown.
> > >
> > > This is completely fine when the modules are loaded and unloaded.
> > >
> > > But during suspend, mei device disappears and mei bus handles it by
> > unbinding device and driver by calling driver->remove.
> > > This in-turn removes the component and triggers the master unbind of I915
> > where, I915 unregister itself.
> > > This cause the HW state mismatch during the suspend and resume.
> > >
> > > Please check the powerwell mismatch errors at CI report for v9
> > > https://intel-gfx-ci.01.org/tree/drm-tip/Trybot_3412/fi-glk-j4005/igt@
> > > gem_exec_suspend@basic-s3.html
> > >
> > > More over unregistering I915 during the suspend is not expected. So how do
> > we handle this?
> >
> > Bit more context from our irc discussion with Ram:
> >
> > I found this very surprising, since I don't know of any other subsystems where
> > the devices get outright removed when going through a suspend/resume cycle.
> > The device model was built to handle this stuff
> > correctly: First clients/devices/interfaces get suspend, then the
> > parent/bridge/bus. Same dance in reverse when resuming. This even holds for
> > lots of hotpluggable buses, where child devices could indeed disappear on
> > resume, but as long as they don't, everything stays the same. It's really
> > surprising for something that's soldered onto the board like ME.
>
> HDCP is an application in the ME it's not ME itself..  On the linux side HDCP2 is a virtual device  on mei client virtual bus,
> the bus  is teared down on ME reset, which mostly happen  on power transitions.
> Theoretically,  we could keep it up during power transitions, but so fare it was not necessary
> and second it's not guarantie that the all ME applications will reappear after reset.

When does this happen that an ME application doesn't come back after
e.g. suspend/resume?

Also, what's all the place where this reset can happen? Just
suspend/resume/hibernate and all these, or also at other times?

How does userspace deal with the reset over s/r? I'm assuming that at
least the device node file will become invalid (or whatever you're
using as userspace api), so if userspace is accessing stuff on the me
at the same time as we do a suspend/resume, what happens?

> > Aside: We'll probably need a device_link to make sure mei_hdcp is fully
> > resumed before i915 gets resumed, but that's kinda a detail for later on.
>
> Frankly I don’t believe there is currently exact abstraction that supports this model,
> neither components nor device_link .
> So fare we used class interface for other purposes, it worked well.

I'm not clear on what class interface has to do with component or
device link. They all solve different problems, at least as far as I
understand all this stuff ...
-Daniel

> > Tomas, can you pls explain why mei is designed like this? Or is there something
> > else we're missing (I didn't dig through the mei bus in detail at all, so not clear
> > on what exactly is going on there).
> Above.
> >
> > Also pulling in device model and suspend/resume experts.
> >
> > Thanks, Daniel
> >
> > >
> > > -Ram
> > >
> > > On 12/13/2018 9:31 AM, Ramalingam C wrote:
> > >
> > > Mei hdcp driver is designed as component slave for the I915 component
> > > master.
> > >
> > > v2: Rebased.
> > > v3:
> > >   Notifier chain is adopted for cldev state update [Tomas]
> > > v4:
> > >   Made static dummy functions as inline in mei_hdcp.h
> > >   API for polling client device status
> > >   IS_ENABLED used in header, for config status for mei_hdcp.
> > > v5:
> > >   Replacing the notifier with component framework. [Daniel]
> > > v6:
> > >   Rebased on the I915 comp master redesign.
> > > v7:
> > >   mei_hdcp_component_registered is made static [Uma]
> > >   Need for global static variable mei_cldev is removed.
> > >
> > > Signed-off-by: Ramalingam C <ramalingam.c@intel.com>
> > > Reviewed-by: Uma Shankar <uma.shankar@intel.com>
> > > ---
> > >  drivers/misc/mei/hdcp/mei_hdcp.c | 67
> > > +++++++++++++++++++++++++++++++++++++---
> > >  1 file changed, 63 insertions(+), 4 deletions(-)
> > >
> > > diff --git a/drivers/misc/mei/hdcp/mei_hdcp.c
> > > b/drivers/misc/mei/hdcp/mei_hdcp.c
> > > index b22a71e8c5d7..3de1700dcc9f 100644
> > > --- a/drivers/misc/mei/hdcp/mei_hdcp.c
> > > +++ b/drivers/misc/mei/hdcp/mei_hdcp.c
> > > @@ -23,11 +23,14 @@
> > >  #include <linux/slab.h>
> > >  #include <linux/uuid.h>
> > >  #include <linux/mei_cl_bus.h>
> > > +#include <linux/component.h>
> > >  #include <drm/drm_connector.h>
> > >  #include <drm/i915_component.h>
> > >
> > >  #include "mei_hdcp.h"
> > >
> > > +static bool mei_hdcp_component_registered;
> > > +
> > >  /**
> > >   * mei_initiate_hdcp2_session() - Initiate a Wired HDCP2.2 Tx Session in ME
> > FW
> > >   * @dev: device corresponding to the mei_cl_device @@ -691,8 +694,7
> > > @@ mei_close_hdcp_session(struct device *dev, struct hdcp_port_data
> > *data)
> > >   return 0;
> > >  }
> > >
> > > -static __attribute__((unused))
> > > -struct i915_hdcp_component_ops mei_hdcp_ops = {
> > > +static struct i915_hdcp_component_ops mei_hdcp_ops = {
> > >   .owner = THIS_MODULE,
> > >   .initiate_hdcp2_session = mei_initiate_hdcp2_session,
> > >   .verify_receiver_cert_prepare_km =
> > > mei_verify_receiver_cert_prepare_km,
> > > @@ -707,20 +709,77 @@ struct i915_hdcp_component_ops mei_hdcp_ops =
> > {
> > >   .close_hdcp_session = mei_close_hdcp_session,  };
> > >
> > > +static int mei_hdcp_component_bind(struct device *mei_kdev,
> > > +   struct device *i915_kdev, void *data) {  struct
> > > +i915_component_master *master_comp = data;
> > > +
> > > + dev_info(mei_kdev, "MEI HDCP comp bind\n");
> > > + WARN_ON(master_comp->hdcp_ops); master_comp->hdcp_ops =
> > > + &mei_hdcp_ops; master_comp->mei_dev = mei_kdev;
> > > +
> > > + return 0;
> > > +}
> > > +
> > > +static void mei_hdcp_component_unbind(struct device *mei_kdev,
> > > +      struct device *i915_kdev, void *data) {  struct
> > > +i915_component_master *master_comp = data;
> > > +
> > > + dev_info(mei_kdev, "MEI HDCP comp unbind\n");  master_comp->hdcp_ops
> > > += NULL;  master_comp->mei_dev = NULL; }
> > > +
> > > +static const struct component_ops mei_hdcp_component_bind_ops = {
> > > +.bind = mei_hdcp_component_bind,  .unbind =
> > > +mei_hdcp_component_unbind, };
> > > +
> > > +static void mei_hdcp_component_init(struct device *dev) {  int ret;
> > > +
> > > + dev_info(dev, "MEI HDCP comp init\n"); ret = component_add(dev,
> > > + &mei_hdcp_component_bind_ops); if (ret < 0) { dev_err(dev, "Failed
> > > + to add MEI HDCP comp (%d)\n", ret); return; }
> > > +
> > > + mei_hdcp_component_registered = true; }
> > > +
> > > +static void mei_hdcp_component_cleanup(struct device *dev) {  if
> > > +(!mei_hdcp_component_registered)  return;
> > > +
> > > + dev_info(dev, "MEI HDCP comp cleanup\n");  component_del(dev,
> > > +&mei_hdcp_component_bind_ops);  mei_hdcp_component_registered =
> > > +false; }
> > > +
> > >  static int mei_hdcp_probe(struct mei_cl_device *cldev,
> > >    const struct mei_cl_device_id *id)
> > >  {
> > >   int ret;
> > >
> > >   ret = mei_cldev_enable(cldev);
> > > - if (ret < 0)
> > > + if (ret < 0) {
> > >   dev_err(&cldev->dev, "mei_cldev_enable Failed. %d\n", ret);
> > > + return ret;
> > > + }
> > > + mei_hdcp_component_init(&cldev->dev);
> > >
> > > - return ret;
> > > + return 0;
> > >  }
> > >
> > >  static int mei_hdcp_remove(struct mei_cl_device *cldev)  {
> > > + mei_hdcp_component_cleanup(&cldev->dev);
> > > +
> > >   return mei_cldev_disable(cldev);
> > >  }
> > >
> >
> >
> >
> > --
> > Daniel Vetter
> > Software Engineer, Intel Corporation
> > +41 (0) 79 365 57 48 - http://blog.ffwll.ch



-- 
Daniel Vetter
Software Engineer, Intel Corporation
+41 (0) 79 365 57 48 - http://blog.ffwll.ch
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 103+ messages in thread

* Re: [PATCH v9 35/39] misc/mei/hdcp: Component framework for I915 Interface
  2018-12-13 17:35         ` Daniel Vetter
@ 2018-12-15 21:20           ` Winkler, Tomas
  2018-12-17  9:39             ` Daniel Vetter
  0 siblings, 1 reply; 103+ messages in thread
From: Winkler, Tomas @ 2018-12-15 21:20 UTC (permalink / raw)
  To: 'Daniel Vetter'
  Cc: Rafael J. Wysocki, intel-gfx, dri-devel, Sean Paul, Greg KH

> 
> On Thu, Dec 13, 2018 at 5:27 PM Winkler, Tomas <tomas.winkler@intel.com>
> wrote:
> >
> > > On Thu, Dec 13, 2018 at 1:36 PM C, Ramalingam
> > > <ramalingam.c@intel.com>
> > > wrote:
> > > >
> > > > Tomas and Daniel,
> > > >
> > > > We got an issue here.
> > > >
> > > > The relationship that we try to build between I915 and mei_hdcp is as
> follows:
> > > >
> > > > We are using the components to establish the relationship.
> > > > I915 is component master where as mei_hdcp is component.
> > > > I915 adds the component master during the module load. mei_hdcp
> > > > adds the
> > > component when the driver->probe is called (on device driver binding).
> > > > I915 forces itself such that until mei_hdcp component is added
> > > > I915_load
> > > wont be complete.
> > > > Similarly on complete system, if mei_hdcp component is removed,
> > > immediately I915 unregister itself and HW will be shutdown.
> > > >
> > > > This is completely fine when the modules are loaded and unloaded.
> > > >
> > > > But during suspend, mei device disappears and mei bus handles it
> > > > by
> > > unbinding device and driver by calling driver->remove.
> > > > This in-turn removes the component and triggers the master unbind
> > > > of I915
> > > where, I915 unregister itself.
> > > > This cause the HW state mismatch during the suspend and resume.
> > > >
> > > > Please check the powerwell mismatch errors at CI report for v9
> > > > https://intel-gfx-ci.01.org/tree/drm-tip/Trybot_3412/fi-glk-j4005/
> > > > igt@
> > > > gem_exec_suspend@basic-s3.html
> > > >
> > > > More over unregistering I915 during the suspend is not expected.
> > > > So how do
> > > we handle this?
> > >
> > > Bit more context from our irc discussion with Ram:
> > >
> > > I found this very surprising, since I don't know of any other
> > > subsystems where the devices get outright removed when going through a
> suspend/resume cycle.
> > > The device model was built to handle this stuff
> > > correctly: First clients/devices/interfaces get suspend, then the
> > > parent/bridge/bus. Same dance in reverse when resuming. This even
> > > holds for lots of hotpluggable buses, where child devices could
> > > indeed disappear on resume, but as long as they don't, everything
> > > stays the same. It's really surprising for something that's soldered onto the
> board like ME.
> >
> > HDCP is an application in the ME it's not ME itself..  On the linux
> > side HDCP2 is a virtual device  on mei client virtual bus, the bus  is teared
> down on ME reset, which mostly happen  on power transitions.
> > Theoretically,  we could keep it up during power transitions, but so
> > fare it was not necessary and second it's not guarantie that the all ME
> applications will reappear after reset.
> 
> When does this happen that an ME application doesn't come back after e.g.
> suspend/resume?
No, this can happen in special flows such as  fw updates and error conditions, but is has to be supported as well. 
 
> 
> Also, what's all the place where this reset can happen? Just
> suspend/resume/hibernate and all these, or also at other times?

Also on errors and fw update,  the basic assumption is here that it can happen any time. 

> How does userspace deal with the reset over s/r? I'm assuming that at least the
> device node file will become invalid (or whatever you're using as userspace
> api), so if userspace is accessing stuff on the me at the same time as we do a
> suspend/resume, what happens?
> 
> > > Aside: We'll probably need a device_link to make sure mei_hdcp is
> > > fully resumed before i915 gets resumed, but that's kinda a detail for later
> on.
> >
> > Frankly I don’t believe there is currently exact abstraction that
> > supports this model, neither components nor device_link .
> > So fare we used class interface for other purposes, it worked well.
> 
> I'm not clear on what class interface has to do with component or device link.
> They all solve different problems, at least as far as I understand all this stuff ...
> -Daniel

It comes instead of it, device_link is mostly used for power management and component as we see know is not what we need as HDCP 
Is a b it volitle. 
class_interface  gives you two handlers: add and remove device, that's all what is needed for the current implementation. 
> 
> > > Tomas, can you pls explain why mei is designed like this? Or is
> > > there something else we're missing (I didn't dig through the mei bus
> > > in detail at all, so not clear on what exactly is going on there).
> > Above.
> > >
> > > Also pulling in device model and suspend/resume experts.
> > >
> > > Thanks, Daniel
> > >
> > > >
> > > > -Ram
> > > >
> > > > On 12/13/2018 9:31 AM, Ramalingam C wrote:
> > > >
> > > > Mei hdcp driver is designed as component slave for the I915
> > > > component master.
> > > >
> > > > v2: Rebased.
> > > > v3:
> > > >   Notifier chain is adopted for cldev state update [Tomas]
> > > > v4:
> > > >   Made static dummy functions as inline in mei_hdcp.h
> > > >   API for polling client device status
> > > >   IS_ENABLED used in header, for config status for mei_hdcp.
> > > > v5:
> > > >   Replacing the notifier with component framework. [Daniel]
> > > > v6:
> > > >   Rebased on the I915 comp master redesign.
> > > > v7:
> > > >   mei_hdcp_component_registered is made static [Uma]
> > > >   Need for global static variable mei_cldev is removed.
> > > >
> > > > Signed-off-by: Ramalingam C <ramalingam.c@intel.com>
> > > > Reviewed-by: Uma Shankar <uma.shankar@intel.com>
> > > > ---
> > > >  drivers/misc/mei/hdcp/mei_hdcp.c | 67
> > > > +++++++++++++++++++++++++++++++++++++---
> > > >  1 file changed, 63 insertions(+), 4 deletions(-)
> > > >
> > > > diff --git a/drivers/misc/mei/hdcp/mei_hdcp.c
> > > > b/drivers/misc/mei/hdcp/mei_hdcp.c
> > > > index b22a71e8c5d7..3de1700dcc9f 100644
> > > > --- a/drivers/misc/mei/hdcp/mei_hdcp.c
> > > > +++ b/drivers/misc/mei/hdcp/mei_hdcp.c
> > > > @@ -23,11 +23,14 @@
> > > >  #include <linux/slab.h>
> > > >  #include <linux/uuid.h>
> > > >  #include <linux/mei_cl_bus.h>
> > > > +#include <linux/component.h>
> > > >  #include <drm/drm_connector.h>
> > > >  #include <drm/i915_component.h>
> > > >
> > > >  #include "mei_hdcp.h"
> > > >
> > > > +static bool mei_hdcp_component_registered;
> > > > +
> > > >  /**
> > > >   * mei_initiate_hdcp2_session() - Initiate a Wired HDCP2.2 Tx
> > > > Session in ME
> > > FW
> > > >   * @dev: device corresponding to the mei_cl_device @@ -691,8
> > > > +694,7 @@ mei_close_hdcp_session(struct device *dev, struct
> > > > hdcp_port_data
> > > *data)
> > > >   return 0;
> > > >  }
> > > >
> > > > -static __attribute__((unused))
> > > > -struct i915_hdcp_component_ops mei_hdcp_ops = {
> > > > +static struct i915_hdcp_component_ops mei_hdcp_ops = {
> > > >   .owner = THIS_MODULE,
> > > >   .initiate_hdcp2_session = mei_initiate_hdcp2_session,
> > > >   .verify_receiver_cert_prepare_km =
> > > > mei_verify_receiver_cert_prepare_km,
> > > > @@ -707,20 +709,77 @@ struct i915_hdcp_component_ops
> mei_hdcp_ops
> > > > =
> > > {
> > > >   .close_hdcp_session = mei_close_hdcp_session,  };
> > > >
> > > > +static int mei_hdcp_component_bind(struct device *mei_kdev,
> > > > +   struct device *i915_kdev, void *data) {  struct
> > > > +i915_component_master *master_comp = data;
> > > > +
> > > > + dev_info(mei_kdev, "MEI HDCP comp bind\n");
> > > > + WARN_ON(master_comp->hdcp_ops); master_comp->hdcp_ops =
> > > > + &mei_hdcp_ops; master_comp->mei_dev = mei_kdev;
> > > > +
> > > > + return 0;
> > > > +}
> > > > +
> > > > +static void mei_hdcp_component_unbind(struct device *mei_kdev,
> > > > +      struct device *i915_kdev, void *data) {  struct
> > > > +i915_component_master *master_comp = data;
> > > > +
> > > > + dev_info(mei_kdev, "MEI HDCP comp unbind\n");
> > > > +master_comp->hdcp_ops = NULL;  master_comp->mei_dev = NULL; }
> > > > +
> > > > +static const struct component_ops mei_hdcp_component_bind_ops = {
> > > > +.bind = mei_hdcp_component_bind,  .unbind =
> > > > +mei_hdcp_component_unbind, };
> > > > +
> > > > +static void mei_hdcp_component_init(struct device *dev) {  int
> > > > +ret;
> > > > +
> > > > + dev_info(dev, "MEI HDCP comp init\n"); ret = component_add(dev,
> > > > + &mei_hdcp_component_bind_ops); if (ret < 0) { dev_err(dev,
> > > > + "Failed to add MEI HDCP comp (%d)\n", ret); return; }
> > > > +
> > > > + mei_hdcp_component_registered = true; }
> > > > +
> > > > +static void mei_hdcp_component_cleanup(struct device *dev) {  if
> > > > +(!mei_hdcp_component_registered)  return;
> > > > +
> > > > + dev_info(dev, "MEI HDCP comp cleanup\n");  component_del(dev,
> > > > +&mei_hdcp_component_bind_ops);  mei_hdcp_component_registered =
> > > > +false; }
> > > > +
> > > >  static int mei_hdcp_probe(struct mei_cl_device *cldev,
> > > >    const struct mei_cl_device_id *id)  {
> > > >   int ret;
> > > >
> > > >   ret = mei_cldev_enable(cldev);
> > > > - if (ret < 0)
> > > > + if (ret < 0) {
> > > >   dev_err(&cldev->dev, "mei_cldev_enable Failed. %d\n", ret);
> > > > + return ret;
> > > > + }
> > > > + mei_hdcp_component_init(&cldev->dev);
> > > >
> > > > - return ret;
> > > > + return 0;
> > > >  }
> > > >
> > > >  static int mei_hdcp_remove(struct mei_cl_device *cldev)  {
> > > > + mei_hdcp_component_cleanup(&cldev->dev);
> > > > +
> > > >   return mei_cldev_disable(cldev);  }
> > > >
> > >
> > >
> > >
> > > --
> > > Daniel Vetter
> > > Software Engineer, Intel Corporation
> > > +41 (0) 79 365 57 48 - http://blog.ffwll.ch
> 
> 
> 
> --
> Daniel Vetter
> Software Engineer, Intel Corporation
> +41 (0) 79 365 57 48 - http://blog.ffwll.ch
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 103+ messages in thread

* Re: [PATCH v9 35/39] misc/mei/hdcp: Component framework for I915 Interface
  2018-12-15 21:20           ` Winkler, Tomas
@ 2018-12-17  9:39             ` Daniel Vetter
  2018-12-17  9:59               ` Daniel Vetter
  2018-12-17 10:57               ` Winkler, Tomas
  0 siblings, 2 replies; 103+ messages in thread
From: Daniel Vetter @ 2018-12-17  9:39 UTC (permalink / raw)
  To: Winkler, Tomas
  Cc: Rafael J. Wysocki, 'Daniel Vetter',
	intel-gfx, dri-devel, Sean Paul, Greg KH

On Sat, Dec 15, 2018 at 09:20:38PM +0000, Winkler, Tomas wrote:
> > 
> > On Thu, Dec 13, 2018 at 5:27 PM Winkler, Tomas <tomas.winkler@intel.com>
> > wrote:
> > >
> > > > On Thu, Dec 13, 2018 at 1:36 PM C, Ramalingam
> > > > <ramalingam.c@intel.com>
> > > > wrote:
> > > > >
> > > > > Tomas and Daniel,
> > > > >
> > > > > We got an issue here.
> > > > >
> > > > > The relationship that we try to build between I915 and mei_hdcp is as
> > follows:
> > > > >
> > > > > We are using the components to establish the relationship.
> > > > > I915 is component master where as mei_hdcp is component.
> > > > > I915 adds the component master during the module load. mei_hdcp
> > > > > adds the
> > > > component when the driver->probe is called (on device driver binding).
> > > > > I915 forces itself such that until mei_hdcp component is added
> > > > > I915_load
> > > > wont be complete.
> > > > > Similarly on complete system, if mei_hdcp component is removed,
> > > > immediately I915 unregister itself and HW will be shutdown.
> > > > >
> > > > > This is completely fine when the modules are loaded and unloaded.
> > > > >
> > > > > But during suspend, mei device disappears and mei bus handles it
> > > > > by
> > > > unbinding device and driver by calling driver->remove.
> > > > > This in-turn removes the component and triggers the master unbind
> > > > > of I915
> > > > where, I915 unregister itself.
> > > > > This cause the HW state mismatch during the suspend and resume.
> > > > >
> > > > > Please check the powerwell mismatch errors at CI report for v9
> > > > > https://intel-gfx-ci.01.org/tree/drm-tip/Trybot_3412/fi-glk-j4005/
> > > > > igt@
> > > > > gem_exec_suspend@basic-s3.html
> > > > >
> > > > > More over unregistering I915 during the suspend is not expected.
> > > > > So how do
> > > > we handle this?
> > > >
> > > > Bit more context from our irc discussion with Ram:
> > > >
> > > > I found this very surprising, since I don't know of any other
> > > > subsystems where the devices get outright removed when going through a
> > suspend/resume cycle.
> > > > The device model was built to handle this stuff
> > > > correctly: First clients/devices/interfaces get suspend, then the
> > > > parent/bridge/bus. Same dance in reverse when resuming. This even
> > > > holds for lots of hotpluggable buses, where child devices could
> > > > indeed disappear on resume, but as long as they don't, everything
> > > > stays the same. It's really surprising for something that's soldered onto the
> > board like ME.
> > >
> > > HDCP is an application in the ME it's not ME itself..  On the linux
> > > side HDCP2 is a virtual device  on mei client virtual bus, the bus  is teared
> > down on ME reset, which mostly happen  on power transitions.
> > > Theoretically,  we could keep it up during power transitions, but so
> > > fare it was not necessary and second it's not guarantie that the all ME
> > applications will reappear after reset.
> > 
> > When does this happen that an ME application doesn't come back after e.g.
> > suspend/resume?
> No, this can happen in special flows such as  fw updates and error conditions, but is has to be supported as well. 
>  
> > 
> > Also, what's all the place where this reset can happen? Just
> > suspend/resume/hibernate and all these, or also at other times?
> 
> Also on errors and fw update,  the basic assumption is here that it can happen any time. 

If this can happen any time, what are we supposed to do if this happens
while we're doing something with the hdcp mei? If this is such a common
occurence I guess we need to somehow wait until everyting is rebound and
working again. I think ideally mei core would handle that for us, but I
guess if this just randomly happens then we need to redo all the
transactions. So does need some involvement of the higher levels.

Also, how likely is it that the hdcp mei will outright disappear and not
come back after a reset?

> > How does userspace deal with the reset over s/r? I'm assuming that at least the
> > device node file will become invalid (or whatever you're using as userspace
> > api), so if userspace is accessing stuff on the me at the same time as we do a
> > suspend/resume, what happens?

Also, answer to how other users handle this would be enlighting.

> > > > Aside: We'll probably need a device_link to make sure mei_hdcp is
> > > > fully resumed before i915 gets resumed, but that's kinda a detail for later
> > on.
> > >
> > > Frankly I don’t believe there is currently exact abstraction that
> > > supports this model, neither components nor device_link .
> > > So fare we used class interface for other purposes, it worked well.
> > 
> > I'm not clear on what class interface has to do with component or device link.
> > They all solve different problems, at least as far as I understand all this stuff ...
> > -Daniel
> 
> It comes instead of it, device_link is mostly used for power management and component as we see know is not what we need as HDCP 
> Is a b it volitle. 
> class_interface  gives you two handlers: add and remove device, that's all what is needed for the current implementation. 

Well someone needs to handle the volatility of hdcp, and atm we seem to be
playing a game of pass the bucket. I still think that mei_hdcp should
supply a clean interface to i915, with all the reset madness handled
internally. But depending upon how badly this all leaks we might need to
have a retry logic in the i915 hdcp flow too.

device linke we'll probably need anyway, since i915 resuming when hdcp is
not yet up is not a good idea no matter what's goîng on.
-Daniel

> > 
> > > > Tomas, can you pls explain why mei is designed like this? Or is
> > > > there something else we're missing (I didn't dig through the mei bus
> > > > in detail at all, so not clear on what exactly is going on there).
> > > Above.
> > > >
> > > > Also pulling in device model and suspend/resume experts.
> > > >
> > > > Thanks, Daniel
> > > >
> > > > >
> > > > > -Ram
> > > > >
> > > > > On 12/13/2018 9:31 AM, Ramalingam C wrote:
> > > > >
> > > > > Mei hdcp driver is designed as component slave for the I915
> > > > > component master.
> > > > >
> > > > > v2: Rebased.
> > > > > v3:
> > > > >   Notifier chain is adopted for cldev state update [Tomas]
> > > > > v4:
> > > > >   Made static dummy functions as inline in mei_hdcp.h
> > > > >   API for polling client device status
> > > > >   IS_ENABLED used in header, for config status for mei_hdcp.
> > > > > v5:
> > > > >   Replacing the notifier with component framework. [Daniel]
> > > > > v6:
> > > > >   Rebased on the I915 comp master redesign.
> > > > > v7:
> > > > >   mei_hdcp_component_registered is made static [Uma]
> > > > >   Need for global static variable mei_cldev is removed.
> > > > >
> > > > > Signed-off-by: Ramalingam C <ramalingam.c@intel.com>
> > > > > Reviewed-by: Uma Shankar <uma.shankar@intel.com>
> > > > > ---
> > > > >  drivers/misc/mei/hdcp/mei_hdcp.c | 67
> > > > > +++++++++++++++++++++++++++++++++++++---
> > > > >  1 file changed, 63 insertions(+), 4 deletions(-)
> > > > >
> > > > > diff --git a/drivers/misc/mei/hdcp/mei_hdcp.c
> > > > > b/drivers/misc/mei/hdcp/mei_hdcp.c
> > > > > index b22a71e8c5d7..3de1700dcc9f 100644
> > > > > --- a/drivers/misc/mei/hdcp/mei_hdcp.c
> > > > > +++ b/drivers/misc/mei/hdcp/mei_hdcp.c
> > > > > @@ -23,11 +23,14 @@
> > > > >  #include <linux/slab.h>
> > > > >  #include <linux/uuid.h>
> > > > >  #include <linux/mei_cl_bus.h>
> > > > > +#include <linux/component.h>
> > > > >  #include <drm/drm_connector.h>
> > > > >  #include <drm/i915_component.h>
> > > > >
> > > > >  #include "mei_hdcp.h"
> > > > >
> > > > > +static bool mei_hdcp_component_registered;
> > > > > +
> > > > >  /**
> > > > >   * mei_initiate_hdcp2_session() - Initiate a Wired HDCP2.2 Tx
> > > > > Session in ME
> > > > FW
> > > > >   * @dev: device corresponding to the mei_cl_device @@ -691,8
> > > > > +694,7 @@ mei_close_hdcp_session(struct device *dev, struct
> > > > > hdcp_port_data
> > > > *data)
> > > > >   return 0;
> > > > >  }
> > > > >
> > > > > -static __attribute__((unused))
> > > > > -struct i915_hdcp_component_ops mei_hdcp_ops = {
> > > > > +static struct i915_hdcp_component_ops mei_hdcp_ops = {
> > > > >   .owner = THIS_MODULE,
> > > > >   .initiate_hdcp2_session = mei_initiate_hdcp2_session,
> > > > >   .verify_receiver_cert_prepare_km =
> > > > > mei_verify_receiver_cert_prepare_km,
> > > > > @@ -707,20 +709,77 @@ struct i915_hdcp_component_ops
> > mei_hdcp_ops
> > > > > =
> > > > {
> > > > >   .close_hdcp_session = mei_close_hdcp_session,  };
> > > > >
> > > > > +static int mei_hdcp_component_bind(struct device *mei_kdev,
> > > > > +   struct device *i915_kdev, void *data) {  struct
> > > > > +i915_component_master *master_comp = data;
> > > > > +
> > > > > + dev_info(mei_kdev, "MEI HDCP comp bind\n");
> > > > > + WARN_ON(master_comp->hdcp_ops); master_comp->hdcp_ops =
> > > > > + &mei_hdcp_ops; master_comp->mei_dev = mei_kdev;
> > > > > +
> > > > > + return 0;
> > > > > +}
> > > > > +
> > > > > +static void mei_hdcp_component_unbind(struct device *mei_kdev,
> > > > > +      struct device *i915_kdev, void *data) {  struct
> > > > > +i915_component_master *master_comp = data;
> > > > > +
> > > > > + dev_info(mei_kdev, "MEI HDCP comp unbind\n");
> > > > > +master_comp->hdcp_ops = NULL;  master_comp->mei_dev = NULL; }
> > > > > +
> > > > > +static const struct component_ops mei_hdcp_component_bind_ops = {
> > > > > +.bind = mei_hdcp_component_bind,  .unbind =
> > > > > +mei_hdcp_component_unbind, };
> > > > > +
> > > > > +static void mei_hdcp_component_init(struct device *dev) {  int
> > > > > +ret;
> > > > > +
> > > > > + dev_info(dev, "MEI HDCP comp init\n"); ret = component_add(dev,
> > > > > + &mei_hdcp_component_bind_ops); if (ret < 0) { dev_err(dev,
> > > > > + "Failed to add MEI HDCP comp (%d)\n", ret); return; }
> > > > > +
> > > > > + mei_hdcp_component_registered = true; }
> > > > > +
> > > > > +static void mei_hdcp_component_cleanup(struct device *dev) {  if
> > > > > +(!mei_hdcp_component_registered)  return;
> > > > > +
> > > > > + dev_info(dev, "MEI HDCP comp cleanup\n");  component_del(dev,
> > > > > +&mei_hdcp_component_bind_ops);  mei_hdcp_component_registered =
> > > > > +false; }
> > > > > +
> > > > >  static int mei_hdcp_probe(struct mei_cl_device *cldev,
> > > > >    const struct mei_cl_device_id *id)  {
> > > > >   int ret;
> > > > >
> > > > >   ret = mei_cldev_enable(cldev);
> > > > > - if (ret < 0)
> > > > > + if (ret < 0) {
> > > > >   dev_err(&cldev->dev, "mei_cldev_enable Failed. %d\n", ret);
> > > > > + return ret;
> > > > > + }
> > > > > + mei_hdcp_component_init(&cldev->dev);
> > > > >
> > > > > - return ret;
> > > > > + return 0;
> > > > >  }
> > > > >
> > > > >  static int mei_hdcp_remove(struct mei_cl_device *cldev)  {
> > > > > + mei_hdcp_component_cleanup(&cldev->dev);
> > > > > +
> > > > >   return mei_cldev_disable(cldev);  }
> > > > >
> > > >
> > > >
> > > >
> > > > --
> > > > Daniel Vetter
> > > > Software Engineer, Intel Corporation
> > > > +41 (0) 79 365 57 48 - http://blog.ffwll.ch
> > 
> > 
> > 
> > --
> > Daniel Vetter
> > Software Engineer, Intel Corporation
> > +41 (0) 79 365 57 48 - http://blog.ffwll.ch

-- 
Daniel Vetter
Software Engineer, Intel Corporation
http://blog.ffwll.ch
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 103+ messages in thread

* Re: [PATCH v9 35/39] misc/mei/hdcp: Component framework for I915 Interface
  2018-12-17  9:39             ` Daniel Vetter
@ 2018-12-17  9:59               ` Daniel Vetter
  2018-12-17 10:57               ` Winkler, Tomas
  1 sibling, 0 replies; 103+ messages in thread
From: Daniel Vetter @ 2018-12-17  9:59 UTC (permalink / raw)
  To: Winkler, Tomas
  Cc: Rafael J. Wysocki, 'Daniel Vetter',
	intel-gfx, dri-devel, Shankar, Uma, Sean Paul, Greg KH

On Mon, Dec 17, 2018 at 10:39:07AM +0100, Daniel Vetter wrote:
> On Sat, Dec 15, 2018 at 09:20:38PM +0000, Winkler, Tomas wrote:
> > > 
> > > On Thu, Dec 13, 2018 at 5:27 PM Winkler, Tomas <tomas.winkler@intel.com>
> > > wrote:
> > > >
> > > > > On Thu, Dec 13, 2018 at 1:36 PM C, Ramalingam
> > > > > <ramalingam.c@intel.com>
> > > > > wrote:
> > > > > >
> > > > > > Tomas and Daniel,
> > > > > >
> > > > > > We got an issue here.
> > > > > >
> > > > > > The relationship that we try to build between I915 and mei_hdcp is as
> > > follows:
> > > > > >
> > > > > > We are using the components to establish the relationship.
> > > > > > I915 is component master where as mei_hdcp is component.
> > > > > > I915 adds the component master during the module load. mei_hdcp
> > > > > > adds the
> > > > > component when the driver->probe is called (on device driver binding).
> > > > > > I915 forces itself such that until mei_hdcp component is added
> > > > > > I915_load
> > > > > wont be complete.
> > > > > > Similarly on complete system, if mei_hdcp component is removed,
> > > > > immediately I915 unregister itself and HW will be shutdown.
> > > > > >
> > > > > > This is completely fine when the modules are loaded and unloaded.
> > > > > >
> > > > > > But during suspend, mei device disappears and mei bus handles it
> > > > > > by
> > > > > unbinding device and driver by calling driver->remove.
> > > > > > This in-turn removes the component and triggers the master unbind
> > > > > > of I915
> > > > > where, I915 unregister itself.
> > > > > > This cause the HW state mismatch during the suspend and resume.
> > > > > >
> > > > > > Please check the powerwell mismatch errors at CI report for v9
> > > > > > https://intel-gfx-ci.01.org/tree/drm-tip/Trybot_3412/fi-glk-j4005/
> > > > > > igt@
> > > > > > gem_exec_suspend@basic-s3.html
> > > > > >
> > > > > > More over unregistering I915 during the suspend is not expected.
> > > > > > So how do
> > > > > we handle this?
> > > > >
> > > > > Bit more context from our irc discussion with Ram:
> > > > >
> > > > > I found this very surprising, since I don't know of any other
> > > > > subsystems where the devices get outright removed when going through a
> > > suspend/resume cycle.
> > > > > The device model was built to handle this stuff
> > > > > correctly: First clients/devices/interfaces get suspend, then the
> > > > > parent/bridge/bus. Same dance in reverse when resuming. This even
> > > > > holds for lots of hotpluggable buses, where child devices could
> > > > > indeed disappear on resume, but as long as they don't, everything
> > > > > stays the same. It's really surprising for something that's soldered onto the
> > > board like ME.
> > > >
> > > > HDCP is an application in the ME it's not ME itself..  On the linux
> > > > side HDCP2 is a virtual device  on mei client virtual bus, the bus  is teared
> > > down on ME reset, which mostly happen  on power transitions.
> > > > Theoretically,  we could keep it up during power transitions, but so
> > > > fare it was not necessary and second it's not guarantie that the all ME
> > > applications will reappear after reset.
> > > 
> > > When does this happen that an ME application doesn't come back after e.g.
> > > suspend/resume?
> > No, this can happen in special flows such as  fw updates and error conditions, but is has to be supported as well. 
> >  
> > > 
> > > Also, what's all the place where this reset can happen? Just
> > > suspend/resume/hibernate and all these, or also at other times?
> > 
> > Also on errors and fw update,  the basic assumption is here that it can happen any time. 
> 
> If this can happen any time, what are we supposed to do if this happens
> while we're doing something with the hdcp mei? If this is such a common
> occurence I guess we need to somehow wait until everyting is rebound and
> working again. I think ideally mei core would handle that for us, but I
> guess if this just randomly happens then we need to redo all the
> transactions. So does need some involvement of the higher levels.

Few more questions on this, beyond the ones in the previous mail.

So generally drivers don't support upgrading the fw at runtime, but only
look once for upgraded fw on driver load (before anyone is using is).
What's the use-case that requires this.

I'm also rather worried about "this can happen any time". Is ME fw so
unstable it just randomly crashes for no good reason at all, taking our
hdcp session with it? Or is this more like "cosmic rays can happen" kind
of problem (which we don't care about)?

> 
> Also, how likely is it that the hdcp mei will outright disappear and not
> come back after a reset?
> 
> > > How does userspace deal with the reset over s/r? I'm assuming that at least the
> > > device node file will become invalid (or whatever you're using as userspace
> > > api), so if userspace is accessing stuff on the me at the same time as we do a
> > > suspend/resume, what happens?
> 
> Also, answer to how other users handle this would be enlighting.
> 
> > > > > Aside: We'll probably need a device_link to make sure mei_hdcp is
> > > > > fully resumed before i915 gets resumed, but that's kinda a detail for later
> > > on.
> > > >
> > > > Frankly I don’t believe there is currently exact abstraction that
> > > > supports this model, neither components nor device_link .
> > > > So fare we used class interface for other purposes, it worked well.
> > > 
> > > I'm not clear on what class interface has to do with component or device link.
> > > They all solve different problems, at least as far as I understand all this stuff ...
> > > -Daniel
> > 
> > It comes instead of it, device_link is mostly used for power management and component as we see know is not what we need as HDCP 
> > Is a b it volitle. 
> > class_interface  gives you two handlers: add and remove device, that's all what is needed for the current implementation. 
> 
> Well someone needs to handle the volatility of hdcp, and atm we seem to be
> playing a game of pass the bucket. I still think that mei_hdcp should
> supply a clean interface to i915, with all the reset madness handled
> internally. But depending upon how badly this all leaks we might need to
> have a retry logic in the i915 hdcp flow too.
> 
> device linke we'll probably need anyway, since i915 resuming when hdcp is
> not yet up is not a good idea no matter what's goîng on.

Cheers, Daniel

> -Daniel
> 
> > > 
> > > > > Tomas, can you pls explain why mei is designed like this? Or is
> > > > > there something else we're missing (I didn't dig through the mei bus
> > > > > in detail at all, so not clear on what exactly is going on there).
> > > > Above.
> > > > >
> > > > > Also pulling in device model and suspend/resume experts.
> > > > >
> > > > > Thanks, Daniel
> > > > >
> > > > > >
> > > > > > -Ram
> > > > > >
> > > > > > On 12/13/2018 9:31 AM, Ramalingam C wrote:
> > > > > >
> > > > > > Mei hdcp driver is designed as component slave for the I915
> > > > > > component master.
> > > > > >
> > > > > > v2: Rebased.
> > > > > > v3:
> > > > > >   Notifier chain is adopted for cldev state update [Tomas]
> > > > > > v4:
> > > > > >   Made static dummy functions as inline in mei_hdcp.h
> > > > > >   API for polling client device status
> > > > > >   IS_ENABLED used in header, for config status for mei_hdcp.
> > > > > > v5:
> > > > > >   Replacing the notifier with component framework. [Daniel]
> > > > > > v6:
> > > > > >   Rebased on the I915 comp master redesign.
> > > > > > v7:
> > > > > >   mei_hdcp_component_registered is made static [Uma]
> > > > > >   Need for global static variable mei_cldev is removed.
> > > > > >
> > > > > > Signed-off-by: Ramalingam C <ramalingam.c@intel.com>
> > > > > > Reviewed-by: Uma Shankar <uma.shankar@intel.com>
> > > > > > ---
> > > > > >  drivers/misc/mei/hdcp/mei_hdcp.c | 67
> > > > > > +++++++++++++++++++++++++++++++++++++---
> > > > > >  1 file changed, 63 insertions(+), 4 deletions(-)
> > > > > >
> > > > > > diff --git a/drivers/misc/mei/hdcp/mei_hdcp.c
> > > > > > b/drivers/misc/mei/hdcp/mei_hdcp.c
> > > > > > index b22a71e8c5d7..3de1700dcc9f 100644
> > > > > > --- a/drivers/misc/mei/hdcp/mei_hdcp.c
> > > > > > +++ b/drivers/misc/mei/hdcp/mei_hdcp.c
> > > > > > @@ -23,11 +23,14 @@
> > > > > >  #include <linux/slab.h>
> > > > > >  #include <linux/uuid.h>
> > > > > >  #include <linux/mei_cl_bus.h>
> > > > > > +#include <linux/component.h>
> > > > > >  #include <drm/drm_connector.h>
> > > > > >  #include <drm/i915_component.h>
> > > > > >
> > > > > >  #include "mei_hdcp.h"
> > > > > >
> > > > > > +static bool mei_hdcp_component_registered;
> > > > > > +
> > > > > >  /**
> > > > > >   * mei_initiate_hdcp2_session() - Initiate a Wired HDCP2.2 Tx
> > > > > > Session in ME
> > > > > FW
> > > > > >   * @dev: device corresponding to the mei_cl_device @@ -691,8
> > > > > > +694,7 @@ mei_close_hdcp_session(struct device *dev, struct
> > > > > > hdcp_port_data
> > > > > *data)
> > > > > >   return 0;
> > > > > >  }
> > > > > >
> > > > > > -static __attribute__((unused))
> > > > > > -struct i915_hdcp_component_ops mei_hdcp_ops = {
> > > > > > +static struct i915_hdcp_component_ops mei_hdcp_ops = {
> > > > > >   .owner = THIS_MODULE,
> > > > > >   .initiate_hdcp2_session = mei_initiate_hdcp2_session,
> > > > > >   .verify_receiver_cert_prepare_km =
> > > > > > mei_verify_receiver_cert_prepare_km,
> > > > > > @@ -707,20 +709,77 @@ struct i915_hdcp_component_ops
> > > mei_hdcp_ops
> > > > > > =
> > > > > {
> > > > > >   .close_hdcp_session = mei_close_hdcp_session,  };
> > > > > >
> > > > > > +static int mei_hdcp_component_bind(struct device *mei_kdev,
> > > > > > +   struct device *i915_kdev, void *data) {  struct
> > > > > > +i915_component_master *master_comp = data;
> > > > > > +
> > > > > > + dev_info(mei_kdev, "MEI HDCP comp bind\n");
> > > > > > + WARN_ON(master_comp->hdcp_ops); master_comp->hdcp_ops =
> > > > > > + &mei_hdcp_ops; master_comp->mei_dev = mei_kdev;
> > > > > > +
> > > > > > + return 0;
> > > > > > +}
> > > > > > +
> > > > > > +static void mei_hdcp_component_unbind(struct device *mei_kdev,
> > > > > > +      struct device *i915_kdev, void *data) {  struct
> > > > > > +i915_component_master *master_comp = data;
> > > > > > +
> > > > > > + dev_info(mei_kdev, "MEI HDCP comp unbind\n");
> > > > > > +master_comp->hdcp_ops = NULL;  master_comp->mei_dev = NULL; }
> > > > > > +
> > > > > > +static const struct component_ops mei_hdcp_component_bind_ops = {
> > > > > > +.bind = mei_hdcp_component_bind,  .unbind =
> > > > > > +mei_hdcp_component_unbind, };
> > > > > > +
> > > > > > +static void mei_hdcp_component_init(struct device *dev) {  int
> > > > > > +ret;
> > > > > > +
> > > > > > + dev_info(dev, "MEI HDCP comp init\n"); ret = component_add(dev,
> > > > > > + &mei_hdcp_component_bind_ops); if (ret < 0) { dev_err(dev,
> > > > > > + "Failed to add MEI HDCP comp (%d)\n", ret); return; }
> > > > > > +
> > > > > > + mei_hdcp_component_registered = true; }
> > > > > > +
> > > > > > +static void mei_hdcp_component_cleanup(struct device *dev) {  if
> > > > > > +(!mei_hdcp_component_registered)  return;
> > > > > > +
> > > > > > + dev_info(dev, "MEI HDCP comp cleanup\n");  component_del(dev,
> > > > > > +&mei_hdcp_component_bind_ops);  mei_hdcp_component_registered =
> > > > > > +false; }
> > > > > > +
> > > > > >  static int mei_hdcp_probe(struct mei_cl_device *cldev,
> > > > > >    const struct mei_cl_device_id *id)  {
> > > > > >   int ret;
> > > > > >
> > > > > >   ret = mei_cldev_enable(cldev);
> > > > > > - if (ret < 0)
> > > > > > + if (ret < 0) {
> > > > > >   dev_err(&cldev->dev, "mei_cldev_enable Failed. %d\n", ret);
> > > > > > + return ret;
> > > > > > + }
> > > > > > + mei_hdcp_component_init(&cldev->dev);
> > > > > >
> > > > > > - return ret;
> > > > > > + return 0;
> > > > > >  }
> > > > > >
> > > > > >  static int mei_hdcp_remove(struct mei_cl_device *cldev)  {
> > > > > > + mei_hdcp_component_cleanup(&cldev->dev);
> > > > > > +
> > > > > >   return mei_cldev_disable(cldev);  }
> > > > > >
> > > > >
> > > > >
> > > > >
> > > > > --
> > > > > Daniel Vetter
> > > > > Software Engineer, Intel Corporation
> > > > > +41 (0) 79 365 57 48 - http://blog.ffwll.ch
> > > 
> > > 
> > > 
> > > --
> > > Daniel Vetter
> > > Software Engineer, Intel Corporation
> > > +41 (0) 79 365 57 48 - http://blog.ffwll.ch
> 
> -- 
> Daniel Vetter
> Software Engineer, Intel Corporation
> http://blog.ffwll.ch

-- 
Daniel Vetter
Software Engineer, Intel Corporation
http://blog.ffwll.ch
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 103+ messages in thread

* Re: [PATCH v9 35/39] misc/mei/hdcp: Component framework for I915 Interface
  2018-12-17  9:39             ` Daniel Vetter
  2018-12-17  9:59               ` Daniel Vetter
@ 2018-12-17 10:57               ` Winkler, Tomas
  2018-12-17 13:46                 ` Daniel Vetter
  1 sibling, 1 reply; 103+ messages in thread
From: Winkler, Tomas @ 2018-12-17 10:57 UTC (permalink / raw)
  To: Daniel Vetter
  Cc: Rafael J. Wysocki, 'Daniel Vetter',
	intel-gfx, dri-devel, Sean Paul, Greg KH


> On Sat, Dec 15, 2018 at 09:20:38PM +0000, Winkler, Tomas wrote:
> > >
> > > On Thu, Dec 13, 2018 at 5:27 PM Winkler, Tomas
> > > <tomas.winkler@intel.com>
> > > wrote:
> > > >
> > > > > On Thu, Dec 13, 2018 at 1:36 PM C, Ramalingam
> > > > > <ramalingam.c@intel.com>
> > > > > wrote:
> > > > > >
> > > > > > Tomas and Daniel,
> > > > > >
> > > > > > We got an issue here.
> > > > > >
> > > > > > The relationship that we try to build between I915 and
> > > > > > mei_hdcp is as
> > > follows:
> > > > > >
> > > > > > We are using the components to establish the relationship.
> > > > > > I915 is component master where as mei_hdcp is component.
> > > > > > I915 adds the component master during the module load.
> > > > > > mei_hdcp adds the
> > > > > component when the driver->probe is called (on device driver binding).
> > > > > > I915 forces itself such that until mei_hdcp component is added
> > > > > > I915_load
> > > > > wont be complete.
> > > > > > Similarly on complete system, if mei_hdcp component is
> > > > > > removed,
> > > > > immediately I915 unregister itself and HW will be shutdown.
> > > > > >
> > > > > > This is completely fine when the modules are loaded and unloaded.
> > > > > >
> > > > > > But during suspend, mei device disappears and mei bus handles
> > > > > > it by
> > > > > unbinding device and driver by calling driver->remove.
> > > > > > This in-turn removes the component and triggers the master
> > > > > > unbind of I915
> > > > > where, I915 unregister itself.
> > > > > > This cause the HW state mismatch during the suspend and resume.
> > > > > >
> > > > > > Please check the powerwell mismatch errors at CI report for v9
> > > > > > https://intel-gfx-ci.01.org/tree/drm-tip/Trybot_3412/fi-glk-j4
> > > > > > 005/
> > > > > > igt@
> > > > > > gem_exec_suspend@basic-s3.html
> > > > > >
> > > > > > More over unregistering I915 during the suspend is not expected.
> > > > > > So how do
> > > > > we handle this?
> > > > >
> > > > > Bit more context from our irc discussion with Ram:
> > > > >
> > > > > I found this very surprising, since I don't know of any other
> > > > > subsystems where the devices get outright removed when going
> > > > > through a
> > > suspend/resume cycle.
> > > > > The device model was built to handle this stuff
> > > > > correctly: First clients/devices/interfaces get suspend, then
> > > > > the parent/bridge/bus. Same dance in reverse when resuming. This
> > > > > even holds for lots of hotpluggable buses, where child devices
> > > > > could indeed disappear on resume, but as long as they don't,
> > > > > everything stays the same. It's really surprising for something
> > > > > that's soldered onto the
> > > board like ME.
> > > >
> > > > HDCP is an application in the ME it's not ME itself..  On the
> > > > linux side HDCP2 is a virtual device  on mei client virtual bus,
> > > > the bus  is teared
> > > down on ME reset, which mostly happen  on power transitions.
> > > > Theoretically,  we could keep it up during power transitions, but
> > > > so fare it was not necessary and second it's not guarantie that
> > > > the all ME
> > > applications will reappear after reset.
> > >
> > > When does this happen that an ME application doesn't come back after e.g.
> > > suspend/resume?
> > No, this can happen in special flows such as  fw updates and error conditions,
> but is has to be supported as well.
> >
> > >
> > > Also, what's all the place where this reset can happen? Just
> > > suspend/resume/hibernate and all these, or also at other times?
> >
> > Also on errors and fw update,  the basic assumption is here that it can happen
> any time.
> 
> If this can happen any time, what are we supposed to do if this happens while
> we're doing something with the hdcp mei? If this is such a common occurence I
> guess we need to somehow wait until everyting is rebound and working again. I
> think ideally mei core would handle that for us, but I guess if this just randomly
> happens then we need to redo all the transactions. So does need some
> involvement of the higher levels.

It's not common occurrence, but the assumption must be it can happen any time,
In that case everything has to restarted as there is no state preserved in the ME FW.
Right MEI core cannot do it for you, it is just a channel, the logic and state of the connection 
is in the mei_hdcp or gfx.   Note that HDCP is not the only App over MEI.

> 
> Also, how likely is it that the hdcp mei will outright disappear and not come
> back after a reset?
> 
> > > How does userspace deal with the reset over s/r? I'm assuming that
> > > at least the device node file will become invalid (or whatever
> > > you're using as userspace api), so if userspace is accessing stuff
> > > on the me at the same time as we do a suspend/resume, what happens?
> 
> Also, answer to how other users handle this would be enlighting.
> 
> > > > > Aside: We'll probably need a device_link to make sure mei_hdcp
> > > > > is fully resumed before i915 gets resumed, but that's kinda a
> > > > > detail for later
> > > on.
> > > >
> > > > Frankly I don’t believe there is currently exact abstraction that
> > > > supports this model, neither components nor device_link .
> > > > So fare we used class interface for other purposes, it worked well.
> > >
> > > I'm not clear on what class interface has to do with component or device
> link.
> > > They all solve different problems, at least as far as I understand all this stuff
> ...
> > > -Daniel
> >
> > It comes instead of it, device_link is mostly used for power
> > management and component as we see know is not what we need as HDCP Is
> a b it volitle.
> > class_interface  gives you two handlers: add and remove device, that's all
> what is needed for the current implementation.
> 
> Well someone needs to handle the volatility of hdcp, and atm we seem to be
> playing a game of pass the bucket. I still think that mei_hdcp should supply a
> clean interface to i915, with all the reset madness handled internally. But
> depending upon how badly this all leaks we might need to have a retry logic in
> the i915 hdcp flow too.


Restart logic is must. 

> 
> device linke we'll probably need anyway, since i915 resuming when hdcp is not
> yet up is not a good idea no matter what's goîng on.

I've explored device_link and I'm not sure it is suitable there is no power relationship, on suspend/resume the device disappear.
I still believe that class_interface is better choice, it this particular case.

The whole issue is not yet resolved in the Linux kernel.
There was a discussion around it in ELC  https://schd.ws/hosted_files/osseu18/0f/deferred_problem.pdf 

Thanks
Tomas

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 103+ messages in thread

* Re: [PATCH v9 02/39] drm: header for i915 - MEI_HDCP interface
  2018-12-13  4:01 ` [PATCH v9 02/39] drm: header for i915 - MEI_HDCP interface Ramalingam C
@ 2018-12-17 11:28   ` Winkler, Tomas
  2018-12-17 13:27     ` Daniel Vetter
  2018-12-19 13:37   ` Daniel Vetter
  1 sibling, 1 reply; 103+ messages in thread
From: Winkler, Tomas @ 2018-12-17 11:28 UTC (permalink / raw)
  To: C, Ramalingam, intel-gfx, dri-devel, seanpaul, daniel.vetter,
	Shankar, Uma

> 
> Header defines the interface for the I915 and MEI_HDCP drivers.
> 
> Signed-off-by: Ramalingam C <ramalingam.c@intel.com>
> ---
>  include/drm/i915_mei_hdcp_interface.h | 132
> ++++++++++++++++++++++++++++++++++
>  1 file changed, 132 insertions(+)
>  create mode 100644 include/drm/i915_mei_hdcp_interface.h
> 
> diff --git a/include/drm/i915_mei_hdcp_interface.h
> b/include/drm/i915_mei_hdcp_interface.h
> new file mode 100644
> index 000000000000..e3b7fb32612a
> --- /dev/null
> +++ b/include/drm/i915_mei_hdcp_interface.h


This should be just 'i915_hdcp_interface.h' 

> @@ -0,0 +1,132 @@
> +/* SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) */
> +/*
> + * Copyright © 2017-2018 Intel Corporation
> + *
> + * Authors:
> + * Ramalingam C <ramalingam.c@intel.com>  */
> +
> +#ifndef _I915_MEI_HDCP_INTERFACE_H_
> +#define _I915_MEI_HDCP_INTERFACE_H_
Drop MEI
> +
> +#include <linux/mutex.h>
> +#include <drm/drm_hdcp.h>
> +
> +/**
> + * enum hdcp_port_type - HDCP port implementation type defined by ME FW
> + * @HDCP_PORT_TYPE_INVALID: Invalid hdcp port type
> + * @HDCP_PORT_TYPE_INTEGRATED: In-Host HDCP2.x port
> + * @HDCP_PORT_TYPE_LSPCON: HDCP2.2 discrete wired Tx port with LSPCON
> + *			   (HDMI 2.0) solution
> + * @HDCP_PORT_TYPE_CPDP: HDCP2.2 discrete wired Tx port using the CPDP
> (DP 1.3)
> + *			 solution
> + */
> +enum hdcp_port_type {
> +	HDCP_PORT_TYPE_INVALID,
> +	HDCP_PORT_TYPE_INTEGRATED,
> +	HDCP_PORT_TYPE_LSPCON,
> +	HDCP_PORT_TYPE_CPDP
> +};
> +
> +/**
> + * enum hdcp_wired_protocol - HDCP adaptation used on the port
> + * @HDCP_PROTOCOL_INVALID: Invalid HDCP adaptation protocol
> + * @HDCP_PROTOCOL_HDMI: HDMI adaptation of HDCP used on the port
> + * @HDCP_PROTOCOL_DP: DP adaptation of HDCP used on the port  */ enum
> +hdcp_wired_protocol {
> +	HDCP_PROTOCOL_INVALID,
> +	HDCP_PROTOCOL_HDMI,
> +	HDCP_PROTOCOL_DP
> +};
> +
> +/**
> + * struct hdcp_port_data - intel specific HDCP port data
> + * @port: port index as per I915
> + * @port_type: HDCP port type as per ME FW classification
> + * @protocol: HDCP adaptation as per ME FW
> + * @k: No of streams transmitted on a port. Only on DP MST this is != 1
> + * @seq_num_m: Count of RepeaterAuth_Stream_Manage msg propagated.
> + *	       Initialized to 0 on AKE_INIT. Incremented after every successful
> + *	       transmission of RepeaterAuth_Stream_Manage message. When it
> rolls
> + *	       over re-Auth has to be triggered.
> + * @streams: struct hdcp2_streamid_type[k]. Defines the type and id for the
> + *	     streams
> + */
> +struct hdcp_port_data {
> +	short int port;
> +	u8 port_type;
> +	u8 protocol;
> +	u16 k;
> +	u32 seq_num_m;
> +	struct hdcp2_streamid_type *streams;
> +};
> +
> +/**
> + * struct i915_hdcp_component_ops- ops for HDCP2.2 services.
> + * @owner: Module providing the ops
> + * @initiate_hdcp2_session: Initiate a Wired HDCP2.2 Tx Session.
> + *			    And Prepare AKE_Init.
> + * @verify_receiver_cert_prepare_km: Verify the Receiver Certificate
> + *				     AKE_Send_Cert and prepare
> +				     AKE_Stored_Km/AKE_No_Stored_Km
> + * @verify_hprime: Verify AKE_Send_H_prime
> + * @store_pairing_info: Store pairing info received
> + * @initiate_locality_check: Prepare LC_Init
> + * @verify_lprime: Verify lprime
> + * @get_session_key: Prepare SKE_Send_Eks
> + * @repeater_check_flow_prepare_ack: Validate the Downstream topology
> + *				     and prepare rep_ack
> + * @verify_mprime: Verify mprime
> + * @enable_hdcp_authentication:  Mark a port as authenticated.
> + * @close_hdcp_session: Close the Wired HDCP Tx session per port.
> + *			This also disables the authenticated state of the port.
> + */
> +struct i915_hdcp_component_ops {
> +	/**
> +	 * @owner: mei_hdcp module
> +	 */
> +	struct module *owner;
> +
> +	int (*initiate_hdcp2_session)(struct device *dev,
> +				      struct hdcp_port_data *data,
> +				      struct hdcp2_ake_init *ake_data);
> +	int (*verify_receiver_cert_prepare_km)(struct device *dev,
> +					       struct hdcp_port_data *data,
> +					       struct hdcp2_ake_send_cert
> +								*rx_cert,
> +					       bool *km_stored,
> +					       struct hdcp2_ake_no_stored_km
> +								*ek_pub_km,
> +					       size_t *msg_sz);
> +	int (*verify_hprime)(struct device *dev,
> +			     struct hdcp_port_data *data,
> +			     struct hdcp2_ake_send_hprime *rx_hprime);
> +	int (*store_pairing_info)(struct device *dev,
> +				  struct hdcp_port_data *data,
> +				  struct hdcp2_ake_send_pairing_info
> +
> 	*pairing_info);
> +	int (*initiate_locality_check)(struct device *dev,
> +				       struct hdcp_port_data *data,
> +				       struct hdcp2_lc_init *lc_init_data);
> +	int (*verify_lprime)(struct device *dev,
> +			     struct hdcp_port_data *data,
> +			     struct hdcp2_lc_send_lprime *rx_lprime);
> +	int (*get_session_key)(struct device *dev,
> +			       struct hdcp_port_data *data,
> +			       struct hdcp2_ske_send_eks *ske_data);
> +	int (*repeater_check_flow_prepare_ack)(struct device *dev,
> +					       struct hdcp_port_data *data,
> +					       struct
> hdcp2_rep_send_receiverid_list
> +
> 	*rep_topology,
> +					       struct hdcp2_rep_send_ack
> +
> 	*rep_send_ack);
> +	int (*verify_mprime)(struct device *dev,
> +			     struct hdcp_port_data *data,
> +			     struct hdcp2_rep_stream_ready *stream_ready);
> +	int (*enable_hdcp_authentication)(struct device *dev,
> +					  struct hdcp_port_data *data);
> +	int (*close_hdcp_session)(struct device *dev,
> +				  struct hdcp_port_data *data);
> +};
> +#endif /* _I915_MEI_HDCP_NTERFACE_H_ */
DROP MEI
> 2.7.4

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 103+ messages in thread

* Re: [PATCH v9 02/39] drm: header for i915 - MEI_HDCP interface
  2018-12-17 11:28   ` Winkler, Tomas
@ 2018-12-17 13:27     ` Daniel Vetter
  2018-12-17 13:42       ` Winkler, Tomas
  0 siblings, 1 reply; 103+ messages in thread
From: Daniel Vetter @ 2018-12-17 13:27 UTC (permalink / raw)
  To: Winkler, Tomas; +Cc: intel-gfx, dri-devel, Shankar, Uma, seanpaul

On Mon, Dec 17, 2018 at 12:28 PM Winkler, Tomas <tomas.winkler@intel.com> wrote:
>
> >
> > Header defines the interface for the I915 and MEI_HDCP drivers.
> >
> > Signed-off-by: Ramalingam C <ramalingam.c@intel.com>
> > ---
> >  include/drm/i915_mei_hdcp_interface.h | 132
> > ++++++++++++++++++++++++++++++++++
> >  1 file changed, 132 insertions(+)
> >  create mode 100644 include/drm/i915_mei_hdcp_interface.h
> >
> > diff --git a/include/drm/i915_mei_hdcp_interface.h
> > b/include/drm/i915_mei_hdcp_interface.h
> > new file mode 100644
> > index 000000000000..e3b7fb32612a
> > --- /dev/null
> > +++ b/include/drm/i915_mei_hdcp_interface.h
>
>
> This should be just 'i915_hdcp_interface.h'

We have other hdcp engines than the mei one. Discrete gpus will
definitely get a differnt hdcp2 engine even, can't rely on ME for
those. Keeping mei in the names to make that clear makes sense to me,
removing it would just cause more confusion I think.

We already had the entire "should we have a common hdcp interface in
drm" discussion when we orginally landed this, and looking at all the
intel and non-intel implementations floating around that didn't make
sense, due to lack of comonality of how things flow and interact with
the hdmi/dp ports.
-Daniel

>
> > @@ -0,0 +1,132 @@
> > +/* SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) */
> > +/*
> > + * Copyright © 2017-2018 Intel Corporation
> > + *
> > + * Authors:
> > + * Ramalingam C <ramalingam.c@intel.com>  */
> > +
> > +#ifndef _I915_MEI_HDCP_INTERFACE_H_
> > +#define _I915_MEI_HDCP_INTERFACE_H_
> Drop MEI
> > +
> > +#include <linux/mutex.h>
> > +#include <drm/drm_hdcp.h>
> > +
> > +/**
> > + * enum hdcp_port_type - HDCP port implementation type defined by ME FW
> > + * @HDCP_PORT_TYPE_INVALID: Invalid hdcp port type
> > + * @HDCP_PORT_TYPE_INTEGRATED: In-Host HDCP2.x port
> > + * @HDCP_PORT_TYPE_LSPCON: HDCP2.2 discrete wired Tx port with LSPCON
> > + *                      (HDMI 2.0) solution
> > + * @HDCP_PORT_TYPE_CPDP: HDCP2.2 discrete wired Tx port using the CPDP
> > (DP 1.3)
> > + *                    solution
> > + */
> > +enum hdcp_port_type {
> > +     HDCP_PORT_TYPE_INVALID,
> > +     HDCP_PORT_TYPE_INTEGRATED,
> > +     HDCP_PORT_TYPE_LSPCON,
> > +     HDCP_PORT_TYPE_CPDP
> > +};
> > +
> > +/**
> > + * enum hdcp_wired_protocol - HDCP adaptation used on the port
> > + * @HDCP_PROTOCOL_INVALID: Invalid HDCP adaptation protocol
> > + * @HDCP_PROTOCOL_HDMI: HDMI adaptation of HDCP used on the port
> > + * @HDCP_PROTOCOL_DP: DP adaptation of HDCP used on the port  */ enum
> > +hdcp_wired_protocol {
> > +     HDCP_PROTOCOL_INVALID,
> > +     HDCP_PROTOCOL_HDMI,
> > +     HDCP_PROTOCOL_DP
> > +};
> > +
> > +/**
> > + * struct hdcp_port_data - intel specific HDCP port data
> > + * @port: port index as per I915
> > + * @port_type: HDCP port type as per ME FW classification
> > + * @protocol: HDCP adaptation as per ME FW
> > + * @k: No of streams transmitted on a port. Only on DP MST this is != 1
> > + * @seq_num_m: Count of RepeaterAuth_Stream_Manage msg propagated.
> > + *          Initialized to 0 on AKE_INIT. Incremented after every successful
> > + *          transmission of RepeaterAuth_Stream_Manage message. When it
> > rolls
> > + *          over re-Auth has to be triggered.
> > + * @streams: struct hdcp2_streamid_type[k]. Defines the type and id for the
> > + *        streams
> > + */
> > +struct hdcp_port_data {
> > +     short int port;
> > +     u8 port_type;
> > +     u8 protocol;
> > +     u16 k;
> > +     u32 seq_num_m;
> > +     struct hdcp2_streamid_type *streams;
> > +};
> > +
> > +/**
> > + * struct i915_hdcp_component_ops- ops for HDCP2.2 services.
> > + * @owner: Module providing the ops
> > + * @initiate_hdcp2_session: Initiate a Wired HDCP2.2 Tx Session.
> > + *                       And Prepare AKE_Init.
> > + * @verify_receiver_cert_prepare_km: Verify the Receiver Certificate
> > + *                                AKE_Send_Cert and prepare
> > +                                  AKE_Stored_Km/AKE_No_Stored_Km
> > + * @verify_hprime: Verify AKE_Send_H_prime
> > + * @store_pairing_info: Store pairing info received
> > + * @initiate_locality_check: Prepare LC_Init
> > + * @verify_lprime: Verify lprime
> > + * @get_session_key: Prepare SKE_Send_Eks
> > + * @repeater_check_flow_prepare_ack: Validate the Downstream topology
> > + *                                and prepare rep_ack
> > + * @verify_mprime: Verify mprime
> > + * @enable_hdcp_authentication:  Mark a port as authenticated.
> > + * @close_hdcp_session: Close the Wired HDCP Tx session per port.
> > + *                   This also disables the authenticated state of the port.
> > + */
> > +struct i915_hdcp_component_ops {
> > +     /**
> > +      * @owner: mei_hdcp module
> > +      */
> > +     struct module *owner;
> > +
> > +     int (*initiate_hdcp2_session)(struct device *dev,
> > +                                   struct hdcp_port_data *data,
> > +                                   struct hdcp2_ake_init *ake_data);
> > +     int (*verify_receiver_cert_prepare_km)(struct device *dev,
> > +                                            struct hdcp_port_data *data,
> > +                                            struct hdcp2_ake_send_cert
> > +                                                             *rx_cert,
> > +                                            bool *km_stored,
> > +                                            struct hdcp2_ake_no_stored_km
> > +                                                             *ek_pub_km,
> > +                                            size_t *msg_sz);
> > +     int (*verify_hprime)(struct device *dev,
> > +                          struct hdcp_port_data *data,
> > +                          struct hdcp2_ake_send_hprime *rx_hprime);
> > +     int (*store_pairing_info)(struct device *dev,
> > +                               struct hdcp_port_data *data,
> > +                               struct hdcp2_ake_send_pairing_info
> > +
> >       *pairing_info);
> > +     int (*initiate_locality_check)(struct device *dev,
> > +                                    struct hdcp_port_data *data,
> > +                                    struct hdcp2_lc_init *lc_init_data);
> > +     int (*verify_lprime)(struct device *dev,
> > +                          struct hdcp_port_data *data,
> > +                          struct hdcp2_lc_send_lprime *rx_lprime);
> > +     int (*get_session_key)(struct device *dev,
> > +                            struct hdcp_port_data *data,
> > +                            struct hdcp2_ske_send_eks *ske_data);
> > +     int (*repeater_check_flow_prepare_ack)(struct device *dev,
> > +                                            struct hdcp_port_data *data,
> > +                                            struct
> > hdcp2_rep_send_receiverid_list
> > +
> >       *rep_topology,
> > +                                            struct hdcp2_rep_send_ack
> > +
> >       *rep_send_ack);
> > +     int (*verify_mprime)(struct device *dev,
> > +                          struct hdcp_port_data *data,
> > +                          struct hdcp2_rep_stream_ready *stream_ready);
> > +     int (*enable_hdcp_authentication)(struct device *dev,
> > +                                       struct hdcp_port_data *data);
> > +     int (*close_hdcp_session)(struct device *dev,
> > +                               struct hdcp_port_data *data);
> > +};
> > +#endif /* _I915_MEI_HDCP_NTERFACE_H_ */
> DROP MEI
> > 2.7.4
>


-- 
Daniel Vetter
Software Engineer, Intel Corporation
+41 (0) 79 365 57 48 - http://blog.ffwll.ch
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 103+ messages in thread

* Re: [PATCH v9 02/39] drm: header for i915 - MEI_HDCP interface
  2018-12-17 13:27     ` Daniel Vetter
@ 2018-12-17 13:42       ` Winkler, Tomas
  2018-12-17 13:59         ` Daniel Vetter
  0 siblings, 1 reply; 103+ messages in thread
From: Winkler, Tomas @ 2018-12-17 13:42 UTC (permalink / raw)
  To: Daniel Vetter; +Cc: intel-gfx, dri-devel, seanpaul

> 
> On Mon, Dec 17, 2018 at 12:28 PM Winkler, Tomas
> <tomas.winkler@intel.com> wrote:
> >
> > >
> > > Header defines the interface for the I915 and MEI_HDCP drivers.
> > >
> > > Signed-off-by: Ramalingam C <ramalingam.c@intel.com>
> > > ---
> > >  include/drm/i915_mei_hdcp_interface.h | 132
> > > ++++++++++++++++++++++++++++++++++
> > >  1 file changed, 132 insertions(+)
> > >  create mode 100644 include/drm/i915_mei_hdcp_interface.h
> > >
> > > diff --git a/include/drm/i915_mei_hdcp_interface.h
> > > b/include/drm/i915_mei_hdcp_interface.h
> > > new file mode 100644
> > > index 000000000000..e3b7fb32612a
> > > --- /dev/null
> > > +++ b/include/drm/i915_mei_hdcp_interface.h
> >
> >
> > This should be just 'i915_hdcp_interface.h'
> 
> We have other hdcp engines than the mei one. Discrete gpus will definitely get
> a differnt hdcp2 engine even, can't rely on ME for those. Keeping mei in the
> names to make that clear makes sense to me, removing it would just cause
> more confusion I think.

We would like to create a DHCP interface and hold the specific implementation w/o hdcp_mei  

> 
> We already had the entire "should we have a common hdcp interface in drm"
> discussion when we orginally landed this, and looking at all the intel and non-
> intel implementations floating around that didn't make sense, due to lack of
> comonality of how things flow and interact with the hdmi/dp ports.
> -Daniel

Sorry, was not part of that discussion, though it looks strange to me as the DHCP is a standard no Intel invention. 

> 
> >
> > > @@ -0,0 +1,132 @@
> > > +/* SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) */
> > > +/*
> > > + * Copyright © 2017-2018 Intel Corporation
> > > + *
> > > + * Authors:
> > > + * Ramalingam C <ramalingam.c@intel.com>  */
> > > +
> > > +#ifndef _I915_MEI_HDCP_INTERFACE_H_ #define
> > > +_I915_MEI_HDCP_INTERFACE_H_
> > Drop MEI
> > > +
> > > +#include <linux/mutex.h>
> > > +#include <drm/drm_hdcp.h>
> > > +
> > > +/**
> > > + * enum hdcp_port_type - HDCP port implementation type defined by
> > > +ME FW
> > > + * @HDCP_PORT_TYPE_INVALID: Invalid hdcp port type
> > > + * @HDCP_PORT_TYPE_INTEGRATED: In-Host HDCP2.x port
> > > + * @HDCP_PORT_TYPE_LSPCON: HDCP2.2 discrete wired Tx port with
> LSPCON
> > > + *                      (HDMI 2.0) solution
> > > + * @HDCP_PORT_TYPE_CPDP: HDCP2.2 discrete wired Tx port using the
> > > +CPDP
> > > (DP 1.3)
> > > + *                    solution
> > > + */
> > > +enum hdcp_port_type {
> > > +     HDCP_PORT_TYPE_INVALID,
> > > +     HDCP_PORT_TYPE_INTEGRATED,
> > > +     HDCP_PORT_TYPE_LSPCON,
> > > +     HDCP_PORT_TYPE_CPDP
> > > +};
> > > +
> > > +/**
> > > + * enum hdcp_wired_protocol - HDCP adaptation used on the port
> > > + * @HDCP_PROTOCOL_INVALID: Invalid HDCP adaptation protocol
> > > + * @HDCP_PROTOCOL_HDMI: HDMI adaptation of HDCP used on the port
> > > + * @HDCP_PROTOCOL_DP: DP adaptation of HDCP used on the port  */
> > > +enum hdcp_wired_protocol {
> > > +     HDCP_PROTOCOL_INVALID,
> > > +     HDCP_PROTOCOL_HDMI,
> > > +     HDCP_PROTOCOL_DP
> > > +};
> > > +
> > > +/**
> > > + * struct hdcp_port_data - intel specific HDCP port data
> > > + * @port: port index as per I915
> > > + * @port_type: HDCP port type as per ME FW classification
> > > + * @protocol: HDCP adaptation as per ME FW
> > > + * @k: No of streams transmitted on a port. Only on DP MST this is
> > > +!= 1
> > > + * @seq_num_m: Count of RepeaterAuth_Stream_Manage msg
> propagated.
> > > + *          Initialized to 0 on AKE_INIT. Incremented after every successful
> > > + *          transmission of RepeaterAuth_Stream_Manage message. When it
> > > rolls
> > > + *          over re-Auth has to be triggered.
> > > + * @streams: struct hdcp2_streamid_type[k]. Defines the type and id for
> the
> > > + *        streams
> > > + */
> > > +struct hdcp_port_data {
> > > +     short int port;
> > > +     u8 port_type;
> > > +     u8 protocol;
> > > +     u16 k;
> > > +     u32 seq_num_m;
> > > +     struct hdcp2_streamid_type *streams; };
> > > +
> > > +/**
> > > + * struct i915_hdcp_component_ops- ops for HDCP2.2 services.
> > > + * @owner: Module providing the ops
> > > + * @initiate_hdcp2_session: Initiate a Wired HDCP2.2 Tx Session.
> > > + *                       And Prepare AKE_Init.
> > > + * @verify_receiver_cert_prepare_km: Verify the Receiver Certificate
> > > + *                                AKE_Send_Cert and prepare
> > > +                                  AKE_Stored_Km/AKE_No_Stored_Km
> > > + * @verify_hprime: Verify AKE_Send_H_prime
> > > + * @store_pairing_info: Store pairing info received
> > > + * @initiate_locality_check: Prepare LC_Init
> > > + * @verify_lprime: Verify lprime
> > > + * @get_session_key: Prepare SKE_Send_Eks
> > > + * @repeater_check_flow_prepare_ack: Validate the Downstream
> topology
> > > + *                                and prepare rep_ack
> > > + * @verify_mprime: Verify mprime
> > > + * @enable_hdcp_authentication:  Mark a port as authenticated.
> > > + * @close_hdcp_session: Close the Wired HDCP Tx session per port.
> > > + *                   This also disables the authenticated state of the port.
> > > + */
> > > +struct i915_hdcp_component_ops {
> > > +     /**
> > > +      * @owner: mei_hdcp module
> > > +      */
> > > +     struct module *owner;
> > > +
> > > +     int (*initiate_hdcp2_session)(struct device *dev,
> > > +                                   struct hdcp_port_data *data,
> > > +                                   struct hdcp2_ake_init *ake_data);
> > > +     int (*verify_receiver_cert_prepare_km)(struct device *dev,
> > > +                                            struct hdcp_port_data *data,
> > > +                                            struct hdcp2_ake_send_cert
> > > +                                                             *rx_cert,
> > > +                                            bool *km_stored,
> > > +                                            struct hdcp2_ake_no_stored_km
> > > +                                                             *ek_pub_km,
> > > +                                            size_t *msg_sz);
> > > +     int (*verify_hprime)(struct device *dev,
> > > +                          struct hdcp_port_data *data,
> > > +                          struct hdcp2_ake_send_hprime *rx_hprime);
> > > +     int (*store_pairing_info)(struct device *dev,
> > > +                               struct hdcp_port_data *data,
> > > +                               struct hdcp2_ake_send_pairing_info
> > > +
> > >       *pairing_info);
> > > +     int (*initiate_locality_check)(struct device *dev,
> > > +                                    struct hdcp_port_data *data,
> > > +                                    struct hdcp2_lc_init *lc_init_data);
> > > +     int (*verify_lprime)(struct device *dev,
> > > +                          struct hdcp_port_data *data,
> > > +                          struct hdcp2_lc_send_lprime *rx_lprime);
> > > +     int (*get_session_key)(struct device *dev,
> > > +                            struct hdcp_port_data *data,
> > > +                            struct hdcp2_ske_send_eks *ske_data);
> > > +     int (*repeater_check_flow_prepare_ack)(struct device *dev,
> > > +                                            struct hdcp_port_data *data,
> > > +                                            struct
> > > hdcp2_rep_send_receiverid_list
> > > +
> > >       *rep_topology,
> > > +                                            struct
> > > + hdcp2_rep_send_ack
> > > +
> > >       *rep_send_ack);
> > > +     int (*verify_mprime)(struct device *dev,
> > > +                          struct hdcp_port_data *data,
> > > +                          struct hdcp2_rep_stream_ready *stream_ready);
> > > +     int (*enable_hdcp_authentication)(struct device *dev,
> > > +                                       struct hdcp_port_data *data);
> > > +     int (*close_hdcp_session)(struct device *dev,
> > > +                               struct hdcp_port_data *data); };
> > > +#endif /* _I915_MEI_HDCP_NTERFACE_H_ */
> > DROP MEI
> > > 2.7.4
> >
> 
> 
> --
> Daniel Vetter
> Software Engineer, Intel Corporation
> +41 (0) 79 365 57 48 - http://blog.ffwll.ch
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 103+ messages in thread

* Re: [PATCH v9 35/39] misc/mei/hdcp: Component framework for I915 Interface
  2018-12-17 10:57               ` Winkler, Tomas
@ 2018-12-17 13:46                 ` Daniel Vetter
  2018-12-19  6:45                   ` C, Ramalingam
  0 siblings, 1 reply; 103+ messages in thread
From: Daniel Vetter @ 2018-12-17 13:46 UTC (permalink / raw)
  To: Winkler, Tomas
  Cc: Rafael J. Wysocki, intel-gfx, dri-devel, Shankar, Uma, Sean Paul,
	Greg KH

On Mon, Dec 17, 2018 at 11:57 AM Winkler, Tomas <tomas.winkler@intel.com> wrote:
>
>
> > On Sat, Dec 15, 2018 at 09:20:38PM +0000, Winkler, Tomas wrote:
> > > >
> > > > On Thu, Dec 13, 2018 at 5:27 PM Winkler, Tomas
> > > > <tomas.winkler@intel.com>
> > > > wrote:
> > > > >
> > > > > > On Thu, Dec 13, 2018 at 1:36 PM C, Ramalingam
> > > > > > <ramalingam.c@intel.com>
> > > > > > wrote:
> > > > > > >
> > > > > > > Tomas and Daniel,
> > > > > > >
> > > > > > > We got an issue here.
> > > > > > >
> > > > > > > The relationship that we try to build between I915 and
> > > > > > > mei_hdcp is as
> > > > follows:
> > > > > > >
> > > > > > > We are using the components to establish the relationship.
> > > > > > > I915 is component master where as mei_hdcp is component.
> > > > > > > I915 adds the component master during the module load.
> > > > > > > mei_hdcp adds the
> > > > > > component when the driver->probe is called (on device driver binding).
> > > > > > > I915 forces itself such that until mei_hdcp component is added
> > > > > > > I915_load
> > > > > > wont be complete.
> > > > > > > Similarly on complete system, if mei_hdcp component is
> > > > > > > removed,
> > > > > > immediately I915 unregister itself and HW will be shutdown.
> > > > > > >
> > > > > > > This is completely fine when the modules are loaded and unloaded.
> > > > > > >
> > > > > > > But during suspend, mei device disappears and mei bus handles
> > > > > > > it by
> > > > > > unbinding device and driver by calling driver->remove.
> > > > > > > This in-turn removes the component and triggers the master
> > > > > > > unbind of I915
> > > > > > where, I915 unregister itself.
> > > > > > > This cause the HW state mismatch during the suspend and resume.
> > > > > > >
> > > > > > > Please check the powerwell mismatch errors at CI report for v9
> > > > > > > https://intel-gfx-ci.01.org/tree/drm-tip/Trybot_3412/fi-glk-j4
> > > > > > > 005/
> > > > > > > igt@
> > > > > > > gem_exec_suspend@basic-s3.html
> > > > > > >
> > > > > > > More over unregistering I915 during the suspend is not expected.
> > > > > > > So how do
> > > > > > we handle this?
> > > > > >
> > > > > > Bit more context from our irc discussion with Ram:
> > > > > >
> > > > > > I found this very surprising, since I don't know of any other
> > > > > > subsystems where the devices get outright removed when going
> > > > > > through a
> > > > suspend/resume cycle.
> > > > > > The device model was built to handle this stuff
> > > > > > correctly: First clients/devices/interfaces get suspend, then
> > > > > > the parent/bridge/bus. Same dance in reverse when resuming. This
> > > > > > even holds for lots of hotpluggable buses, where child devices
> > > > > > could indeed disappear on resume, but as long as they don't,
> > > > > > everything stays the same. It's really surprising for something
> > > > > > that's soldered onto the
> > > > board like ME.
> > > > >
> > > > > HDCP is an application in the ME it's not ME itself..  On the
> > > > > linux side HDCP2 is a virtual device  on mei client virtual bus,
> > > > > the bus  is teared
> > > > down on ME reset, which mostly happen  on power transitions.
> > > > > Theoretically,  we could keep it up during power transitions, but
> > > > > so fare it was not necessary and second it's not guarantie that
> > > > > the all ME
> > > > applications will reappear after reset.
> > > >
> > > > When does this happen that an ME application doesn't come back after e.g.
> > > > suspend/resume?
> > > No, this can happen in special flows such as  fw updates and error conditions,
> > but is has to be supported as well.
> > >
> > > >
> > > > Also, what's all the place where this reset can happen? Just
> > > > suspend/resume/hibernate and all these, or also at other times?
> > >
> > > Also on errors and fw update,  the basic assumption is here that it can happen
> > any time.
> >
> > If this can happen any time, what are we supposed to do if this happens while
> > we're doing something with the hdcp mei? If this is such a common occurence I
> > guess we need to somehow wait until everyting is rebound and working again. I
> > think ideally mei core would handle that for us, but I guess if this just randomly
> > happens then we need to redo all the transactions. So does need some
> > involvement of the higher levels.
>
> It's not common occurrence, but the assumption must be it can happen any time,
> In that case everything has to restarted as there is no state preserved in the ME FW.
> Right MEI core cannot do it for you, it is just a channel, the logic and state of the connection
> is in the mei_hdcp or gfx.   Note that HDCP is not the only App over MEI.

Yes, each mei interface would need to provide suspend/resume
functions, or something like that. Or at least a reset function.

> > Also, how likely is it that the hdcp mei will outright disappear and not come
> > back after a reset?
> >
> > > > How does userspace deal with the reset over s/r? I'm assuming that
> > > > at least the device node file will become invalid (or whatever
> > > > you're using as userspace api), so if userspace is accessing stuff
> > > > on the me at the same time as we do a suspend/resume, what happens?
> >
> > Also, answer to how other users handle this would be enlighting.

Still looking to understand this here.

> > > > > > Aside: We'll probably need a device_link to make sure mei_hdcp
> > > > > > is fully resumed before i915 gets resumed, but that's kinda a
> > > > > > detail for later
> > > > on.
> > > > >
> > > > > Frankly I don’t believe there is currently exact abstraction that
> > > > > supports this model, neither components nor device_link .
> > > > > So fare we used class interface for other purposes, it worked well.
> > > >
> > > > I'm not clear on what class interface has to do with component or device
> > link.
> > > > They all solve different problems, at least as far as I understand all this stuff
> > ...
> > > > -Daniel
> > >
> > > It comes instead of it, device_link is mostly used for power
> > > management and component as we see know is not what we need as HDCP Is
> > a b it volitle.
> > > class_interface  gives you two handlers: add and remove device, that's all
> > what is needed for the current implementation.
> >
> > Well someone needs to handle the volatility of hdcp, and atm we seem to be
> > playing a game of pass the bucket. I still think that mei_hdcp should supply a
> > clean interface to i915, with all the reset madness handled internally. But
> > depending upon how badly this all leaks we might need to have a retry logic in
> > the i915 hdcp flow too.
>
>
> Restart logic is must.

Ok, I guess then we need to wrap another layer on top of mei to make
this happen.

Does mei provide any signal whether a client/app has not survived a
reset? Atm there's not way for us to tell a reset apart from a
"mei_hdcp disappared for good" event. Which we kinda need to do.
Ideally a reset would be a distinct event and not implemented as an
unbind/rebind cycle like it currently is.

> > device linke we'll probably need anyway, since i915 resuming when hdcp is not
> > yet up is not a good idea no matter what's goîng on.
>
> I've explored device_link and I'm not sure it is suitable there is no power relationship, on suspend/resume the device disappear.
> I still believe that class_interface is better choice, it this particular case.

I'm not sure what you mean with class_interface here. How are we
supposed to use that in this case here? I'm not following you at all
here.

I also noticed that resume seems to be entirely deferred to workers:
mei_restart only writes the me start command through the hbm. So all
the clients will only be re-registered somewhen later on through an
async worker (in the rescan_work). Is that understanding correct? If
that's the case we'd need a way to wait for that, so we know whether
the mei_hdcp is useable again or has disappeared for good.

> The whole issue is not yet resolved in the Linux kernel.
> There was a discussion around it in ELC  https://schd.ws/hosted_files/osseu18/0f/deferred_problem.pdf

There's still a bunch of open issues around deferred probe and device
driver loading, but none that would interfer with what we're trying to
do here. At least if mei wouldn't handle resets through a bind/unbind
cycle.
-Daniel

>
> Thanks
> Tomas
>


-- 
Daniel Vetter
Software Engineer, Intel Corporation
+41 (0) 79 365 57 48 - http://blog.ffwll.ch
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 103+ messages in thread

* Re: [PATCH v9 02/39] drm: header for i915 - MEI_HDCP interface
  2018-12-17 13:42       ` Winkler, Tomas
@ 2018-12-17 13:59         ` Daniel Vetter
  0 siblings, 0 replies; 103+ messages in thread
From: Daniel Vetter @ 2018-12-17 13:59 UTC (permalink / raw)
  To: Winkler, Tomas; +Cc: intel-gfx, dri-devel, seanpaul

On Mon, Dec 17, 2018 at 2:42 PM Winkler, Tomas <tomas.winkler@intel.com> wrote:
>
> >
> > On Mon, Dec 17, 2018 at 12:28 PM Winkler, Tomas
> > <tomas.winkler@intel.com> wrote:
> > >
> > > >
> > > > Header defines the interface for the I915 and MEI_HDCP drivers.
> > > >
> > > > Signed-off-by: Ramalingam C <ramalingam.c@intel.com>
> > > > ---
> > > >  include/drm/i915_mei_hdcp_interface.h | 132
> > > > ++++++++++++++++++++++++++++++++++
> > > >  1 file changed, 132 insertions(+)
> > > >  create mode 100644 include/drm/i915_mei_hdcp_interface.h
> > > >
> > > > diff --git a/include/drm/i915_mei_hdcp_interface.h
> > > > b/include/drm/i915_mei_hdcp_interface.h
> > > > new file mode 100644
> > > > index 000000000000..e3b7fb32612a
> > > > --- /dev/null
> > > > +++ b/include/drm/i915_mei_hdcp_interface.h
> > >
> > >
> > > This should be just 'i915_hdcp_interface.h'
> >
> > We have other hdcp engines than the mei one. Discrete gpus will definitely get
> > a differnt hdcp2 engine even, can't rely on ME for those. Keeping mei in the
> > names to make that clear makes sense to me, removing it would just cause
> > more confusion I think.
>
> We would like to create a DHCP interface and hold the specific implementation w/o hdcp_mei

mei_hdcp is only part of the hw interface, the other part is setting
the right bits at the right time on the i915 side (afaiui ME has a
priviledge hw channel to hand the key over to the display hw). Only
the overall thing implements hdcp.

> > We already had the entire "should we have a common hdcp interface in drm"
> > discussion when we orginally landed this, and looking at all the intel and non-
> > intel implementations floating around that didn't make sense, due to lack of
> > comonality of how things flow and interact with the hdmi/dp ports.
> > -Daniel
>
> Sorry, was not part of that discussion, though it looks strange to me as the DHCP is a standard no Intel invention.

The stuff going over the wire is a standard, and we have a header for
those bits in drm_hdcp.h. The programming interface exposed by the
hardware isn't standardized. We do share some code in the i915 driver,
because a bunch of things work the same way across hdcd1/mei_hdcp and
dp/hdmi, but that's about it.
-Daniel

>
> >
> > >
> > > > @@ -0,0 +1,132 @@
> > > > +/* SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) */
> > > > +/*
> > > > + * Copyright © 2017-2018 Intel Corporation
> > > > + *
> > > > + * Authors:
> > > > + * Ramalingam C <ramalingam.c@intel.com>  */
> > > > +
> > > > +#ifndef _I915_MEI_HDCP_INTERFACE_H_ #define
> > > > +_I915_MEI_HDCP_INTERFACE_H_
> > > Drop MEI
> > > > +
> > > > +#include <linux/mutex.h>
> > > > +#include <drm/drm_hdcp.h>
> > > > +
> > > > +/**
> > > > + * enum hdcp_port_type - HDCP port implementation type defined by
> > > > +ME FW
> > > > + * @HDCP_PORT_TYPE_INVALID: Invalid hdcp port type
> > > > + * @HDCP_PORT_TYPE_INTEGRATED: In-Host HDCP2.x port
> > > > + * @HDCP_PORT_TYPE_LSPCON: HDCP2.2 discrete wired Tx port with
> > LSPCON
> > > > + *                      (HDMI 2.0) solution
> > > > + * @HDCP_PORT_TYPE_CPDP: HDCP2.2 discrete wired Tx port using the
> > > > +CPDP
> > > > (DP 1.3)
> > > > + *                    solution
> > > > + */
> > > > +enum hdcp_port_type {
> > > > +     HDCP_PORT_TYPE_INVALID,
> > > > +     HDCP_PORT_TYPE_INTEGRATED,
> > > > +     HDCP_PORT_TYPE_LSPCON,
> > > > +     HDCP_PORT_TYPE_CPDP
> > > > +};
> > > > +
> > > > +/**
> > > > + * enum hdcp_wired_protocol - HDCP adaptation used on the port
> > > > + * @HDCP_PROTOCOL_INVALID: Invalid HDCP adaptation protocol
> > > > + * @HDCP_PROTOCOL_HDMI: HDMI adaptation of HDCP used on the port
> > > > + * @HDCP_PROTOCOL_DP: DP adaptation of HDCP used on the port  */
> > > > +enum hdcp_wired_protocol {
> > > > +     HDCP_PROTOCOL_INVALID,
> > > > +     HDCP_PROTOCOL_HDMI,
> > > > +     HDCP_PROTOCOL_DP
> > > > +};
> > > > +
> > > > +/**
> > > > + * struct hdcp_port_data - intel specific HDCP port data
> > > > + * @port: port index as per I915
> > > > + * @port_type: HDCP port type as per ME FW classification
> > > > + * @protocol: HDCP adaptation as per ME FW
> > > > + * @k: No of streams transmitted on a port. Only on DP MST this is
> > > > +!= 1
> > > > + * @seq_num_m: Count of RepeaterAuth_Stream_Manage msg
> > propagated.
> > > > + *          Initialized to 0 on AKE_INIT. Incremented after every successful
> > > > + *          transmission of RepeaterAuth_Stream_Manage message. When it
> > > > rolls
> > > > + *          over re-Auth has to be triggered.
> > > > + * @streams: struct hdcp2_streamid_type[k]. Defines the type and id for
> > the
> > > > + *        streams
> > > > + */
> > > > +struct hdcp_port_data {
> > > > +     short int port;
> > > > +     u8 port_type;
> > > > +     u8 protocol;
> > > > +     u16 k;
> > > > +     u32 seq_num_m;
> > > > +     struct hdcp2_streamid_type *streams; };
> > > > +
> > > > +/**
> > > > + * struct i915_hdcp_component_ops- ops for HDCP2.2 services.
> > > > + * @owner: Module providing the ops
> > > > + * @initiate_hdcp2_session: Initiate a Wired HDCP2.2 Tx Session.
> > > > + *                       And Prepare AKE_Init.
> > > > + * @verify_receiver_cert_prepare_km: Verify the Receiver Certificate
> > > > + *                                AKE_Send_Cert and prepare
> > > > +                                  AKE_Stored_Km/AKE_No_Stored_Km
> > > > + * @verify_hprime: Verify AKE_Send_H_prime
> > > > + * @store_pairing_info: Store pairing info received
> > > > + * @initiate_locality_check: Prepare LC_Init
> > > > + * @verify_lprime: Verify lprime
> > > > + * @get_session_key: Prepare SKE_Send_Eks
> > > > + * @repeater_check_flow_prepare_ack: Validate the Downstream
> > topology
> > > > + *                                and prepare rep_ack
> > > > + * @verify_mprime: Verify mprime
> > > > + * @enable_hdcp_authentication:  Mark a port as authenticated.
> > > > + * @close_hdcp_session: Close the Wired HDCP Tx session per port.
> > > > + *                   This also disables the authenticated state of the port.
> > > > + */
> > > > +struct i915_hdcp_component_ops {
> > > > +     /**
> > > > +      * @owner: mei_hdcp module
> > > > +      */
> > > > +     struct module *owner;
> > > > +
> > > > +     int (*initiate_hdcp2_session)(struct device *dev,
> > > > +                                   struct hdcp_port_data *data,
> > > > +                                   struct hdcp2_ake_init *ake_data);
> > > > +     int (*verify_receiver_cert_prepare_km)(struct device *dev,
> > > > +                                            struct hdcp_port_data *data,
> > > > +                                            struct hdcp2_ake_send_cert
> > > > +                                                             *rx_cert,
> > > > +                                            bool *km_stored,
> > > > +                                            struct hdcp2_ake_no_stored_km
> > > > +                                                             *ek_pub_km,
> > > > +                                            size_t *msg_sz);
> > > > +     int (*verify_hprime)(struct device *dev,
> > > > +                          struct hdcp_port_data *data,
> > > > +                          struct hdcp2_ake_send_hprime *rx_hprime);
> > > > +     int (*store_pairing_info)(struct device *dev,
> > > > +                               struct hdcp_port_data *data,
> > > > +                               struct hdcp2_ake_send_pairing_info
> > > > +
> > > >       *pairing_info);
> > > > +     int (*initiate_locality_check)(struct device *dev,
> > > > +                                    struct hdcp_port_data *data,
> > > > +                                    struct hdcp2_lc_init *lc_init_data);
> > > > +     int (*verify_lprime)(struct device *dev,
> > > > +                          struct hdcp_port_data *data,
> > > > +                          struct hdcp2_lc_send_lprime *rx_lprime);
> > > > +     int (*get_session_key)(struct device *dev,
> > > > +                            struct hdcp_port_data *data,
> > > > +                            struct hdcp2_ske_send_eks *ske_data);
> > > > +     int (*repeater_check_flow_prepare_ack)(struct device *dev,
> > > > +                                            struct hdcp_port_data *data,
> > > > +                                            struct
> > > > hdcp2_rep_send_receiverid_list
> > > > +
> > > >       *rep_topology,
> > > > +                                            struct
> > > > + hdcp2_rep_send_ack
> > > > +
> > > >       *rep_send_ack);
> > > > +     int (*verify_mprime)(struct device *dev,
> > > > +                          struct hdcp_port_data *data,
> > > > +                          struct hdcp2_rep_stream_ready *stream_ready);
> > > > +     int (*enable_hdcp_authentication)(struct device *dev,
> > > > +                                       struct hdcp_port_data *data);
> > > > +     int (*close_hdcp_session)(struct device *dev,
> > > > +                               struct hdcp_port_data *data); };
> > > > +#endif /* _I915_MEI_HDCP_NTERFACE_H_ */
> > > DROP MEI
> > > > 2.7.4
> > >
> >
> >
> > --
> > Daniel Vetter
> > Software Engineer, Intel Corporation
> > +41 (0) 79 365 57 48 - http://blog.ffwll.ch



-- 
Daniel Vetter
Software Engineer, Intel Corporation
+41 (0) 79 365 57 48 - http://blog.ffwll.ch
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 103+ messages in thread

* Re: [PATCH v9 35/39] misc/mei/hdcp: Component framework for I915 Interface
  2018-12-17 13:46                 ` Daniel Vetter
@ 2018-12-19  6:45                   ` C, Ramalingam
  2018-12-20 15:59                     ` C, Ramalingam
  0 siblings, 1 reply; 103+ messages in thread
From: C, Ramalingam @ 2018-12-19  6:45 UTC (permalink / raw)
  To: Daniel Vetter, Winkler, Tomas
  Cc: Rafael J. Wysocki, Greg KH, intel-gfx, dri-devel, Shankar, Uma,
	Sean Paul


[-- Attachment #1.1: Type: text/plain, Size: 10079 bytes --]

Tomas and Daniel,

 From the discussion on this thread, I infer following understanding:

  * At present(v9) I915 wants to be hard binded to mei_hdcp
    device-driver binding status through components
      o This means I915 driver load will get complete only when the
        mei_hdcp's device and driver are bound.
      o if mei_hdcp device reset I915 will unregister itself from
        userspace, and wait for the mei_hdcp device-deriver rebinding.
          + Could be due to FW error or any unexpected failures those
            are rare occurances.
      o when mei_hdcp module is removed i915 will unregister itself.
      o Becasue of this, Ideally I915 dont expect the device reset from
        mei for suspend and resume.
  * At present Mei bus is designed as below:
      o Device will disappear on FW failures, FW upgrade, suspend of the
        system etc.
      o And when the errors are handled or on system resume mei device
        will reappear, hence binding with corresponding driver.
  * Mei doesn't plan to avoid the device reset(disappearance and
    reappearance) for suspend and resume in near future.

Based on above understanding, I propose the below approach. Please correct or approve it.

  * At present(v9) component_add from mei_hdcp indicates the mei_hdcp's
    device-driver binded state.
  * Instead lets use component to indicate the mei_hdcp's module
    availability,
      o by adding the component at module_init and removing it from
        module_exit.
  * This way I915 will not be impacted due to the mei device reset at
    suspend.
  * In such scenario I915 will have no idea about the device-driver bind
    status of mei_hdcp.
      o So incase of device is not available, mei_hdcp is responsible to
        prune such calls with -EIO error.
  * This approach avoid any future impact to I915, incase mei intended
    to support suspend and resume.

I am aware this is not the ideal solution we want. But I feel this is the best at present we could do for this I915-mei interface.

Best regards,
Ram

On 12/17/2018 7:16 PM, Daniel Vetter wrote:
> On Mon, Dec 17, 2018 at 11:57 AM Winkler, Tomas <tomas.winkler@intel.com> wrote:
>>
>>> On Sat, Dec 15, 2018 at 09:20:38PM +0000, Winkler, Tomas wrote:
>>>>> On Thu, Dec 13, 2018 at 5:27 PM Winkler, Tomas
>>>>> <tomas.winkler@intel.com>
>>>>> wrote:
>>>>>>> On Thu, Dec 13, 2018 at 1:36 PM C, Ramalingam
>>>>>>> <ramalingam.c@intel.com>
>>>>>>> wrote:
>>>>>>>> Tomas and Daniel,
>>>>>>>>
>>>>>>>> We got an issue here.
>>>>>>>>
>>>>>>>> The relationship that we try to build between I915 and
>>>>>>>> mei_hdcp is as
>>>>> follows:
>>>>>>>> We are using the components to establish the relationship.
>>>>>>>> I915 is component master where as mei_hdcp is component.
>>>>>>>> I915 adds the component master during the module load.
>>>>>>>> mei_hdcp adds the
>>>>>>> component when the driver->probe is called (on device driver binding).
>>>>>>>> I915 forces itself such that until mei_hdcp component is added
>>>>>>>> I915_load
>>>>>>> wont be complete.
>>>>>>>> Similarly on complete system, if mei_hdcp component is
>>>>>>>> removed,
>>>>>>> immediately I915 unregister itself and HW will be shutdown.
>>>>>>>> This is completely fine when the modules are loaded and unloaded.
>>>>>>>>
>>>>>>>> But during suspend, mei device disappears and mei bus handles
>>>>>>>> it by
>>>>>>> unbinding device and driver by calling driver->remove.
>>>>>>>> This in-turn removes the component and triggers the master
>>>>>>>> unbind of I915
>>>>>>> where, I915 unregister itself.
>>>>>>>> This cause the HW state mismatch during the suspend and resume.
>>>>>>>>
>>>>>>>> Please check the powerwell mismatch errors at CI report for v9
>>>>>>>> https://intel-gfx-ci.01.org/tree/drm-tip/Trybot_3412/fi-glk-j4
>>>>>>>> 005/
>>>>>>>> igt@
>>>>>>>> gem_exec_suspend@basic-s3.html
>>>>>>>>
>>>>>>>> More over unregistering I915 during the suspend is not expected.
>>>>>>>> So how do
>>>>>>> we handle this?
>>>>>>>
>>>>>>> Bit more context from our irc discussion with Ram:
>>>>>>>
>>>>>>> I found this very surprising, since I don't know of any other
>>>>>>> subsystems where the devices get outright removed when going
>>>>>>> through a
>>>>> suspend/resume cycle.
>>>>>>> The device model was built to handle this stuff
>>>>>>> correctly: First clients/devices/interfaces get suspend, then
>>>>>>> the parent/bridge/bus. Same dance in reverse when resuming. This
>>>>>>> even holds for lots of hotpluggable buses, where child devices
>>>>>>> could indeed disappear on resume, but as long as they don't,
>>>>>>> everything stays the same. It's really surprising for something
>>>>>>> that's soldered onto the
>>>>> board like ME.
>>>>>> HDCP is an application in the ME it's not ME itself..  On the
>>>>>> linux side HDCP2 is a virtual device  on mei client virtual bus,
>>>>>> the bus  is teared
>>>>> down on ME reset, which mostly happen  on power transitions.
>>>>>> Theoretically,  we could keep it up during power transitions, but
>>>>>> so fare it was not necessary and second it's not guarantie that
>>>>>> the all ME
>>>>> applications will reappear after reset.
>>>>>
>>>>> When does this happen that an ME application doesn't come back after e.g.
>>>>> suspend/resume?
>>>> No, this can happen in special flows such as  fw updates and error conditions,
>>> but is has to be supported as well.
>>>>> Also, what's all the place where this reset can happen? Just
>>>>> suspend/resume/hibernate and all these, or also at other times?
>>>> Also on errors and fw update,  the basic assumption is here that it can happen
>>> any time.
>>>
>>> If this can happen any time, what are we supposed to do if this happens while
>>> we're doing something with the hdcp mei? If this is such a common occurence I
>>> guess we need to somehow wait until everyting is rebound and working again. I
>>> think ideally mei core would handle that for us, but I guess if this just randomly
>>> happens then we need to redo all the transactions. So does need some
>>> involvement of the higher levels.
>> It's not common occurrence, but the assumption must be it can happen any time,
>> In that case everything has to restarted as there is no state preserved in the ME FW.
>> Right MEI core cannot do it for you, it is just a channel, the logic and state of the connection
>> is in the mei_hdcp or gfx.   Note that HDCP is not the only App over MEI.
> Yes, each mei interface would need to provide suspend/resume
> functions, or something like that. Or at least a reset function.
>
>>> Also, how likely is it that the hdcp mei will outright disappear and not come
>>> back after a reset?
>>>
>>>>> How does userspace deal with the reset over s/r? I'm assuming that
>>>>> at least the device node file will become invalid (or whatever
>>>>> you're using as userspace api), so if userspace is accessing stuff
>>>>> on the me at the same time as we do a suspend/resume, what happens?
>>> Also, answer to how other users handle this would be enlighting.
> Still looking to understand this here.
>
>>>>>>> Aside: We'll probably need a device_link to make sure mei_hdcp
>>>>>>> is fully resumed before i915 gets resumed, but that's kinda a
>>>>>>> detail for later
>>>>> on.
>>>>>> Frankly I don’t believe there is currently exact abstraction that
>>>>>> supports this model, neither components nor device_link .
>>>>>> So fare we used class interface for other purposes, it worked well.
>>>>> I'm not clear on what class interface has to do with component or device
>>> link.
>>>>> They all solve different problems, at least as far as I understand all this stuff
>>> ...
>>>>> -Daniel
>>>> It comes instead of it, device_link is mostly used for power
>>>> management and component as we see know is not what we need as HDCP Is
>>> a b it volitle.
>>>> class_interface  gives you two handlers: add and remove device, that's all
>>> what is needed for the current implementation.
>>>
>>> Well someone needs to handle the volatility of hdcp, and atm we seem to be
>>> playing a game of pass the bucket. I still think that mei_hdcp should supply a
>>> clean interface to i915, with all the reset madness handled internally. But
>>> depending upon how badly this all leaks we might need to have a retry logic in
>>> the i915 hdcp flow too.
>>
>> Restart logic is must.
> Ok, I guess then we need to wrap another layer on top of mei to make
> this happen.
>
> Does mei provide any signal whether a client/app has not survived a
> reset? Atm there's not way for us to tell a reset apart from a
> "mei_hdcp disappared for good" event. Which we kinda need to do.
> Ideally a reset would be a distinct event and not implemented as an
> unbind/rebind cycle like it currently is.
>
>>> device linke we'll probably need anyway, since i915 resuming when hdcp is not
>>> yet up is not a good idea no matter what's goîng on.
>> I've explored device_link and I'm not sure it is suitable there is no power relationship, on suspend/resume the device disappear.
>> I still believe that class_interface is better choice, it this particular case.
> I'm not sure what you mean with class_interface here. How are we
> supposed to use that in this case here? I'm not following you at all
> here.
>
> I also noticed that resume seems to be entirely deferred to workers:
> mei_restart only writes the me start command through the hbm. So all
> the clients will only be re-registered somewhen later on through an
> async worker (in the rescan_work). Is that understanding correct? If
> that's the case we'd need a way to wait for that, so we know whether
> the mei_hdcp is useable again or has disappeared for good.
>
>> The whole issue is not yet resolved in the Linux kernel.
>> There was a discussion around it in ELC  https://schd.ws/hosted_files/osseu18/0f/deferred_problem.pdf
> There's still a bunch of open issues around deferred probe and device
> driver loading, but none that would interfer with what we're trying to
> do here. At least if mei wouldn't handle resets through a bind/unbind
> cycle.
> -Daniel
>
>> Thanks
>> Tomas
>>
>

[-- Attachment #1.2: Type: text/html, Size: 16461 bytes --]

[-- Attachment #2: Type: text/plain, Size: 160 bytes --]

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 103+ messages in thread

* Re: [PATCH v9 01/39] drm/i915: Gathering the HDCP1.4 routines together
  2018-12-13  4:01 ` [PATCH v9 01/39] drm/i915: Gathering the HDCP1.4 routines together Ramalingam C
  2018-12-13  8:17   ` Winkler, Tomas
@ 2018-12-19 13:35   ` Daniel Vetter
  1 sibling, 0 replies; 103+ messages in thread
From: Daniel Vetter @ 2018-12-19 13:35 UTC (permalink / raw)
  To: Ramalingam C
  Cc: daniel.vetter, intel-gfx, dri-devel, uma.shankar, seanpaul,
	tomas.winkler

On Thu, Dec 13, 2018 at 09:31:03AM +0530, Ramalingam C wrote:
> All HDCP1.4 routines are gathered together, followed by the generic
> functions those can be extended for HDCP2.2 too.
> 
> Signed-off-by: Ramalingam C <ramalingam.c@intel.com>

Since just code movement:

Acked-by: Daniel Vetter <daniel.vetter@ffwll.ch>

> ---
>  drivers/gpu/drm/i915/intel_hdcp.c | 118 +++++++++++++++++++-------------------
>  1 file changed, 59 insertions(+), 59 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/intel_hdcp.c b/drivers/gpu/drm/i915/intel_hdcp.c
> index e000e54ad569..506b4cc6f46b 100644
> --- a/drivers/gpu/drm/i915/intel_hdcp.c
> +++ b/drivers/gpu/drm/i915/intel_hdcp.c
> @@ -731,6 +731,65 @@ struct intel_connector *intel_hdcp_to_connector(struct intel_hdcp *hdcp)
>  	return container_of(hdcp, struct intel_connector, hdcp);
>  }
>  
> +/* Implements Part 3 of the HDCP authorization procedure */
> +int intel_hdcp_check_link(struct intel_connector *connector)
> +{
> +	struct intel_hdcp *hdcp = &connector->hdcp;
> +	struct drm_i915_private *dev_priv = connector->base.dev->dev_private;
> +	struct intel_digital_port *intel_dig_port = conn_to_dig_port(connector);
> +	enum port port = intel_dig_port->base.port;
> +	int ret = 0;
> +
> +	if (!hdcp->shim)
> +		return -ENOENT;
> +
> +	mutex_lock(&hdcp->mutex);
> +
> +	if (hdcp->value == DRM_MODE_CONTENT_PROTECTION_UNDESIRED)
> +		goto out;
> +
> +	if (!(I915_READ(PORT_HDCP_STATUS(port)) & HDCP_STATUS_ENC)) {
> +		DRM_ERROR("%s:%d HDCP check failed: link is not encrypted,%x\n",
> +			  connector->base.name, connector->base.base.id,
> +			  I915_READ(PORT_HDCP_STATUS(port)));
> +		ret = -ENXIO;
> +		hdcp->value = DRM_MODE_CONTENT_PROTECTION_DESIRED;
> +		schedule_work(&hdcp->prop_work);
> +		goto out;
> +	}
> +
> +	if (hdcp->shim->check_link(intel_dig_port)) {
> +		if (hdcp->value != DRM_MODE_CONTENT_PROTECTION_UNDESIRED) {
> +			hdcp->value = DRM_MODE_CONTENT_PROTECTION_ENABLED;
> +			schedule_work(&hdcp->prop_work);
> +		}
> +		goto out;
> +	}
> +
> +	DRM_DEBUG_KMS("[%s:%d] HDCP link failed, retrying authentication\n",
> +		      connector->base.name, connector->base.base.id);
> +
> +	ret = _intel_hdcp_disable(connector);
> +	if (ret) {
> +		DRM_ERROR("Failed to disable hdcp (%d)\n", ret);
> +		hdcp->value = DRM_MODE_CONTENT_PROTECTION_DESIRED;
> +		schedule_work(&hdcp->prop_work);
> +		goto out;
> +	}
> +
> +	ret = _intel_hdcp_enable(connector);
> +	if (ret) {
> +		DRM_ERROR("Failed to enable hdcp (%d)\n", ret);
> +		hdcp->value = DRM_MODE_CONTENT_PROTECTION_DESIRED;
> +		schedule_work(&hdcp->prop_work);
> +		goto out;
> +	}
> +
> +out:
> +	mutex_unlock(&hdcp->mutex);
> +	return ret;
> +}
> +
>  static void intel_hdcp_check_work(struct work_struct *work)
>  {
>  	struct intel_hdcp *hdcp = container_of(to_delayed_work(work),
> @@ -867,62 +926,3 @@ void intel_hdcp_atomic_check(struct drm_connector *connector,
>  						   new_state->crtc);
>  	crtc_state->mode_changed = true;
>  }
> -
> -/* Implements Part 3 of the HDCP authorization procedure */
> -int intel_hdcp_check_link(struct intel_connector *connector)
> -{
> -	struct intel_hdcp *hdcp = &connector->hdcp;
> -	struct drm_i915_private *dev_priv = connector->base.dev->dev_private;
> -	struct intel_digital_port *intel_dig_port = conn_to_dig_port(connector);
> -	enum port port = intel_dig_port->base.port;
> -	int ret = 0;
> -
> -	if (!hdcp->shim)
> -		return -ENOENT;
> -
> -	mutex_lock(&hdcp->mutex);
> -
> -	if (hdcp->value == DRM_MODE_CONTENT_PROTECTION_UNDESIRED)
> -		goto out;
> -
> -	if (!(I915_READ(PORT_HDCP_STATUS(port)) & HDCP_STATUS_ENC)) {
> -		DRM_ERROR("%s:%d HDCP check failed: link is not encrypted,%x\n",
> -			  connector->base.name, connector->base.base.id,
> -			  I915_READ(PORT_HDCP_STATUS(port)));
> -		ret = -ENXIO;
> -		hdcp->value = DRM_MODE_CONTENT_PROTECTION_DESIRED;
> -		schedule_work(&hdcp->prop_work);
> -		goto out;
> -	}
> -
> -	if (hdcp->shim->check_link(intel_dig_port)) {
> -		if (hdcp->value != DRM_MODE_CONTENT_PROTECTION_UNDESIRED) {
> -			hdcp->value = DRM_MODE_CONTENT_PROTECTION_ENABLED;
> -			schedule_work(&hdcp->prop_work);
> -		}
> -		goto out;
> -	}
> -
> -	DRM_DEBUG_KMS("[%s:%d] HDCP link failed, retrying authentication\n",
> -		      connector->base.name, connector->base.base.id);
> -
> -	ret = _intel_hdcp_disable(connector);
> -	if (ret) {
> -		DRM_ERROR("Failed to disable hdcp (%d)\n", ret);
> -		hdcp->value = DRM_MODE_CONTENT_PROTECTION_DESIRED;
> -		schedule_work(&hdcp->prop_work);
> -		goto out;
> -	}
> -
> -	ret = _intel_hdcp_enable(connector);
> -	if (ret) {
> -		DRM_DEBUG_KMS("Failed to enable hdcp (%d)\n", ret);
> -		hdcp->value = DRM_MODE_CONTENT_PROTECTION_DESIRED;
> -		schedule_work(&hdcp->prop_work);
> -		goto out;
> -	}
> -
> -out:
> -	mutex_unlock(&hdcp->mutex);
> -	return ret;
> -}
> -- 
> 2.7.4
> 

-- 
Daniel Vetter
Software Engineer, Intel Corporation
http://blog.ffwll.ch
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 103+ messages in thread

* Re: [PATCH v9 02/39] drm: header for i915 - MEI_HDCP interface
  2018-12-13  4:01 ` [PATCH v9 02/39] drm: header for i915 - MEI_HDCP interface Ramalingam C
  2018-12-17 11:28   ` Winkler, Tomas
@ 2018-12-19 13:37   ` Daniel Vetter
  1 sibling, 0 replies; 103+ messages in thread
From: Daniel Vetter @ 2018-12-19 13:37 UTC (permalink / raw)
  To: Ramalingam C
  Cc: daniel.vetter, intel-gfx, dri-devel, uma.shankar, seanpaul,
	tomas.winkler

On Thu, Dec 13, 2018 at 09:31:04AM +0530, Ramalingam C wrote:
> Header defines the interface for the I915 and MEI_HDCP drivers.
> 
> Signed-off-by: Ramalingam C <ramalingam.c@intel.com>

Yeah I think everything together is much neater, and I didn't have any
material concerns with the interface from v8.

> ---
>  include/drm/i915_mei_hdcp_interface.h | 132 ++++++++++++++++++++++++++++++++++
>  1 file changed, 132 insertions(+)
>  create mode 100644 include/drm/i915_mei_hdcp_interface.h
> 
> diff --git a/include/drm/i915_mei_hdcp_interface.h b/include/drm/i915_mei_hdcp_interface.h
> new file mode 100644
> index 000000000000..e3b7fb32612a
> --- /dev/null
> +++ b/include/drm/i915_mei_hdcp_interface.h
> @@ -0,0 +1,132 @@
> +/* SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) */
> +/*
> + * Copyright © 2017-2018 Intel Corporation
> + *
> + * Authors:
> + * Ramalingam C <ramalingam.c@intel.com>

To address Tomas questions, maybe add a comment here that this is the
mei_hdcp specific interface specific to mei and gen9+ intel display IP,
and doesn't implment the entirety of hdcp2, hence why it's specific and
not generic. Plus maybe mention that all the generic/standardized bits are
in drm/drm_hdcp.h.

Either way Reviewed-by: Daniel Vetter <daniel.vetter@ffwll.ch>


> + */
> +
> +#ifndef _I915_MEI_HDCP_INTERFACE_H_
> +#define _I915_MEI_HDCP_INTERFACE_H_
> +
> +#include <linux/mutex.h>
> +#include <drm/drm_hdcp.h>
> +
> +/**
> + * enum hdcp_port_type - HDCP port implementation type defined by ME FW
> + * @HDCP_PORT_TYPE_INVALID: Invalid hdcp port type
> + * @HDCP_PORT_TYPE_INTEGRATED: In-Host HDCP2.x port
> + * @HDCP_PORT_TYPE_LSPCON: HDCP2.2 discrete wired Tx port with LSPCON
> + *			   (HDMI 2.0) solution
> + * @HDCP_PORT_TYPE_CPDP: HDCP2.2 discrete wired Tx port using the CPDP (DP 1.3)
> + *			 solution
> + */
> +enum hdcp_port_type {
> +	HDCP_PORT_TYPE_INVALID,
> +	HDCP_PORT_TYPE_INTEGRATED,
> +	HDCP_PORT_TYPE_LSPCON,
> +	HDCP_PORT_TYPE_CPDP
> +};
> +
> +/**
> + * enum hdcp_wired_protocol - HDCP adaptation used on the port
> + * @HDCP_PROTOCOL_INVALID: Invalid HDCP adaptation protocol
> + * @HDCP_PROTOCOL_HDMI: HDMI adaptation of HDCP used on the port
> + * @HDCP_PROTOCOL_DP: DP adaptation of HDCP used on the port
> + */
> +enum hdcp_wired_protocol {
> +	HDCP_PROTOCOL_INVALID,
> +	HDCP_PROTOCOL_HDMI,
> +	HDCP_PROTOCOL_DP
> +};
> +
> +/**
> + * struct hdcp_port_data - intel specific HDCP port data
> + * @port: port index as per I915
> + * @port_type: HDCP port type as per ME FW classification
> + * @protocol: HDCP adaptation as per ME FW
> + * @k: No of streams transmitted on a port. Only on DP MST this is != 1
> + * @seq_num_m: Count of RepeaterAuth_Stream_Manage msg propagated.
> + *	       Initialized to 0 on AKE_INIT. Incremented after every successful
> + *	       transmission of RepeaterAuth_Stream_Manage message. When it rolls
> + *	       over re-Auth has to be triggered.
> + * @streams: struct hdcp2_streamid_type[k]. Defines the type and id for the
> + *	     streams
> + */
> +struct hdcp_port_data {
> +	short int port;
> +	u8 port_type;
> +	u8 protocol;
> +	u16 k;
> +	u32 seq_num_m;
> +	struct hdcp2_streamid_type *streams;
> +};
> +
> +/**
> + * struct i915_hdcp_component_ops- ops for HDCP2.2 services.
> + * @owner: Module providing the ops
> + * @initiate_hdcp2_session: Initiate a Wired HDCP2.2 Tx Session.
> + *			    And Prepare AKE_Init.
> + * @verify_receiver_cert_prepare_km: Verify the Receiver Certificate
> + *				     AKE_Send_Cert and prepare
> +				     AKE_Stored_Km/AKE_No_Stored_Km
> + * @verify_hprime: Verify AKE_Send_H_prime
> + * @store_pairing_info: Store pairing info received
> + * @initiate_locality_check: Prepare LC_Init
> + * @verify_lprime: Verify lprime
> + * @get_session_key: Prepare SKE_Send_Eks
> + * @repeater_check_flow_prepare_ack: Validate the Downstream topology
> + *				     and prepare rep_ack
> + * @verify_mprime: Verify mprime
> + * @enable_hdcp_authentication:  Mark a port as authenticated.
> + * @close_hdcp_session: Close the Wired HDCP Tx session per port.
> + *			This also disables the authenticated state of the port.
> + */
> +struct i915_hdcp_component_ops {
> +	/**
> +	 * @owner: mei_hdcp module
> +	 */
> +	struct module *owner;
> +
> +	int (*initiate_hdcp2_session)(struct device *dev,
> +				      struct hdcp_port_data *data,
> +				      struct hdcp2_ake_init *ake_data);
> +	int (*verify_receiver_cert_prepare_km)(struct device *dev,
> +					       struct hdcp_port_data *data,
> +					       struct hdcp2_ake_send_cert
> +								*rx_cert,
> +					       bool *km_stored,
> +					       struct hdcp2_ake_no_stored_km
> +								*ek_pub_km,
> +					       size_t *msg_sz);
> +	int (*verify_hprime)(struct device *dev,
> +			     struct hdcp_port_data *data,
> +			     struct hdcp2_ake_send_hprime *rx_hprime);
> +	int (*store_pairing_info)(struct device *dev,
> +				  struct hdcp_port_data *data,
> +				  struct hdcp2_ake_send_pairing_info
> +								*pairing_info);
> +	int (*initiate_locality_check)(struct device *dev,
> +				       struct hdcp_port_data *data,
> +				       struct hdcp2_lc_init *lc_init_data);
> +	int (*verify_lprime)(struct device *dev,
> +			     struct hdcp_port_data *data,
> +			     struct hdcp2_lc_send_lprime *rx_lprime);
> +	int (*get_session_key)(struct device *dev,
> +			       struct hdcp_port_data *data,
> +			       struct hdcp2_ske_send_eks *ske_data);
> +	int (*repeater_check_flow_prepare_ack)(struct device *dev,
> +					       struct hdcp_port_data *data,
> +					       struct hdcp2_rep_send_receiverid_list
> +								*rep_topology,
> +					       struct hdcp2_rep_send_ack
> +								*rep_send_ack);
> +	int (*verify_mprime)(struct device *dev,
> +			     struct hdcp_port_data *data,
> +			     struct hdcp2_rep_stream_ready *stream_ready);
> +	int (*enable_hdcp_authentication)(struct device *dev,
> +					  struct hdcp_port_data *data);
> +	int (*close_hdcp_session)(struct device *dev,
> +				  struct hdcp_port_data *data);
> +};
> +#endif /* _I915_MEI_HDCP_NTERFACE_H_ */
> -- 
> 2.7.4
> 

-- 
Daniel Vetter
Software Engineer, Intel Corporation
http://blog.ffwll.ch
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 103+ messages in thread

* Re: [PATCH v9 03/39] drivers/base: use a worker for sysfs unbind
  2018-12-13  4:01 ` [PATCH v9 03/39] drivers/base: use a worker for sysfs unbind Ramalingam C
@ 2018-12-19 13:38   ` Daniel Vetter
  0 siblings, 0 replies; 103+ messages in thread
From: Daniel Vetter @ 2018-12-19 13:38 UTC (permalink / raw)
  To: Ramalingam C
  Cc: daniel.vetter, intel-gfx, dri-devel, uma.shankar, seanpaul,
	Daniel Vetter, tomas.winkler

On Thu, Dec 13, 2018 at 09:31:05AM +0530, Ramalingam C wrote:
> From: Daniel Vetter <daniel.vetter@intel.com>
> 
> Drivers might want to remove some sysfs files, which needs the same
> locks and ends up angering lockdep. Relevant snippet of the stack
> trace:
> 
>   kernfs_remove_by_name_ns+0x3b/0x80
>   bus_remove_driver+0x92/0xa0
>   acpi_video_unregister+0x24/0x40
>   i915_driver_unload+0x42/0x130 [i915]
>   i915_pci_remove+0x19/0x30 [i915]
>   pci_device_remove+0x36/0xb0
>   device_release_driver_internal+0x185/0x250
>   unbind_store+0xaf/0x180
>   kernfs_fop_write+0x104/0x190
> 
> I've stumbled over this because some new patches by Ram connect the
> snd-hda-intel unload (where we do use sysfs unbind) with the locking
> chains in the i915 unload code (but without creating a new loop),
> which upset our CI. But the bug is already there and can be easily
> reproduced by unbind i915 directly.
> 
> No idea whether this is the correct place to fix this, should at least
> get CI happy again.
> 
> Note that the bus locking is already done by device_release_driver ->
> device_release_driver_internal, so I dropped that part. Also note that
> we don't recheck that the device is still bound by the same driver,
> but neither does the current code do that without races. And I figured
> that's a obscure enough corner case to not bother.
> 
> v2: Use a task work. An entirely async work leads to impressive
> fireworks in our CI, notably in the vtcon bind/unbind code. Task work
> will be as synchronous as the current code, and so keep all these
> preexisting races neatly tugged under the rug.
> 
> Cc: Ramalingam C <ramalingam.c@intel.com>
> Signed-off-by: Daniel Vetter <daniel.vetter@intel.com>

Revised version of this just landed, so we won't need this anymore for
merging. I'll put my patch into topic/core-for-CI, so you can drop this
for the next version.
-Daniel

> ---
>  drivers/base/bus.c | 35 +++++++++++++++++++++++++++++------
>  1 file changed, 29 insertions(+), 6 deletions(-)
> 
> diff --git a/drivers/base/bus.c b/drivers/base/bus.c
> index 8bfd27ec73d6..095c4a140d76 100644
> --- a/drivers/base/bus.c
> +++ b/drivers/base/bus.c
> @@ -17,6 +17,7 @@
>  #include <linux/string.h>
>  #include <linux/mutex.h>
>  #include <linux/sysfs.h>
> +#include <linux/task_work.h>
>  #include "base.h"
>  #include "power/power.h"
>  
> @@ -174,22 +175,44 @@ static const struct kset_uevent_ops bus_uevent_ops = {
>  
>  static struct kset *bus_kset;
>  
> +struct unbind_work {
> +	struct callback_head twork;
> +	struct device *dev;
> +};
> +
> +void unbind_work_fn(struct callback_head *work)
> +{
> +	struct unbind_work *unbind_work =
> +		container_of(work, struct unbind_work, twork);
> +
> +	device_release_driver_internal(unbind_work->dev, NULL,
> +				       unbind_work->dev->parent);
> +	put_device(unbind_work->dev);
> +	kfree(unbind_work);
> +}
> +
>  /* Manually detach a device from its associated driver. */
>  static ssize_t unbind_store(struct device_driver *drv, const char *buf,
>  			    size_t count)
>  {
>  	struct bus_type *bus = bus_get(drv->bus);
> +	struct unbind_work *unbind_work;
>  	struct device *dev;
>  	int err = -ENODEV;
>  
>  	dev = bus_find_device_by_name(bus, NULL, buf);
>  	if (dev && dev->driver == drv) {
> -		if (dev->parent && dev->bus->need_parent_lock)
> -			device_lock(dev->parent);
> -		device_release_driver(dev);
> -		if (dev->parent && dev->bus->need_parent_lock)
> -			device_unlock(dev->parent);
> -		err = count;
> +		unbind_work = kmalloc(sizeof(*unbind_work), GFP_KERNEL);
> +		if (unbind_work) {
> +			unbind_work->dev = dev;
> +			get_device(dev);
> +			init_task_work(&unbind_work->twork, unbind_work_fn);
> +			task_work_add(current, &unbind_work->twork, true);
> +
> +			err = count;
> +		} else {
> +			err = -ENOMEM;
> +		}
>  	}
>  	put_device(dev);
>  	bus_put(bus);
> -- 
> 2.7.4
> 

-- 
Daniel Vetter
Software Engineer, Intel Corporation
http://blog.ffwll.ch
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 103+ messages in thread

* Re: [PATCH v9 04/39] component: alloc component_match without any comp to match
  2018-12-13  4:01 ` [PATCH v9 04/39] component: alloc component_match without any comp to match Ramalingam C
@ 2018-12-19 13:42   ` Daniel Vetter
  2018-12-19 15:04       ` Greg Kroah-Hartman
  0 siblings, 1 reply; 103+ messages in thread
From: Daniel Vetter @ 2018-12-19 13:42 UTC (permalink / raw)
  To: Ramalingam C
  Cc: intel-gfx, dri-devel, seanpaul, daniel.vetter, tomas.winkler,
	uma.shankar, ville.syrjala, chris, Greg Kroah-Hartman,
	Kate Stewart, Thomas Gleixner, Philippe Ombredanne, linux-kernel

On Thu, Dec 13, 2018 at 09:31:06AM +0530, Ramalingam C wrote:
> If all the components associated to a component master is not added
> to the component framework due to the HW capability or Kconfig
> selection, component_match will be NULL at
> component_master_add_with_match().
> 
> To avoid this, component_match_alloc() is added to the framework,
> to allcoate the struct component_match with zero associated components.
> Hence component master can be added with a component_match with zero
> associated components.
> 
> This helps the component master bind call to get triggered,
> even if no component is registered for that particular master.
> 
> This is meant for big PCI device drivers where small/optional
> features are external components, and based on usecases different
> combination of components are build as entire driver.
> 
> In such PCI device driver Load, if we use the component master for
> waiting for few  components(features) availability, only if they are
> supported by the underlying HW, then we need to allocate memory for
> component_match using the API introduced in this change before
> the call to component_master_add_with_match.
> 
> v2:
>   No Change.
> 
> Signed-off-by: Ramalingam C <ramalingam.c@intel.com>
> Suggested-by: Daniel Vetter <daniel.vetter@ffwll.ch>
> Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
> Cc: Kate Stewart <kstewart@linuxfoundation.org>
> Cc: Thomas Gleixner <tglx@linutronix.de>
> Cc: Philippe Ombredanne <pombredanne@nexb.com>
> Cc: linux-kernel@vger.kernel.org

Reviewed-by: Daniel Vetter <daniel.vetter@ffwll.ch>

Greg, I expect the i915 feature that needs this will only land in 4.22.
I'm also not aware of anyone else using this (all the other component
users always use components). How do you want to get this landed?

I think either getting this into 4.21, or an ack for merging through drm
trees would work well for us.
-Daniel

> ---
>  drivers/base/component.c  | 30 ++++++++++++++++++++++++++++++
>  include/linux/component.h |  2 ++
>  2 files changed, 32 insertions(+)
> 
> diff --git a/drivers/base/component.c b/drivers/base/component.c
> index e8d676fad0c9..0ab36b2255ea 100644
> --- a/drivers/base/component.c
> +++ b/drivers/base/component.c
> @@ -312,6 +312,36 @@ static int component_match_realloc(struct device *dev,
>  }
>  
>  /*
> + * Allocate the match without any component_match_array elements.
> + *
> + * This function is useful when the component master might end up
> + * registering itself without any matching components.
> + */
> +void component_match_alloc(struct device *master,
> +	struct component_match **matchptr)
> +{
> +	struct component_match *match = *matchptr;
> +
> +	if (IS_ERR(match))
> +		return;
> +
> +	if (match)
> +		return;
> +
> +	match = devres_alloc(devm_component_match_release,
> +			     sizeof(*match), GFP_KERNEL);
> +	if (!match) {
> +		*matchptr = ERR_PTR(-ENOMEM);
> +		return;
> +	}
> +
> +	devres_add(master, match);
> +
> +	*matchptr = match;
> +}
> +EXPORT_SYMBOL(component_match_alloc);
> +
> +/*
>   * Add a component to be matched, with a release function.
>   *
>   * The match array is first created or extended if necessary.
> diff --git a/include/linux/component.h b/include/linux/component.h
> index e71fbbbc74e2..3f6b420a58f8 100644
> --- a/include/linux/component.h
> +++ b/include/linux/component.h
> @@ -37,6 +37,8 @@ void component_match_add_release(struct device *master,
>  	struct component_match **matchptr,
>  	void (*release)(struct device *, void *),
>  	int (*compare)(struct device *, void *), void *compare_data);
> +void component_match_alloc(struct device *master,
> +	struct component_match **matchptr);
>  
>  static inline void component_match_add(struct device *master,
>  	struct component_match **matchptr,
> -- 
> 2.7.4
> 

-- 
Daniel Vetter
Software Engineer, Intel Corporation
http://blog.ffwll.ch

^ permalink raw reply	[flat|nested] 103+ messages in thread

* Re: [PATCH v9 05/39] drm/i915: component master at i915 driver load
  2018-12-13  4:01 ` [PATCH v9 05/39] drm/i915: component master at i915 driver load Ramalingam C
@ 2018-12-19 13:45   ` Daniel Vetter
  0 siblings, 0 replies; 103+ messages in thread
From: Daniel Vetter @ 2018-12-19 13:45 UTC (permalink / raw)
  To: Ramalingam C; +Cc: daniel.vetter, intel-gfx, dri-devel, seanpaul, tomas.winkler

On Thu, Dec 13, 2018 at 09:31:07AM +0530, Ramalingam C wrote:
> A generic component master is added to hold the i915 registration
> until all required kernel modules are up and active.
> 
> This is achieved through following steps:
>   - moving the i915 driver registration to the component master's
>     bind call
>   - all required kernel modules will add one component each to
>     component_match of I915 component master.
> 
> If no component is added to the I915 component master, due to CONFIG
> selection or HW limitation, component master's bind call (i915
> registration) will be triggered with no wait.
> 
> Similarly when a associated component is removed for some reasons,
> I915 will be unregistered through component master unbind.
> 
> v2:
>   i915_driver_unregister is added to the unbind of master.
> v3:
>   In master_unbind i915_unregister->drm_atomic_helper_shutdown->
> 	component_unbind_all [Daniel]
> 
> Signed-off-by: Ramalingam C <ramalingam.c@intel.com>
> Suggested-by: Daniel Vetter <daniel.vetter@ffwll.ch>
> ---
>  drivers/gpu/drm/i915/i915_drv.c | 86 +++++++++++++++++++++++++++++++++++++----
>  drivers/gpu/drm/i915/i915_drv.h |  3 ++
>  include/drm/i915_component.h    | 11 ++++++
>  3 files changed, 92 insertions(+), 8 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c
> index b310a897a4ad..b8a204072e60 100644
> --- a/drivers/gpu/drm/i915/i915_drv.c
> +++ b/drivers/gpu/drm/i915/i915_drv.c
> @@ -39,12 +39,14 @@
>  #include <linux/vgaarb.h>
>  #include <linux/vga_switcheroo.h>
>  #include <linux/vt.h>
> +#include <linux/component.h>
>  #include <acpi/video.h>
>  
>  #include <drm/drmP.h>
>  #include <drm/drm_crtc_helper.h>
>  #include <drm/drm_atomic_helper.h>
>  #include <drm/i915_drm.h>
> +#include <drm/i915_component.h>
>  
>  #include "i915_drv.h"
>  #include "i915_trace.h"
> @@ -1577,8 +1579,6 @@ static void i915_driver_register(struct drm_i915_private *dev_priv)
>  	if (IS_GEN5(dev_priv))
>  		intel_gpu_ips_init(dev_priv);
>  
> -	intel_audio_init(dev_priv);
> -
>  	/*
>  	 * Some ports require correctly set-up hpd registers for detection to
>  	 * work properly (leading to ghost connected connector status), e.g. VGA
> @@ -1609,7 +1609,6 @@ static void i915_driver_unregister(struct drm_i915_private *dev_priv)
>  	intel_power_domains_disable(dev_priv);
>  
>  	intel_fbdev_unregister(dev_priv);
> -	intel_audio_deinit(dev_priv);
>  
>  	/*
>  	 * After flushing the fbdev (incl. a late async config which will
> @@ -1694,6 +1693,48 @@ static void i915_driver_destroy(struct drm_i915_private *i915)
>  	pci_set_drvdata(pdev, NULL);
>  }
>  
> +static void i915_driver_load_tail(struct drm_i915_private *dev_priv)
> +{
> +	i915_driver_register(dev_priv);
> +
> +	DRM_INFO("load_tail: I915 driver registered\n");
> +}
> +
> +static void i915_driver_unload_head(struct drm_i915_private *dev_priv)
> +{
> +	i915_driver_unregister(dev_priv);
> +
> +	DRM_INFO("unload_head: I915 driver unregistered\n");
> +}
> +
> +static int i915_component_master_bind(struct device *dev)
> +{
> +	struct drm_i915_private *dev_priv = kdev_to_i915(dev);
> +	int ret;
> +
> +	ret = component_bind_all(dev, dev_priv->comp_master);
> +	if (ret < 0)
> +		return ret;
> +
> +	i915_driver_load_tail(dev_priv);
> +
> +	return 0;
> +}
> +
> +static void i915_component_master_unbind(struct device *dev)
> +{
> +	struct drm_i915_private *dev_priv = kdev_to_i915(dev);
> +
> +	i915_driver_unload_head(dev_priv);
> +	drm_atomic_helper_shutdown(&dev_priv->drm);
> +	component_unbind_all(dev, dev_priv->comp_master);
> +}
> +
> +static const struct component_master_ops i915_component_master_ops = {
> +	.bind = i915_component_master_bind,
> +	.unbind = i915_component_master_unbind,
> +};
> +
>  /**
>   * i915_driver_load - setup chip and create an initial config
>   * @pdev: PCI device
> @@ -1720,9 +1761,22 @@ int i915_driver_load(struct pci_dev *pdev, const struct pci_device_id *ent)
>  	if (!i915_modparams.nuclear_pageflip && match_info->gen < 5)
>  		dev_priv->drm.driver_features &= ~DRIVER_ATOMIC;
>  
> +	dev_priv->comp_master = kzalloc(sizeof(*dev_priv->comp_master),
> +					GFP_KERNEL);
> +	if (!dev_priv->comp_master) {
> +		ret = -ENOMEM;
> +		goto out_fini;
> +	}
> +
> +	component_match_alloc(dev_priv->drm.dev, &dev_priv->master_match);
> +	if (!dev_priv->master_match) {
> +		ret = -ENOMEM;
> +		goto out_comp_master_clean;
> +	}
> +
>  	ret = pci_enable_device(pdev);
>  	if (ret)
> -		goto out_fini;
> +		goto out_comp_master_clean;
>  
>  	ret = i915_driver_init_early(dev_priv);
>  	if (ret < 0)
> @@ -1742,14 +1796,27 @@ int i915_driver_load(struct pci_dev *pdev, const struct pci_device_id *ent)
>  	if (ret < 0)
>  		goto out_cleanup_hw;
>  
> -	i915_driver_register(dev_priv);
> +	ret = component_master_add_with_match(dev_priv->drm.dev,
> +					      &i915_component_master_ops,
> +					      dev_priv->master_match);
> +	if (ret < 0) {
> +		DRM_DEV_ERROR(&pdev->dev, "Master comp add failed %d\n",
> +			      ret);
> +		goto out_cleanup_modeset;
> +	}
> +

I think a FIXME here would be nice, all we need to do is have a
component_add_locked functions to handle the recursion. Logically there's
not issue really. Same with intel_audio_deinit() below.

Otoh, the component we expose to snd-hda isn't really related to anything
uapi related, it's just a very low-level interface for power domains and a
few other things. Nothing bad happens if we don't register/unregister that
together with all the uapi/kms/fbdev interfaces.

Either way: Reviewed-by: Daniel Vetter <daniel.vetter@ffwll.ch>

> +	intel_audio_init(dev_priv);
>  
>  	enable_rpm_wakeref_asserts(dev_priv);
>  
>  	i915_welcome_messages(dev_priv);
>  
> +	DRM_INFO("I915 registration waits for req component(s). if any...\n");
> +
>  	return 0;
>  
> +out_cleanup_modeset:
> +	intel_modeset_cleanup(&dev_priv->drm);
>  out_cleanup_hw:
>  	i915_driver_cleanup_hw(dev_priv);
>  out_cleanup_mmio:
> @@ -1759,6 +1826,8 @@ int i915_driver_load(struct pci_dev *pdev, const struct pci_device_id *ent)
>  	i915_driver_cleanup_early(dev_priv);
>  out_pci_disable:
>  	pci_disable_device(pdev);
> +out_comp_master_clean:
> +	kfree(dev_priv->comp_master);
>  out_fini:
>  	i915_load_error(dev_priv, "Device initialization failed (%d)\n", ret);
>  	i915_driver_destroy(dev_priv);
> @@ -1772,13 +1841,14 @@ void i915_driver_unload(struct drm_device *dev)
>  
>  	disable_rpm_wakeref_asserts(dev_priv);
>  
> -	i915_driver_unregister(dev_priv);
> +	component_master_del(dev_priv->drm.dev, &i915_component_master_ops);
> +	kfree(dev_priv->comp_master);
> +
> +	intel_audio_deinit(dev_priv);
>  
>  	if (i915_gem_suspend(dev_priv))
>  		DRM_ERROR("failed to idle hardware; continuing to unload!\n");
>  
> -	drm_atomic_helper_shutdown(dev);
> -
>  	intel_gvt_cleanup(dev_priv);
>  
>  	intel_modeset_cleanup(dev);
> diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
> index e70707e79386..25dc3d7a1e3b 100644
> --- a/drivers/gpu/drm/i915/i915_drv.h
> +++ b/drivers/gpu/drm/i915/i915_drv.h
> @@ -2002,6 +2002,9 @@ struct drm_i915_private {
>  
>  	struct i915_pmu pmu;
>  
> +	struct i915_component_master *comp_master;
> +	struct component_match *master_match;
> +
>  	/*
>  	 * NOTE: This is the dri1/ums dungeon, don't add stuff here. Your patch
>  	 * will be rejected. Instead look for a better place.
> diff --git a/include/drm/i915_component.h b/include/drm/i915_component.h
> index fca22d463e1b..6f94ddd3f2c2 100644
> --- a/include/drm/i915_component.h
> +++ b/include/drm/i915_component.h
> @@ -46,4 +46,15 @@ struct i915_audio_component {
>  	int aud_sample_rate[MAX_PORTS];
>  };
>  
> +/**
> + * struct i915_component_master - Used for communication between i915
> + *				  and any other drivers for the services
> + *				  of different feature.
> + */
> +struct i915_component_master {
> +	/*
> +	 * Add here the interface details between I915 and interested modules.
> +	 */
> +};
> +
>  #endif /* _I915_COMPONENT_H_ */
> -- 
> 2.7.4
> 

-- 
Daniel Vetter
Software Engineer, Intel Corporation
http://blog.ffwll.ch
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 103+ messages in thread

* Re: [PATCH v9 06/39] drm/i915: Initialize HDCP2.2
  2018-12-13  4:01 ` [PATCH v9 06/39] drm/i915: Initialize HDCP2.2 Ramalingam C
@ 2018-12-19 13:45   ` Daniel Vetter
  0 siblings, 0 replies; 103+ messages in thread
From: Daniel Vetter @ 2018-12-19 13:45 UTC (permalink / raw)
  To: Ramalingam C; +Cc: daniel.vetter, intel-gfx, dri-devel, seanpaul, tomas.winkler

On Thu, Dec 13, 2018 at 09:31:08AM +0530, Ramalingam C wrote:
> Add the HDCP2.2 initialization to the existing HDCP1.4 stack.
> 
> v2:
>   mei interface handle is protected with mutex. [Chris Wilson]
> v3:
>   Notifiers are used for the mei interface state.
> v4:
>   Poll for mei client device state
>   Error msg for out of mem [Uma]
>   Inline req for init function removed [Uma]
> v5:
>   Rebase as Part of reordering.
>   Component is used for the I915 and MEI_HDCP interface [Daniel]
> v6:
>   HDCP2.2 uses the I915 component master to communicate with mei_hdcp
> 	- [Daniel]
>   Required HDCP2.2 variables defined [Sean Paul]
> v7:
>   intel_hdcp2.2_init returns void [Uma]
>   Realigning the codes.
> v8:
>   Avoid using bool structure members.
>   MEI interface related changes are moved into separate patch.
>   Commit msg is updated accordingly.
>   intel_hdcp_exit is defined and used from i915_unload
> v9:
>   Movement of the hdcp_check_link is moved to new patch [Daniel]
>   intel_hdcp2_exit is removed as mei_comp will be unbind in i915_unload.

All concerns I had addressed.

Reviewed-by: Daniel Vetter <daniel.vetter@ffwll.ch>

> 
> Signed-off-by: Ramalingam C <ramalingam.c@intel.com>
> ---
>  drivers/gpu/drm/i915/intel_dp.c   |  3 ++-
>  drivers/gpu/drm/i915/intel_drv.h  | 15 ++++++++++++++-
>  drivers/gpu/drm/i915/intel_hdcp.c | 30 +++++++++++++++++++++++++++---
>  drivers/gpu/drm/i915/intel_hdmi.c |  2 +-
>  4 files changed, 44 insertions(+), 6 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
> index e94faa0a42eb..aba884c64879 100644
> --- a/drivers/gpu/drm/i915/intel_dp.c
> +++ b/drivers/gpu/drm/i915/intel_dp.c
> @@ -6902,7 +6902,8 @@ intel_dp_init_connector(struct intel_digital_port *intel_dig_port,
>  	intel_dp_add_properties(intel_dp, connector);
>  
>  	if (is_hdcp_supported(dev_priv, port) && !intel_dp_is_edp(intel_dp)) {
> -		int ret = intel_hdcp_init(intel_connector, &intel_dp_hdcp_shim);
> +		int ret = intel_hdcp_init(intel_connector, &intel_dp_hdcp_shim,
> +					  false);
>  		if (ret)
>  			DRM_DEBUG_KMS("HDCP init failed, skipping.\n");
>  	}
> diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
> index d08f08f607dd..dd9371647a8c 100644
> --- a/drivers/gpu/drm/i915/intel_drv.h
> +++ b/drivers/gpu/drm/i915/intel_drv.h
> @@ -388,6 +388,17 @@ struct intel_hdcp {
>  	u64 value;
>  	struct delayed_work check_work;
>  	struct work_struct prop_work;
> +
> +	/* HDCP2.2 related definitions */
> +	/* Flag indicates whether this connector supports HDCP2.2 or not. */
> +	u8 hdcp2_supported;
> +
> +	/*
> +	 * Content Stream Type defined by content owner. TYPE0(0x0) content can
> +	 * flow in the link protected by HDCP2.2 or HDCP1.4, where as TYPE1(0x1)
> +	 * content can flow only through a link protected by HDCP2.2.
> +	 */
> +	u8 content_type;
>  };
>  
>  struct intel_connector {
> @@ -2038,12 +2049,14 @@ void intel_hdcp_atomic_check(struct drm_connector *connector,
>  			     struct drm_connector_state *old_state,
>  			     struct drm_connector_state *new_state);
>  int intel_hdcp_init(struct intel_connector *connector,
> -		    const struct intel_hdcp_shim *hdcp_shim);
> +		    const struct intel_hdcp_shim *hdcp_shim,
> +		    bool hdcp2_supported);
>  int intel_hdcp_enable(struct intel_connector *connector);
>  int intel_hdcp_disable(struct intel_connector *connector);
>  int intel_hdcp_check_link(struct intel_connector *connector);
>  bool is_hdcp_supported(struct drm_i915_private *dev_priv, enum port port);
>  bool intel_hdcp_capable(struct intel_connector *connector);
> +bool is_hdcp2_supported(struct drm_i915_private *dev_priv);
>  
>  /* intel_psr.c */
>  #define CAN_PSR(dev_priv) (HAS_PSR(dev_priv) && dev_priv->psr.sink_support)
> diff --git a/drivers/gpu/drm/i915/intel_hdcp.c b/drivers/gpu/drm/i915/intel_hdcp.c
> index 506b4cc6f46b..584d27f3c699 100644
> --- a/drivers/gpu/drm/i915/intel_hdcp.c
> +++ b/drivers/gpu/drm/i915/intel_hdcp.c
> @@ -833,14 +833,34 @@ bool is_hdcp_supported(struct drm_i915_private *dev_priv, enum port port)
>  	return INTEL_GEN(dev_priv) >= 9 && port < PORT_E;
>  }
>  
> +bool is_hdcp2_supported(struct drm_i915_private *dev_priv)
> +{
> +	return ((INTEL_GEN(dev_priv) >= 10 || IS_GEMINILAKE(dev_priv) ||
> +		 IS_KABYLAKE(dev_priv)) && IS_ENABLED(CONFIG_INTEL_MEI_HDCP));
> +}
> +
> +static void intel_hdcp2_init(struct intel_connector *connector)
> +{
> +	struct drm_i915_private *dev_priv = to_i915(connector->base.dev);
> +	struct intel_hdcp *hdcp = &connector->hdcp;
> +
> +	WARN_ON(!is_hdcp2_supported(dev_priv));
> +
> +	/* TODO: MEI interface needs to be initialized here */
> +	hdcp->hdcp2_supported = 1;
> +}
> +
>  int intel_hdcp_init(struct intel_connector *connector,
> -		    const struct intel_hdcp_shim *shim)
> +		    const struct intel_hdcp_shim *shim,
> +		    bool hdcp2_supported)
>  {
>  	struct intel_hdcp *hdcp = &connector->hdcp;
>  	int ret;
>  
> -	ret = drm_connector_attach_content_protection_property(
> -			&connector->base);
> +	if (!shim)
> +		return -EINVAL;
> +
> +	ret = drm_connector_attach_content_protection_property(&connector->base);
>  	if (ret)
>  		return ret;
>  
> @@ -848,6 +868,10 @@ int intel_hdcp_init(struct intel_connector *connector,
>  	mutex_init(&hdcp->mutex);
>  	INIT_DELAYED_WORK(&hdcp->check_work, intel_hdcp_check_work);
>  	INIT_WORK(&hdcp->prop_work, intel_hdcp_prop_work);
> +
> +	if (hdcp2_supported)
> +		intel_hdcp2_init(connector);
> +
>  	return 0;
>  }
>  
> diff --git a/drivers/gpu/drm/i915/intel_hdmi.c b/drivers/gpu/drm/i915/intel_hdmi.c
> index 07e803a604bd..38fe0fdbf8d8 100644
> --- a/drivers/gpu/drm/i915/intel_hdmi.c
> +++ b/drivers/gpu/drm/i915/intel_hdmi.c
> @@ -2434,7 +2434,7 @@ void intel_hdmi_init_connector(struct intel_digital_port *intel_dig_port,
>  
>  	if (is_hdcp_supported(dev_priv, port)) {
>  		int ret = intel_hdcp_init(intel_connector,
> -					  &intel_hdmi_hdcp_shim);
> +					  &intel_hdmi_hdcp_shim, false);
>  		if (ret)
>  			DRM_DEBUG_KMS("HDCP init failed, skipping.\n");
>  	}
> -- 
> 2.7.4
> 

-- 
Daniel Vetter
Software Engineer, Intel Corporation
http://blog.ffwll.ch
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 103+ messages in thread

* Re: [PATCH v9 07/39] drm/i915: MEI interface definition
  2018-12-13  4:01 ` [PATCH v9 07/39] drm/i915: MEI interface definition Ramalingam C
@ 2018-12-19 14:00   ` Daniel Vetter
  2018-12-19 15:15     ` C, Ramalingam
  0 siblings, 1 reply; 103+ messages in thread
From: Daniel Vetter @ 2018-12-19 14:00 UTC (permalink / raw)
  To: Ramalingam C; +Cc: daniel.vetter, intel-gfx, dri-devel, seanpaul, tomas.winkler

On Thu, Dec 13, 2018 at 09:31:09AM +0530, Ramalingam C wrote:
> Defining the mei-i915 interface functions and initialization of
> the interface.
> 
> v2:
>   Adjust to the new interface changes. [Tomas]
>   Added further debug logs for the failures at MEI i/f.
>   port in hdcp_port data is equipped to handle -ve values.
> v3:
>   mei comp is matched for global i915 comp master. [Daniel]
>   In hdcp_shim hdcp_protocol() is replaced with const variable. [Daniel]
>   mei wrappers are adjusted as per the i/f change [Daniel]

Yeah looks all good. Spotted some small stuff below still.

> Signed-off-by: Ramalingam C <ramalingam.c@intel.com>
> ---
>  drivers/gpu/drm/i915/intel_drv.h  |   5 +
>  drivers/gpu/drm/i915/intel_hdcp.c | 248 +++++++++++++++++++++++++++++++++++++-
>  include/drm/i915_component.h      |   7 ++
>  3 files changed, 259 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
> index dd9371647a8c..191b6e0f086c 100644
> --- a/drivers/gpu/drm/i915/intel_drv.h
> +++ b/drivers/gpu/drm/i915/intel_drv.h
> @@ -39,6 +39,7 @@
>  #include <drm/drm_dp_mst_helper.h>
>  #include <drm/drm_rect.h>
>  #include <drm/drm_atomic.h>
> +#include <drm/i915_mei_hdcp_interface.h>
>  #include <media/cec-notifier.h>
>  
>  /**
> @@ -379,6 +380,9 @@ struct intel_hdcp_shim {
>  	/* Detects panel's hdcp capability. This is optional for HDMI. */
>  	int (*hdcp_capable)(struct intel_digital_port *intel_dig_port,
>  			    bool *hdcp_capable);
> +
> +	/* HDCP adaptation(DP/HDMI) required on the port */
> +	enum hdcp_wired_protocol protocol;
>  };
>  
>  struct intel_hdcp {
> @@ -399,6 +403,7 @@ struct intel_hdcp {
>  	 * content can flow only through a link protected by HDCP2.2.
>  	 */
>  	u8 content_type;
> +	struct hdcp_port_data port_data;
>  };
>  
>  struct intel_connector {
> diff --git a/drivers/gpu/drm/i915/intel_hdcp.c b/drivers/gpu/drm/i915/intel_hdcp.c
> index 584d27f3c699..9405fce07b93 100644
> --- a/drivers/gpu/drm/i915/intel_hdcp.c
> +++ b/drivers/gpu/drm/i915/intel_hdcp.c
> @@ -8,8 +8,10 @@
>  
>  #include <drm/drmP.h>
>  #include <drm/drm_hdcp.h>
> +#include <drm/i915_component.h>
>  #include <linux/i2c.h>
>  #include <linux/random.h>
> +#include <linux/component.h>
>  
>  #include "intel_drv.h"
>  #include "i915_reg.h"
> @@ -833,6 +835,232 @@ bool is_hdcp_supported(struct drm_i915_private *dev_priv, enum port port)
>  	return INTEL_GEN(dev_priv) >= 9 && port < PORT_E;
>  }
>  
> +static __attribute__((unused)) int
> +hdcp2_prepare_ake_init(struct intel_connector *connector,
> +		       struct hdcp2_ake_init *ake_data)
> +{
> +	struct hdcp_port_data *data = &connector->hdcp.port_data;
> +	struct drm_i915_private *dev_priv = to_i915(connector->base.dev);
> +	struct i915_component_master *comp = dev_priv->comp_master;
> +	int ret;
> +
> +	/* During the connector init encoder might not be initialized */
> +	if (data->port == PORT_NONE)
> +		data->port = connector->encoder->port;
> +
> +	ret = comp->hdcp_ops->initiate_hdcp2_session(comp->mei_dev,
> +						     data, ake_data);
> +	if (ret)
> +		DRM_DEBUG_KMS("Prepare_ake_init failed. %d\n", ret);
> +
> +	return ret;
> +}
> +
> +static __attribute__((unused)) int
> +hdcp2_verify_rx_cert_prepare_km(struct intel_connector *connector,
> +				struct hdcp2_ake_send_cert *rx_cert,
> +				bool *paired,
> +				struct hdcp2_ake_no_stored_km *ek_pub_km,
> +				size_t *msg_sz)
> +{
> +	struct hdcp_port_data *data = &connector->hdcp.port_data;
> +	struct drm_i915_private *dev_priv = to_i915(connector->base.dev);
> +	struct i915_component_master *comp = dev_priv->comp_master;
> +	int ret;
> +
> +	ret = comp->hdcp_ops->verify_receiver_cert_prepare_km(comp->mei_dev,
> +							      data, rx_cert,
> +							      paired, ek_pub_km,
> +							      msg_sz);
> +	if (ret < 0)
> +		DRM_DEBUG_KMS("Verify rx_cert failed. %d\n", ret);
> +
> +	return ret;
> +}
> +
> +static __attribute__((unused)) int
> +hdcp2_verify_hprime(struct intel_connector *connector,
> +		    struct hdcp2_ake_send_hprime *rx_hprime)
> +{
> +	struct hdcp_port_data *data = &connector->hdcp.port_data;
> +	struct drm_i915_private *dev_priv = to_i915(connector->base.dev);
> +	struct i915_component_master *comp = dev_priv->comp_master;
> +	int ret;
> +
> +	ret = comp->hdcp_ops->verify_hprime(comp->mei_dev, data, rx_hprime);
> +	if (ret < 0)
> +		DRM_DEBUG_KMS("Verify hprime failed. %d\n", ret);
> +
> +	return ret;
> +}
> +
> +static __attribute__((unused)) int
> +hdcp2_store_pairing_info(struct intel_connector *connector,
> +			 struct hdcp2_ake_send_pairing_info *pairing_info)
> +{
> +	struct hdcp_port_data *data = &connector->hdcp.port_data;
> +	struct drm_i915_private *dev_priv = to_i915(connector->base.dev);
> +	struct i915_component_master *comp = dev_priv->comp_master;
> +	int ret;
> +
> +	ret = comp->hdcp_ops->store_pairing_info(comp->mei_dev, data,
> +						 pairing_info);
> +	if (ret < 0)
> +		DRM_DEBUG_KMS("Store pairing info failed. %d\n", ret);
> +
> +	return ret;
> +}
> +
> +static __attribute__((unused)) int
> +hdcp2_prepare_lc_init(struct intel_connector *connector,
> +		      struct hdcp2_lc_init *lc_init)
> +{
> +	struct hdcp_port_data *data = &connector->hdcp.port_data;
> +	struct drm_i915_private *dev_priv = to_i915(connector->base.dev);
> +	struct i915_component_master *comp = dev_priv->comp_master;
> +	int ret;
> +
> +	ret = comp->hdcp_ops->initiate_locality_check(comp->mei_dev, data,
> +						      lc_init);
> +	if (ret < 0)
> +		DRM_DEBUG_KMS("Prepare lc_init failed. %d\n", ret);
> +
> +	return ret;
> +}
> +
> +static __attribute__((unused)) int
> +hdcp2_verify_lprime(struct intel_connector *connector,
> +		    struct hdcp2_lc_send_lprime *rx_lprime)
> +{
> +	struct hdcp_port_data *data = &connector->hdcp.port_data;
> +	struct drm_i915_private *dev_priv = to_i915(connector->base.dev);
> +	struct i915_component_master *comp = dev_priv->comp_master;
> +	int ret;
> +
> +	ret = comp->hdcp_ops->verify_lprime(comp->mei_dev, data, rx_lprime);
> +	if (ret < 0)
> +		DRM_DEBUG_KMS("Verify L_Prime failed. %d\n", ret);
> +
> +	return ret;
> +}
> +
> +static __attribute__((unused))
> +int hdcp2_prepare_skey(struct intel_connector *connector,
> +		       struct hdcp2_ske_send_eks *ske_data)
> +{
> +	struct hdcp_port_data *data = &connector->hdcp.port_data;
> +	struct drm_i915_private *dev_priv = to_i915(connector->base.dev);
> +	struct i915_component_master *comp = dev_priv->comp_master;
> +	int ret;
> +
> +	ret = comp->hdcp_ops->get_session_key(comp->mei_dev, data, ske_data);
> +	if (ret < 0)
> +		DRM_DEBUG_KMS("Get session key failed. %d\n", ret);
> +
> +	return ret;
> +}
> +
> +static __attribute__((unused)) int
> +hdcp2_verify_rep_topology_prepare_ack(struct intel_connector *connector,
> +				      struct hdcp2_rep_send_receiverid_list
> +								*rep_topology,
> +				      struct hdcp2_rep_send_ack *rep_send_ack)
> +{
> +	struct hdcp_port_data *data = &connector->hdcp.port_data;
> +	struct drm_i915_private *dev_priv = to_i915(connector->base.dev);
> +	struct i915_component_master *comp = dev_priv->comp_master;
> +	int ret;
> +
> +	ret = comp->hdcp_ops->repeater_check_flow_prepare_ack(comp->mei_dev,
> +							      data,
> +							      rep_topology,
> +							      rep_send_ack);
> +	if (ret < 0)
> +		DRM_DEBUG_KMS("Verify rep topology failed. %d\n", ret);
> +
> +	return ret;
> +}
> +
> +static __attribute__((unused)) int
> +hdcp2_verify_mprime(struct intel_connector *connector,
> +		    struct hdcp2_rep_stream_ready *stream_ready)
> +{
> +	struct hdcp_port_data *data = &connector->hdcp.port_data;
> +	struct drm_i915_private *dev_priv = to_i915(connector->base.dev);
> +	struct i915_component_master *comp = dev_priv->comp_master;
> +	int ret;
> +
> +	ret = comp->hdcp_ops->verify_mprime(comp->mei_dev, data, stream_ready);
> +	if (ret < 0)
> +		DRM_DEBUG_KMS("Verify mprime failed. %d\n", ret);
> +
> +	return ret;
> +}
> +
> +static __attribute__((unused))
> +int hdcp2_authenticate_port(struct intel_connector *connector)
> +{
> +	struct hdcp_port_data *data = &connector->hdcp.port_data;
> +	struct drm_i915_private *dev_priv = to_i915(connector->base.dev);
> +	struct i915_component_master *comp = dev_priv->comp_master;
> +	int ret;
> +
> +	ret = comp->hdcp_ops->enable_hdcp_authentication(comp->mei_dev, data);
> +	if (ret < 0)
> +		DRM_DEBUG_KMS("Enable hdcp auth failed. %d\n", ret);
> +
> +	return ret;
> +}
> +
> +static __attribute__((unused))
> +int hdcp2_close_mei_session(struct intel_connector *connector)
> +{
> +	struct drm_i915_private *dev_priv = to_i915(connector->base.dev);
> +	struct i915_component_master *comp = dev_priv->comp_master;
> +
> +	return comp->hdcp_ops->close_hdcp_session(comp->mei_dev,
> +						  &connector->hdcp.port_data);
> +}
> +
> +static __attribute__((unused))
> +int hdcp2_deauthenticate_port(struct intel_connector *connector)
> +{
> +	return hdcp2_close_mei_session(connector);
> +}
> +
> +static int i915_hdcp_component_match(struct device *dev, void *data)
> +{
> +	return !strcmp(dev->driver->name, "mei_hdcp");
> +}
> +
> +static int initialize_hdcp_port_data(struct intel_connector *connector)
> +{
> +	struct intel_hdcp *hdcp = &connector->hdcp;
> +	struct hdcp_port_data *data = &hdcp->port_data;
> +
> +	data->port = PORT_NONE;
> +	if (connector->encoder)
> +		data->port = connector->encoder->port;

This and the code above in ake_init still look strange. I'm not really
following how we can end up with an intialization sequence where we do not
yet know the encoder and hence can't assign the port?

That still smells like a bug. I think we should be able to set this
uncondtionally (if not, I need to understand why).

> +
> +	data->port_type = (u8)HDCP_PORT_TYPE_INTEGRATED;
> +	data->protocol = (u8)hdcp->shim->protocol;
> +
> +	data->k = 1;
> +	if (!data->streams)
> +		data->streams = kcalloc(data->k,
> +					sizeof(struct hdcp2_streamid_type),
> +					GFP_KERNEL);
> +	if (!data->streams) {
> +		DRM_ERROR("Out of Memory\n");
> +		return -ENOMEM;
> +	}
> +
> +	data->streams[0].stream_id = 0;
> +	data->streams[0].stream_type = hdcp->content_type;
> +
> +	return 0;
> +}
> +
>  bool is_hdcp2_supported(struct drm_i915_private *dev_priv)
>  {
>  	return ((INTEL_GEN(dev_priv) >= 10 || IS_GEMINILAKE(dev_priv) ||
> @@ -843,10 +1071,28 @@ static void intel_hdcp2_init(struct intel_connector *connector)
>  {
>  	struct drm_i915_private *dev_priv = to_i915(connector->base.dev);
>  	struct intel_hdcp *hdcp = &connector->hdcp;
> +	static bool comp_match_added;
> +	int ret;
>  
>  	WARN_ON(!is_hdcp2_supported(dev_priv));
>  
> -	/* TODO: MEI interface needs to be initialized here */
> +	ret = initialize_hdcp_port_data(connector);
> +	if (ret) {
> +		DRM_DEBUG_KMS("Mei hdcp data init failed\n");
> +		return;
> +	}
> +
> +	/*
> +	 * Component for mei is common across the connector.
> +	 * Adding the match once is sufficient.
> +	 * TODO: Instead of static bool, do we need flag in dev_priv?.
> +	 */
> +	if (!comp_match_added) {
> +		component_match_add(dev_priv->drm.dev, &dev_priv->master_match,
> +				    i915_hdcp_component_match, dev_priv);

Patch series needs to be reordered: We can only do the component_match_add
once the mei component is merged. Maybe just split out this hunk into a
final patch?

> +		comp_match_added = true;

This static here kinda works because there's only 1 gpu, but it's a bad
hack. Please move to drm_i915_private (next to the other component stuff).

Also, we need to only do this when CONFIG_MEI_HDCP is enabled, otherwise
hdcp2 init must fail. Maybe best to put that into the is_hdcp2_supported
helper for now. Once we get non-MEI hdcp2 (definitely needed for discrete
gpu) we can split that up into is_mei_hdcp2_support and
is_other_hdcp2_supported.

Otherwise lgtm I think.
-Daniel

> +	}
> +
>  	hdcp->hdcp2_supported = 1;
>  }
>  
> diff --git a/include/drm/i915_component.h b/include/drm/i915_component.h
> index 6f94ddd3f2c2..7a7201374cfe 100644
> --- a/include/drm/i915_component.h
> +++ b/include/drm/i915_component.h
> @@ -24,6 +24,8 @@
>  #ifndef _I915_COMPONENT_H_
>  #define _I915_COMPONENT_H_
>  
> +#include <drm/i915_mei_hdcp_interface.h>
> +
>  #include "drm_audio_component.h"
>  
>  /* MAX_PORT is the number of port
> @@ -50,8 +52,13 @@ struct i915_audio_component {
>   * struct i915_component_master - Used for communication between i915
>   *				  and any other drivers for the services
>   *				  of different feature.
> + * @mei_dev: device that provide the HDCP2.2 service from MEI Bus.
> + * @hdcp_ops: Ops implemented by mei_hdcp driver, used by i915 driver.
>   */
>  struct i915_component_master {
> +	struct device *mei_dev;
> +	const struct i915_hdcp_component_ops *hdcp_ops;
> +
>  	/*
>  	 * Add here the interface details between I915 and interested modules.
>  	 */
> -- 
> 2.7.4
> 

-- 
Daniel Vetter
Software Engineer, Intel Corporation
http://blog.ffwll.ch
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 103+ messages in thread

* Re: [PATCH v9 10/39] drm/i915: Implement HDCP2.2 receiver authentication
  2018-12-13  4:01 ` [PATCH v9 10/39] drm/i915: Implement HDCP2.2 receiver authentication Ramalingam C
@ 2018-12-19 14:35   ` Daniel Vetter
  2018-12-19 15:05     ` C, Ramalingam
  0 siblings, 1 reply; 103+ messages in thread
From: Daniel Vetter @ 2018-12-19 14:35 UTC (permalink / raw)
  To: Ramalingam C
  Cc: daniel.vetter, intel-gfx, dri-devel, uma.shankar, seanpaul,
	tomas.winkler

On Thu, Dec 13, 2018 at 09:31:12AM +0530, Ramalingam C wrote:
> Implements HDCP2.2 authentication for hdcp2.2 receivers, with
> following steps:
> 	Authentication and Key exchange (AKE).
> 	Locality Check (LC).
> 	Session Key Exchange(SKE).
> 	DP Errata for stream type configuration for receivers.
> 
> At AKE, the HDCP Receiver’s public key certificate is verified by the
> HDCP Transmitter. A Master Key k m is exchanged.
> 
> At LC, the HDCP Transmitter enforces locality on the content by
> requiring that the Round Trip Time (RTT) between a pair of messages
> is not more than 20 ms.
> 
> At SKE, The HDCP Transmitter exchanges Session Key ks with
> the HDCP Receiver.
> 
> In DP HDCP2.2 encryption and decryption logics use the stream type as
> one of the parameter. So Before enabling the Encryption DP HDCP2.2
> receiver needs to be communicated with stream type. This is added to
> spec as ERRATA.
> 
> This generic implementation is complete only with the hdcp2 specific
> functions defined at hdcp_shim.
> 
> v2: Rebased.
> v3:
>   %s/PARING/PAIRING
>   Coding style fixing [Uma]
> v4:
>   Rebased as part of patch reordering.
>   Defined the functions for mei services. [Daniel]
> v5:
>   Redefined the mei service functions as per comp redesign.
>   Required intel_hdcp members are defined [Sean Paul]
> v6:
>   Typo of cipher is Fixed [Uma]
>   %s/uintxx_t/uxx
>   Check for comp_master is removed.
> v7:
>   Adjust to the new interface.
>   Avoid using bool structure members. [Tomas]
> v8: Rebased.
> 
> Signed-off-by: Ramalingam C <ramalingam.c@intel.com>
> ---
>  drivers/gpu/drm/i915/intel_drv.h  |  34 ++++++
>  drivers/gpu/drm/i915/intel_hdcp.c | 211 +++++++++++++++++++++++++++++++++++---
>  2 files changed, 230 insertions(+), 15 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
> index 6d5361616ca3..a6b632d71490 100644
> --- a/drivers/gpu/drm/i915/intel_drv.h
> +++ b/drivers/gpu/drm/i915/intel_drv.h
> @@ -387,6 +387,22 @@ struct intel_hdcp_shim {
>  	/* Detects whether Panel is HDCP2.2 capable */
>  	int (*hdcp_2_2_capable)(struct intel_digital_port *intel_dig_port,
>  				bool *capable);
> +
> +	/* Write HDCP2.2 messages */
> +	int (*write_2_2_msg)(struct intel_digital_port *intel_dig_port,
> +			     void *buf, size_t size);
> +
> +	/* Read HDCP2.2 messages */
> +	int (*read_2_2_msg)(struct intel_digital_port *intel_dig_port,
> +			    u8 msg_id, void *buf, size_t size);
> +
> +	/*
> +	 * Implementation of DP HDCP2.2 Errata for the communication of stream
> +	 * type to Receivers. In DP HDCP2.2 Stream type is one of the input to
> +	 * the HDCP2.2 Cipher for En/De-Cryption. Not applicable for HDMI.
> +	 */
> +	int (*config_stream_type)(struct intel_digital_port *intel_dig_port,
> +				  void *buf, size_t size);
>  };
>  
>  struct intel_hdcp {
> @@ -414,6 +430,24 @@ struct intel_hdcp {
>  	 */
>  	u8 content_type;
>  	struct hdcp_port_data port_data;
> +
> +	u8 is_paired;
> +	u8 is_repeater;

Make these two bool, will simplify the code a bunch.

> +
> +	/*
> +	 * Count of ReceiverID_List received. Initialized to 0 at AKE_INIT.
> +	 * Incremented after processing the RepeaterAuth_Send_ReceiverID_List.
> +	 * When it rolls over re-auth has to be triggered.
> +	 */
> +	u32 seq_num_v;
> +
> +	/*
> +	 * Count of RepeaterAuth_Stream_Manage msg propagated.
> +	 * Initialized to 0 on AKE_INIT. Incremented after every successful
> +	 * transmission of RepeaterAuth_Stream_Manage message. When it rolls
> +	 * over re-Auth has to be triggered.
> +	 */
> +	u32 seq_num_m;
>  };
>  
>  struct intel_connector {
> diff --git a/drivers/gpu/drm/i915/intel_hdcp.c b/drivers/gpu/drm/i915/intel_hdcp.c
> index f0ee448e6546..f1f0ef294e20 100644
> --- a/drivers/gpu/drm/i915/intel_hdcp.c
> +++ b/drivers/gpu/drm/i915/intel_hdcp.c
> @@ -18,6 +18,7 @@
>  
>  #define KEY_LOAD_TRIES	5
>  #define ENCRYPT_STATUS_CHANGE_TIMEOUT_MS	50
> +#define HDCP2_LC_RETRY_CNT			3
>  
>  static
>  bool intel_hdcp_is_ksv_valid(u8 *ksv)
> @@ -854,7 +855,7 @@ bool is_hdcp_supported(struct drm_i915_private *dev_priv, enum port port)
>  	return INTEL_GEN(dev_priv) >= 9 && port < PORT_E;
>  }
>  
> -static __attribute__((unused)) int
> +static int
>  hdcp2_prepare_ake_init(struct intel_connector *connector,
>  		       struct hdcp2_ake_init *ake_data)
>  {
> @@ -875,7 +876,7 @@ hdcp2_prepare_ake_init(struct intel_connector *connector,
>  	return ret;
>  }
>  
> -static __attribute__((unused)) int
> +static int
>  hdcp2_verify_rx_cert_prepare_km(struct intel_connector *connector,
>  				struct hdcp2_ake_send_cert *rx_cert,
>  				bool *paired,
> @@ -897,9 +898,8 @@ hdcp2_verify_rx_cert_prepare_km(struct intel_connector *connector,
>  	return ret;
>  }
>  
> -static __attribute__((unused)) int
> -hdcp2_verify_hprime(struct intel_connector *connector,
> -		    struct hdcp2_ake_send_hprime *rx_hprime)
> +static int hdcp2_verify_hprime(struct intel_connector *connector,
> +			       struct hdcp2_ake_send_hprime *rx_hprime)
>  {
>  	struct hdcp_port_data *data = &connector->hdcp.port_data;
>  	struct drm_i915_private *dev_priv = to_i915(connector->base.dev);
> @@ -913,7 +913,7 @@ hdcp2_verify_hprime(struct intel_connector *connector,
>  	return ret;
>  }
>  
> -static __attribute__((unused)) int
> +static int
>  hdcp2_store_pairing_info(struct intel_connector *connector,
>  			 struct hdcp2_ake_send_pairing_info *pairing_info)
>  {
> @@ -930,7 +930,7 @@ hdcp2_store_pairing_info(struct intel_connector *connector,
>  	return ret;
>  }
>  
> -static __attribute__((unused)) int
> +static int
>  hdcp2_prepare_lc_init(struct intel_connector *connector,
>  		      struct hdcp2_lc_init *lc_init)
>  {
> @@ -947,7 +947,7 @@ hdcp2_prepare_lc_init(struct intel_connector *connector,
>  	return ret;
>  }
>  
> -static __attribute__((unused)) int
> +static int
>  hdcp2_verify_lprime(struct intel_connector *connector,
>  		    struct hdcp2_lc_send_lprime *rx_lprime)
>  {
> @@ -963,9 +963,8 @@ hdcp2_verify_lprime(struct intel_connector *connector,
>  	return ret;
>  }
>  
> -static __attribute__((unused))
> -int hdcp2_prepare_skey(struct intel_connector *connector,
> -		       struct hdcp2_ske_send_eks *ske_data)
> +static int hdcp2_prepare_skey(struct intel_connector *connector,
> +			      struct hdcp2_ske_send_eks *ske_data)
>  {
>  	struct hdcp_port_data *data = &connector->hdcp.port_data;
>  	struct drm_i915_private *dev_priv = to_i915(connector->base.dev);
> @@ -1016,8 +1015,7 @@ hdcp2_verify_mprime(struct intel_connector *connector,
>  	return ret;
>  }
>  
> -static __attribute__((unused))
> -int hdcp2_authenticate_port(struct intel_connector *connector)
> +static int hdcp2_authenticate_port(struct intel_connector *connector)
>  {
>  	struct hdcp_port_data *data = &connector->hdcp.port_data;
>  	struct drm_i915_private *dev_priv = to_i915(connector->base.dev);
> @@ -1045,11 +1043,194 @@ static int hdcp2_deauthenticate_port(struct intel_connector *connector)
>  	return hdcp2_close_mei_session(connector);
>  }
>  
> +/* Authentication flow starts from here */
> +static int hdcp2_authentication_key_exchange(struct intel_connector *connector)
> +{
> +	struct intel_digital_port *intel_dig_port = conn_to_dig_port(connector);
> +	struct intel_hdcp *hdcp = &connector->hdcp;
> +	union {
> +		struct hdcp2_ake_init ake_init;
> +		struct hdcp2_ake_send_cert send_cert;
> +		struct hdcp2_ake_no_stored_km no_stored_km;
> +		struct hdcp2_ake_send_hprime send_hprime;
> +		struct hdcp2_ake_send_pairing_info pairing_info;
> +	} msgs;
> +	const struct intel_hdcp_shim *shim = hdcp->shim;
> +	size_t size;
> +	int ret;
> +	bool is_paired;
> +
> +	/* Init for seq_num */
> +	hdcp->seq_num_v = 0;
> +	hdcp->seq_num_m = 0;
> +
> +	ret = hdcp2_prepare_ake_init(connector, &msgs.ake_init);
> +	if (ret < 0)
> +		return ret;
> +
> +	ret = shim->write_2_2_msg(intel_dig_port, &msgs.ake_init,
> +				  sizeof(msgs.ake_init));
> +	if (ret < 0)
> +		return ret;
> +
> +	ret = shim->read_2_2_msg(intel_dig_port, HDCP_2_2_AKE_SEND_CERT,
> +				 &msgs.send_cert, sizeof(msgs.send_cert));
> +	if (ret < 0)
> +		return ret;

sink should give us the initial key with 100ms. I guess there's going to
be a patch later on to check that?

> +
> +	if (msgs.send_cert.rx_caps[0] != HDCP_2_2_RX_CAPS_VERSION_VAL)
> +		return -EINVAL;
> +
> +	hdcp->is_repeater = HDCP_2_2_RX_REPEATER(msgs.send_cert.rx_caps[2]) ?
> +			    1 : 0;

If you make is_repeater of type bool you can simplify this.

> +
> +	/*
> +	 * Here msgs.no_stored_km will hold msgs corresponding to the km
> +	 * stored also.
> +	 */
> +	ret = hdcp2_verify_rx_cert_prepare_km(connector, &msgs.send_cert,
> +					      &is_paired,
> +					      &msgs.no_stored_km, &size);
> +	if (ret < 0)
> +		return ret;
> +
> +	hdcp->is_paired = is_paired ? 1 : 0;

The ? 1 : 0 is redundant if you make is_paired type bool.
> +
> +	ret = shim->write_2_2_msg(intel_dig_port, &msgs.no_stored_km, size);
> +	if (ret < 0)
> +		return ret;
> +
> +	ret = shim->read_2_2_msg(intel_dig_port, HDCP_2_2_AKE_SEND_HPRIME,
> +				 &msgs.send_hprime, sizeof(msgs.send_hprime));
> +	if (ret < 0)
> +		return ret;
> +
> +	ret = hdcp2_verify_hprime(connector, &msgs.send_hprime);
> +	if (ret < 0)
> +		return ret;
> +
> +	if (!hdcp->is_paired) {
> +		/* Pairing is required */
> +		ret = shim->read_2_2_msg(intel_dig_port,
> +					 HDCP_2_2_AKE_SEND_PAIRING_INFO,
> +					 &msgs.pairing_info,
> +					 sizeof(msgs.pairing_info));
> +		if (ret < 0)
> +			return ret;
> +
> +		ret = hdcp2_store_pairing_info(connector, &msgs.pairing_info);
> +		if (ret < 0)
> +			return ret;
> +		hdcp->is_paired = 1;

s/1/true/

> +	}
> +
> +	return 0;
> +}
> +
> +static int hdcp2_locality_check(struct intel_connector *connector)
> +{
> +	struct intel_digital_port *intel_dig_port = conn_to_dig_port(connector);
> +	struct intel_hdcp *hdcp = &connector->hdcp;
> +	union {
> +		struct hdcp2_lc_init lc_init;
> +		struct hdcp2_lc_send_lprime send_lprime;
> +	} msgs;
> +	const struct intel_hdcp_shim *shim = hdcp->shim;
> +	int tries = HDCP2_LC_RETRY_CNT, ret, i;
> +
> +	for (i = 0; i < tries; i++) {
> +		ret = hdcp2_prepare_lc_init(connector, &msgs.lc_init);
> +		if (ret < 0)
> +			continue;
> +
> +		ret = shim->write_2_2_msg(intel_dig_port, &msgs.lc_init,
> +				      sizeof(msgs.lc_init));
> +		if (ret < 0)
> +			continue;
> +
> +		ret = shim->read_2_2_msg(intel_dig_port,
> +					 HDCP_2_2_LC_SEND_LPRIME,
> +					 &msgs.send_lprime,
> +					 sizeof(msgs.send_lprime));
> +		if (ret < 0)
> +			continue;
> +
> +		ret = hdcp2_verify_lprime(connector, &msgs.send_lprime);
> +		if (!ret)
> +			break;

We're not checking that the sink replies quickly enough here. Sink needs
to reply in 20ms. Can be a followup I guess.

Also just noticed that we seem to lack all these timing checks for hdcp1
too, at least we don't fail auth if the sink takes too long.

> +	}
> +
> +	return ret;
> +}
> +
> +static int hdcp2_session_key_exchange(struct intel_connector *connector)
> +{
> +	struct intel_digital_port *intel_dig_port = conn_to_dig_port(connector);
> +	struct intel_hdcp *hdcp = &connector->hdcp;
> +	struct hdcp2_ske_send_eks send_eks;
> +	int ret;
> +
> +	ret = hdcp2_prepare_skey(connector, &send_eks);
> +	if (ret < 0)
> +		return ret;
> +
> +	ret = hdcp->shim->write_2_2_msg(intel_dig_port, &send_eks,
> +					sizeof(send_eks));
> +	if (ret < 0)
> +		return ret;
> +
> +	return 0;
> +}
> +
>  static int hdcp2_authenticate_sink(struct intel_connector *connector)
>  {
> -	DRM_ERROR("Sink authentication is done in subsequent patches\n");
> +	struct intel_digital_port *intel_dig_port = conn_to_dig_port(connector);
> +	struct intel_hdcp *hdcp = &connector->hdcp;
> +	const struct intel_hdcp_shim *shim = hdcp->shim;
> +	struct hdcp2_dp_errata_stream_type stream_type_msg;
> +	int ret;
>  
> -	return -EINVAL;
> +	ret = hdcp2_authentication_key_exchange(connector);
> +	if (ret < 0) {
> +		DRM_DEBUG_KMS("AKE Failed. Err : %d\n", ret);
> +		return ret;
> +	}
> +
> +	ret = hdcp2_locality_check(connector);
> +	if (ret < 0) {
> +		DRM_DEBUG_KMS("Locality Check failed. Err : %d\n", ret);
> +		return ret;
> +	}
> +
> +	ret = hdcp2_session_key_exchange(connector);
> +	if (ret < 0) {
> +		DRM_DEBUG_KMS("SKE Failed. Err : %d\n", ret);
> +		return ret;
> +	}
> +
> +	if (!hdcp->is_repeater && shim->config_stream_type) {
> +		/*
> +		 * Errata for DP: As Stream type is used for encryption,
> +		 * Receiver should be communicated with stream type for the
> +		 * decryption of the content.
> +		 * Repeater will be communicated with stream type as a
> +		 * part of it's auth later in time.
> +		 */

I'm not following what you want to say with this comment, and haven't
found anything in the hdcp2 dp spec about this either.

> +		stream_type_msg.msg_id = HDCP_2_2_ERRATA_DP_STREAM_TYP:E;
> +		stream_type_msg.stream_type = hdcp->content_type;
> +
> +		ret = shim->config_stream_type(intel_dig_port, &stream_type_msg,
> +					       sizeof(stream_type_msg));
> +		if (ret < 0)
> +			return ret;
> +	}
> +
> +	hdcp->port_data.streams[0].stream_type = hdcp->content_type;
> +	ret = hdcp2_authenticate_port(connector);
> +	if (ret < 0)
> +		return ret;
> +
> +	return ret;
>  }

With thy types changed to bool and the dp errata cleared up somehow:

Reviewed-by: Daniel Vetter <daniel.vetter@ffwll.ch>

>  
>  static int hdcp2_enable_encryption(struct intel_connector *connector)
> -- 
> 2.7.4
> 

-- 
Daniel Vetter
Software Engineer, Intel Corporation
http://blog.ffwll.ch
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 103+ messages in thread

* Re: [PATCH v9 11/39] drm: helper functions for hdcp2 seq_num to from u32
  2018-12-13  4:01 ` [PATCH v9 11/39] drm: helper functions for hdcp2 seq_num to from u32 Ramalingam C
@ 2018-12-19 14:38   ` Daniel Vetter
  0 siblings, 0 replies; 103+ messages in thread
From: Daniel Vetter @ 2018-12-19 14:38 UTC (permalink / raw)
  To: Ramalingam C
  Cc: daniel.vetter, intel-gfx, dri-devel, uma.shankar, seanpaul,
	tomas.winkler

On Thu, Dec 13, 2018 at 09:31:13AM +0530, Ramalingam C wrote:
> Library functions for endianness are aligned for 16/32/64 bits.
> But hdcp sequence numbers are 24bits(big endian).
> So for their conversion to and from u32 helper functions are developed.
> 
> Signed-off-by: Ramalingam C <ramalingam.c@intel.com>
> ---
>  include/drm/drm_hdcp.h | 18 ++++++++++++++++++
>  1 file changed, 18 insertions(+)
> 
> diff --git a/include/drm/drm_hdcp.h b/include/drm/drm_hdcp.h
> index a6de09c5e47f..d8093ecf3ddc 100644
> --- a/include/drm/drm_hdcp.h
> +++ b/include/drm/drm_hdcp.h
> @@ -250,4 +250,22 @@ struct hdcp2_dp_errata_stream_type {
>  #define HDCP_2_2_HDMI_RXSTATUS_READY(x)		((x) & BIT(2))
>  #define HDCP_2_2_HDMI_RXSTATUS_REAUTH_REQ(x)	((x) & BIT(3))
>  
> +/*
> + * Library functions for endianness are aligned for 16/32/64 bits.
> + * But hdcp sequence numbers are 24bits(big endian). So for their conversion
> + * from and to u32 below functions are developed.

Comment is a bit confusing, I'd do a simple:

/*
 * Helper functions to convert 24bit big endian hdcp sequence number to
 * host format and back
 */

Explaining why we need them exactly isn't terribly interesting.

> + */
> +static inline void
> +drm_hdcp2_seq_num_to_u32(u32 *val, u8 seq_num[HDCP_2_2_SEQ_NUM_LEN])

make u32 val the return value of this function, should be cleaner.

> +{
> +	*val = seq_num[2] | seq_num[1] << 8 | seq_num[0] << 16;
> +}
> +
> +static inline void drm_hdcp2_u32_to_seq_num(u8 *seq_num, u32 val)

u8 seq_num[HDCP_2_2_SEQ_NUM_LEN]. Not any different in the actual function
type, just a bit more informative.


> +{
> +	seq_num[0] = (val & (0xff << 16)) >> 16;
> +	seq_num[1] = (val & (0xff << 8)) >> 8;

Shift alone should be enough, since seq_num[x] is of type u8 the & 0xff is
implied.

With the above comments addressed:

Reviewed-by: Daniel Vetter <daniel.vetter@ffwll.ch>


> +	seq_num[2] = val & 0xff;
> +}
> +
>  #endif
> -- 
> 2.7.4
> 

-- 
Daniel Vetter
Software Engineer, Intel Corporation
http://blog.ffwll.ch
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 103+ messages in thread

* Re: [PATCH v9 12/39] drm/i915: Implement HDCP2.2 repeater authentication
  2018-12-13  4:01 ` [PATCH v9 12/39] drm/i915: Implement HDCP2.2 repeater authentication Ramalingam C
  2018-12-13  8:22   ` Winkler, Tomas
@ 2018-12-19 14:48   ` Daniel Vetter
  2018-12-19 15:35     ` C, Ramalingam
  1 sibling, 1 reply; 103+ messages in thread
From: Daniel Vetter @ 2018-12-19 14:48 UTC (permalink / raw)
  To: Ramalingam C
  Cc: daniel.vetter, intel-gfx, dri-devel, uma.shankar, seanpaul,
	tomas.winkler

On Thu, Dec 13, 2018 at 09:31:14AM +0530, Ramalingam C wrote:
> Implements the HDCP2.2 repeaters authentication steps such as verifying
> the downstream topology and sending stream management information.
> 
> v2: Rebased.
> v3:
>   -EINVAL is returned for topology error and rollover scenario.
>   Endianness conversion func from drm_hdcp.h is used [Uma]
> v4:
>   Rebased as part of patches reordering.
>   Defined the mei service functions [Daniel]
> v5:
>   Redefined the mei service functions as per comp redesign.
> v6:
>   %s/uintxx_t/uxx
>   Check for comp_master is removed.
> v7:
>   Adjust to the new mei interface.
>   style issue fixed.
> v8:
>   drm_hdcp.h change is moved into separate patch [Daniel]
> 
> Signed-off-by: Ramalingam C <ramalingam.c@intel.com>
> ---
>  drivers/gpu/drm/i915/intel_hdcp.c | 123 +++++++++++++++++++++++++++++++++++++-
>  1 file changed, 121 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/intel_hdcp.c b/drivers/gpu/drm/i915/intel_hdcp.c
> index f1f0ef294e20..b52da5c3159d 100644
> --- a/drivers/gpu/drm/i915/intel_hdcp.c
> +++ b/drivers/gpu/drm/i915/intel_hdcp.c
> @@ -978,7 +978,7 @@ static int hdcp2_prepare_skey(struct intel_connector *connector,
>  	return ret;
>  }
>  
> -static __attribute__((unused)) int
> +static int
>  hdcp2_verify_rep_topology_prepare_ack(struct intel_connector *connector,
>  				      struct hdcp2_rep_send_receiverid_list
>  								*rep_topology,
> @@ -999,7 +999,7 @@ hdcp2_verify_rep_topology_prepare_ack(struct intel_connector *connector,
>  	return ret;
>  }
>  
> -static __attribute__((unused)) int
> +static int
>  hdcp2_verify_mprime(struct intel_connector *connector,
>  		    struct hdcp2_rep_stream_ready *stream_ready)
>  {
> @@ -1182,6 +1182,119 @@ static int hdcp2_session_key_exchange(struct intel_connector *connector)
>  	return 0;
>  }
>  
> +static
> +int hdcp2_propagate_stream_management_info(struct intel_connector *connector)
> +{
> +	struct intel_digital_port *intel_dig_port = conn_to_dig_port(connector);
> +	struct intel_hdcp *hdcp = &connector->hdcp;
> +	union {
> +		struct hdcp2_rep_stream_manage stream_manage;
> +		struct hdcp2_rep_stream_ready stream_ready;
> +	} msgs;
> +	const struct intel_hdcp_shim *shim = hdcp->shim;
> +	int ret;
> +
> +	/* Prepare RepeaterAuth_Stream_Manage msg */
> +	msgs.stream_manage.msg_id = HDCP_2_2_REP_STREAM_MANAGE;
> +	drm_hdcp2_u32_to_seq_num(msgs.stream_manage.seq_num_m, hdcp->seq_num_m);
> +
> +	/* K no of streams is fixed as 1. Stored as big-endian. */
> +	msgs.stream_manage.k = __swab16(1);
> +
> +	/* For HDMI this is forced to be 0x0. For DP SST also this is 0x0. */
> +	msgs.stream_manage.streams[0].stream_id = 0;
> +	msgs.stream_manage.streams[0].stream_type = hdcp->content_type;
> +
> +	/* Send it to Repeater */
> +	ret = shim->write_2_2_msg(intel_dig_port, &msgs.stream_manage,
> +				  sizeof(msgs.stream_manage));
> +	if (ret < 0)
> +		return ret;
> +
> +	ret = shim->read_2_2_msg(intel_dig_port, HDCP_2_2_REP_STREAM_READY,
> +				 &msgs.stream_ready, sizeof(msgs.stream_ready));
> +	if (ret < 0)
> +		return ret;
> +
> +	hdcp->port_data.seq_num_m = hdcp->seq_num_m;
> +	hdcp->port_data.streams[0].stream_type = hdcp->content_type;
> +
> +	ret = hdcp2_verify_mprime(connector, &msgs.stream_ready);
> +	if (ret < 0)
> +		return ret;
> +
> +	hdcp->seq_num_m++;
> +
> +	if (hdcp->seq_num_m > HDCP_2_2_SEQ_NUM_MAX) {
> +		DRM_DEBUG_KMS("seq_num_m roll over.\n");
> +		return -1;
> +	}
> +
> +	return 0;
> +}
> +
> +static
> +int hdcp2_authenticate_repeater_topology(struct intel_connector *connector)
> +{
> +	struct intel_digital_port *intel_dig_port = conn_to_dig_port(connector);
> +	struct intel_hdcp *hdcp = &connector->hdcp;
> +	union {
> +		struct hdcp2_rep_send_receiverid_list recvid_list;
> +		struct hdcp2_rep_send_ack rep_ack;
> +	} msgs;
> +	const struct intel_hdcp_shim *shim = hdcp->shim;
> +	u8 *rx_info;
> +	u32 seq_num_v;
> +	int ret;
> +
> +	ret = shim->read_2_2_msg(intel_dig_port, HDCP_2_2_REP_SEND_RECVID_LIST,
> +				 &msgs.recvid_list, sizeof(msgs.recvid_list));
> +	if (ret < 0)
> +		return ret;
> +
> +	rx_info = msgs.recvid_list.rx_info;

There's a 2s timeout here that we're not checking, but again probably
follow-up patch.

> +
> +	if (HDCP_2_2_MAX_CASCADE_EXCEEDED(rx_info[1]) ||
> +	    HDCP_2_2_MAX_DEVS_EXCEEDED(rx_info[1])) {
> +		DRM_DEBUG_KMS("Topology Max Size Exceeded\n");
> +		return -EINVAL;
> +	}
> +
> +	/* Converting and Storing the seq_num_v to local variable as DWORD */
> +	drm_hdcp2_seq_num_to_u32(&seq_num_v, msgs.recvid_list.seq_num_v);
> +
> +	if (seq_num_v < hdcp->seq_num_v) {
> +		/* Roll over of the seq_num_v from repeater. Reauthenticate. */
> +		DRM_DEBUG_KMS("Seq_num_v roll over.\n");
> +		return -EINVAL;
> +	}
> +
> +	ret = hdcp2_verify_rep_topology_prepare_ack(connector,
> +						    &msgs.recvid_list,
> +						    &msgs.rep_ack);
> +	if (ret < 0)
> +		return ret;

Spec talks about type0 vs type1 here, but for now we can ignore that.

> +
> +	hdcp->seq_num_v = seq_num_v;
> +	ret = shim->write_2_2_msg(intel_dig_port, &msgs.rep_ack,
> +				  sizeof(msgs.rep_ack));
> +	if (ret < 0)
> +		return ret;
> +
> +	return 0;
> +}
> +
> +static int hdcp2_authenticate_repeater(struct intel_connector *connector)
> +{
> +	int ret;
> +
> +	ret = hdcp2_authenticate_repeater_topology(connector);
> +	if (ret < 0)
> +		return ret;
> +
> +	return hdcp2_propagate_stream_management_info(connector);
> +}
> +
>  static int hdcp2_authenticate_sink(struct intel_connector *connector)
>  {
>  	struct intel_digital_port *intel_dig_port = conn_to_dig_port(connector);
> @@ -1223,6 +1336,12 @@ static int hdcp2_authenticate_sink(struct intel_connector *connector)
>  					       sizeof(stream_type_msg));
>  		if (ret < 0)
>  			return ret;
> +	} else if (hdcp->is_repeater) {
> +		ret = hdcp2_authenticate_repeater(connector);
> +		if (ret < 0) {
> +			DRM_DEBUG_KMS("Repeater Auth Failed. Err: %d\n", ret);
> +			return ret;
> +		}
>  	}

Spec for receiver auth is a bit more confusing than usual, but I think
this matches.

Reviewed-by: Daniel Vetter <daniel.vetter@ffwll.ch>
>  
>  	hdcp->port_data.streams[0].stream_type = hdcp->content_type;
> -- 
> 2.7.4
> 

-- 
Daniel Vetter
Software Engineer, Intel Corporation
http://blog.ffwll.ch
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 103+ messages in thread

* Re: [PATCH v9 04/39] component: alloc component_match without any comp to match
  2018-12-19 13:42   ` Daniel Vetter
@ 2018-12-19 15:04       ` Greg Kroah-Hartman
  0 siblings, 0 replies; 103+ messages in thread
From: Greg Kroah-Hartman @ 2018-12-19 15:04 UTC (permalink / raw)
  To: Ramalingam C, intel-gfx, dri-devel, seanpaul, tomas.winkler,
	uma.shankar, ville.syrjala, chris, Kate Stewart, Thomas Gleixner,
	Philippe Ombredanne, linux-kernel

On Wed, Dec 19, 2018 at 02:42:45PM +0100, Daniel Vetter wrote:
> On Thu, Dec 13, 2018 at 09:31:06AM +0530, Ramalingam C wrote:
> > If all the components associated to a component master is not added
> > to the component framework due to the HW capability or Kconfig
> > selection, component_match will be NULL at
> > component_master_add_with_match().
> > 
> > To avoid this, component_match_alloc() is added to the framework,
> > to allcoate the struct component_match with zero associated components.
> > Hence component master can be added with a component_match with zero
> > associated components.
> > 
> > This helps the component master bind call to get triggered,
> > even if no component is registered for that particular master.
> > 
> > This is meant for big PCI device drivers where small/optional
> > features are external components, and based on usecases different
> > combination of components are build as entire driver.
> > 
> > In such PCI device driver Load, if we use the component master for
> > waiting for few  components(features) availability, only if they are
> > supported by the underlying HW, then we need to allocate memory for
> > component_match using the API introduced in this change before
> > the call to component_master_add_with_match.
> > 
> > v2:
> >   No Change.
> > 
> > Signed-off-by: Ramalingam C <ramalingam.c@intel.com>
> > Suggested-by: Daniel Vetter <daniel.vetter@ffwll.ch>
> > Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
> > Cc: Kate Stewart <kstewart@linuxfoundation.org>
> > Cc: Thomas Gleixner <tglx@linutronix.de>
> > Cc: Philippe Ombredanne <pombredanne@nexb.com>
> > Cc: linux-kernel@vger.kernel.org
> 
> Reviewed-by: Daniel Vetter <daniel.vetter@ffwll.ch>
> 
> Greg, I expect the i915 feature that needs this will only land in 4.22.
> I'm also not aware of anyone else using this (all the other component
> users always use components). How do you want to get this landed?
> 
> I think either getting this into 4.21, or an ack for merging through drm
> trees would work well for us.

I have no objection to you taking this through the drm tree.  As I
really do not know the component code at all (that would be Russell
King), feel free to add my:

	Acked-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

as it looks sane to me.

thanks,

greg k-h

^ permalink raw reply	[flat|nested] 103+ messages in thread

* Re: [PATCH v9 04/39] component: alloc component_match without any comp to match
@ 2018-12-19 15:04       ` Greg Kroah-Hartman
  0 siblings, 0 replies; 103+ messages in thread
From: Greg Kroah-Hartman @ 2018-12-19 15:04 UTC (permalink / raw)
  To: Ramalingam C, intel-gfx, dri-devel, seanpaul, tomas.winkler,
	uma.shankar, ville.syrjala, chris, Kate Stewart, Thomas Gleixner,
	Philippe Ombredanne, linux-kernel

On Wed, Dec 19, 2018 at 02:42:45PM +0100, Daniel Vetter wrote:
> On Thu, Dec 13, 2018 at 09:31:06AM +0530, Ramalingam C wrote:
> > If all the components associated to a component master is not added
> > to the component framework due to the HW capability or Kconfig
> > selection, component_match will be NULL at
> > component_master_add_with_match().
> > 
> > To avoid this, component_match_alloc() is added to the framework,
> > to allcoate the struct component_match with zero associated components.
> > Hence component master can be added with a component_match with zero
> > associated components.
> > 
> > This helps the component master bind call to get triggered,
> > even if no component is registered for that particular master.
> > 
> > This is meant for big PCI device drivers where small/optional
> > features are external components, and based on usecases different
> > combination of components are build as entire driver.
> > 
> > In such PCI device driver Load, if we use the component master for
> > waiting for few  components(features) availability, only if they are
> > supported by the underlying HW, then we need to allocate memory for
> > component_match using the API introduced in this change before
> > the call to component_master_add_with_match.
> > 
> > v2:
> >   No Change.
> > 
> > Signed-off-by: Ramalingam C <ramalingam.c@intel.com>
> > Suggested-by: Daniel Vetter <daniel.vetter@ffwll.ch>
> > Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
> > Cc: Kate Stewart <kstewart@linuxfoundation.org>
> > Cc: Thomas Gleixner <tglx@linutronix.de>
> > Cc: Philippe Ombredanne <pombredanne@nexb.com>
> > Cc: linux-kernel@vger.kernel.org
> 
> Reviewed-by: Daniel Vetter <daniel.vetter@ffwll.ch>
> 
> Greg, I expect the i915 feature that needs this will only land in 4.22.
> I'm also not aware of anyone else using this (all the other component
> users always use components). How do you want to get this landed?
> 
> I think either getting this into 4.21, or an ack for merging through drm
> trees would work well for us.

I have no objection to you taking this through the drm tree.  As I
really do not know the component code at all (that would be Russell
King), feel free to add my:

	Acked-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

as it looks sane to me.

thanks,

greg k-h
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 103+ messages in thread

* Re: [PATCH v9 10/39] drm/i915: Implement HDCP2.2 receiver authentication
  2018-12-19 14:35   ` Daniel Vetter
@ 2018-12-19 15:05     ` C, Ramalingam
  2018-12-19 15:35       ` Daniel Vetter
  2018-12-19 18:40       ` Jani Nikula
  0 siblings, 2 replies; 103+ messages in thread
From: C, Ramalingam @ 2018-12-19 15:05 UTC (permalink / raw)
  To: Daniel Vetter
  Cc: daniel.vetter, intel-gfx, dri-devel, uma.shankar, seanpaul,
	tomas.winkler


[-- Attachment #1.1: Type: text/plain, Size: 14580 bytes --]


On 12/19/2018 8:05 PM, Daniel Vetter wrote:
> On Thu, Dec 13, 2018 at 09:31:12AM +0530, Ramalingam C wrote:
>> Implements HDCP2.2 authentication for hdcp2.2 receivers, with
>> following steps:
>> 	Authentication and Key exchange (AKE).
>> 	Locality Check (LC).
>> 	Session Key Exchange(SKE).
>> 	DP Errata for stream type configuration for receivers.
>>
>> At AKE, the HDCP Receiver’s public key certificate is verified by the
>> HDCP Transmitter. A Master Key k m is exchanged.
>>
>> At LC, the HDCP Transmitter enforces locality on the content by
>> requiring that the Round Trip Time (RTT) between a pair of messages
>> is not more than 20 ms.
>>
>> At SKE, The HDCP Transmitter exchanges Session Key ks with
>> the HDCP Receiver.
>>
>> In DP HDCP2.2 encryption and decryption logics use the stream type as
>> one of the parameter. So Before enabling the Encryption DP HDCP2.2
>> receiver needs to be communicated with stream type. This is added to
>> spec as ERRATA.
>>
>> This generic implementation is complete only with the hdcp2 specific
>> functions defined at hdcp_shim.
>>
>> v2: Rebased.
>> v3:
>>    %s/PARING/PAIRING
>>    Coding style fixing [Uma]
>> v4:
>>    Rebased as part of patch reordering.
>>    Defined the functions for mei services. [Daniel]
>> v5:
>>    Redefined the mei service functions as per comp redesign.
>>    Required intel_hdcp members are defined [Sean Paul]
>> v6:
>>    Typo of cipher is Fixed [Uma]
>>    %s/uintxx_t/uxx
>>    Check for comp_master is removed.
>> v7:
>>    Adjust to the new interface.
>>    Avoid using bool structure members. [Tomas]
>> v8: Rebased.
>>
>> Signed-off-by: Ramalingam C <ramalingam.c@intel.com>
>> ---
>>   drivers/gpu/drm/i915/intel_drv.h  |  34 ++++++
>>   drivers/gpu/drm/i915/intel_hdcp.c | 211 +++++++++++++++++++++++++++++++++++---
>>   2 files changed, 230 insertions(+), 15 deletions(-)
>>
>> diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
>> index 6d5361616ca3..a6b632d71490 100644
>> --- a/drivers/gpu/drm/i915/intel_drv.h
>> +++ b/drivers/gpu/drm/i915/intel_drv.h
>> @@ -387,6 +387,22 @@ struct intel_hdcp_shim {
>>   	/* Detects whether Panel is HDCP2.2 capable */
>>   	int (*hdcp_2_2_capable)(struct intel_digital_port *intel_dig_port,
>>   				bool *capable);
>> +
>> +	/* Write HDCP2.2 messages */
>> +	int (*write_2_2_msg)(struct intel_digital_port *intel_dig_port,
>> +			     void *buf, size_t size);
>> +
>> +	/* Read HDCP2.2 messages */
>> +	int (*read_2_2_msg)(struct intel_digital_port *intel_dig_port,
>> +			    u8 msg_id, void *buf, size_t size);
>> +
>> +	/*
>> +	 * Implementation of DP HDCP2.2 Errata for the communication of stream
>> +	 * type to Receivers. In DP HDCP2.2 Stream type is one of the input to
>> +	 * the HDCP2.2 Cipher for En/De-Cryption. Not applicable for HDMI.
>> +	 */
>> +	int (*config_stream_type)(struct intel_digital_port *intel_dig_port,
>> +				  void *buf, size_t size);
>>   };
>>   
>>   struct intel_hdcp {
>> @@ -414,6 +430,24 @@ struct intel_hdcp {
>>   	 */
>>   	u8 content_type;
>>   	struct hdcp_port_data port_data;
>> +
>> +	u8 is_paired;
>> +	u8 is_repeater;
> Make these two bool, will simplify the code a bunch.

Seems there is a movement for not to use the bool in structures.
Thats why I have changed these from bool to u8 from v8 onwards. Checkpatch also complains on this

>
>> +
>> +	/*
>> +	 * Count of ReceiverID_List received. Initialized to 0 at AKE_INIT.
>> +	 * Incremented after processing the RepeaterAuth_Send_ReceiverID_List.
>> +	 * When it rolls over re-auth has to be triggered.
>> +	 */
>> +	u32 seq_num_v;
>> +
>> +	/*
>> +	 * Count of RepeaterAuth_Stream_Manage msg propagated.
>> +	 * Initialized to 0 on AKE_INIT. Incremented after every successful
>> +	 * transmission of RepeaterAuth_Stream_Manage message. When it rolls
>> +	 * over re-Auth has to be triggered.
>> +	 */
>> +	u32 seq_num_m;
>>   };
>>   
>>   struct intel_connector {
>> diff --git a/drivers/gpu/drm/i915/intel_hdcp.c b/drivers/gpu/drm/i915/intel_hdcp.c
>> index f0ee448e6546..f1f0ef294e20 100644
>> --- a/drivers/gpu/drm/i915/intel_hdcp.c
>> +++ b/drivers/gpu/drm/i915/intel_hdcp.c
>> @@ -18,6 +18,7 @@
>>   
>>   #define KEY_LOAD_TRIES	5
>>   #define ENCRYPT_STATUS_CHANGE_TIMEOUT_MS	50
>> +#define HDCP2_LC_RETRY_CNT			3
>>   
>>   static
>>   bool intel_hdcp_is_ksv_valid(u8 *ksv)
>> @@ -854,7 +855,7 @@ bool is_hdcp_supported(struct drm_i915_private *dev_priv, enum port port)
>>   	return INTEL_GEN(dev_priv) >= 9 && port < PORT_E;
>>   }
>>   
>> -static __attribute__((unused)) int
>> +static int
>>   hdcp2_prepare_ake_init(struct intel_connector *connector,
>>   		       struct hdcp2_ake_init *ake_data)
>>   {
>> @@ -875,7 +876,7 @@ hdcp2_prepare_ake_init(struct intel_connector *connector,
>>   	return ret;
>>   }
>>   
>> -static __attribute__((unused)) int
>> +static int
>>   hdcp2_verify_rx_cert_prepare_km(struct intel_connector *connector,
>>   				struct hdcp2_ake_send_cert *rx_cert,
>>   				bool *paired,
>> @@ -897,9 +898,8 @@ hdcp2_verify_rx_cert_prepare_km(struct intel_connector *connector,
>>   	return ret;
>>   }
>>   
>> -static __attribute__((unused)) int
>> -hdcp2_verify_hprime(struct intel_connector *connector,
>> -		    struct hdcp2_ake_send_hprime *rx_hprime)
>> +static int hdcp2_verify_hprime(struct intel_connector *connector,
>> +			       struct hdcp2_ake_send_hprime *rx_hprime)
>>   {
>>   	struct hdcp_port_data *data = &connector->hdcp.port_data;
>>   	struct drm_i915_private *dev_priv = to_i915(connector->base.dev);
>> @@ -913,7 +913,7 @@ hdcp2_verify_hprime(struct intel_connector *connector,
>>   	return ret;
>>   }
>>   
>> -static __attribute__((unused)) int
>> +static int
>>   hdcp2_store_pairing_info(struct intel_connector *connector,
>>   			 struct hdcp2_ake_send_pairing_info *pairing_info)
>>   {
>> @@ -930,7 +930,7 @@ hdcp2_store_pairing_info(struct intel_connector *connector,
>>   	return ret;
>>   }
>>   
>> -static __attribute__((unused)) int
>> +static int
>>   hdcp2_prepare_lc_init(struct intel_connector *connector,
>>   		      struct hdcp2_lc_init *lc_init)
>>   {
>> @@ -947,7 +947,7 @@ hdcp2_prepare_lc_init(struct intel_connector *connector,
>>   	return ret;
>>   }
>>   
>> -static __attribute__((unused)) int
>> +static int
>>   hdcp2_verify_lprime(struct intel_connector *connector,
>>   		    struct hdcp2_lc_send_lprime *rx_lprime)
>>   {
>> @@ -963,9 +963,8 @@ hdcp2_verify_lprime(struct intel_connector *connector,
>>   	return ret;
>>   }
>>   
>> -static __attribute__((unused))
>> -int hdcp2_prepare_skey(struct intel_connector *connector,
>> -		       struct hdcp2_ske_send_eks *ske_data)
>> +static int hdcp2_prepare_skey(struct intel_connector *connector,
>> +			      struct hdcp2_ske_send_eks *ske_data)
>>   {
>>   	struct hdcp_port_data *data = &connector->hdcp.port_data;
>>   	struct drm_i915_private *dev_priv = to_i915(connector->base.dev);
>> @@ -1016,8 +1015,7 @@ hdcp2_verify_mprime(struct intel_connector *connector,
>>   	return ret;
>>   }
>>   
>> -static __attribute__((unused))
>> -int hdcp2_authenticate_port(struct intel_connector *connector)
>> +static int hdcp2_authenticate_port(struct intel_connector *connector)
>>   {
>>   	struct hdcp_port_data *data = &connector->hdcp.port_data;
>>   	struct drm_i915_private *dev_priv = to_i915(connector->base.dev);
>> @@ -1045,11 +1043,194 @@ static int hdcp2_deauthenticate_port(struct intel_connector *connector)
>>   	return hdcp2_close_mei_session(connector);
>>   }
>>   
>> +/* Authentication flow starts from here */
>> +static int hdcp2_authentication_key_exchange(struct intel_connector *connector)
>> +{
>> +	struct intel_digital_port *intel_dig_port = conn_to_dig_port(connector);
>> +	struct intel_hdcp *hdcp = &connector->hdcp;
>> +	union {
>> +		struct hdcp2_ake_init ake_init;
>> +		struct hdcp2_ake_send_cert send_cert;
>> +		struct hdcp2_ake_no_stored_km no_stored_km;
>> +		struct hdcp2_ake_send_hprime send_hprime;
>> +		struct hdcp2_ake_send_pairing_info pairing_info;
>> +	} msgs;
>> +	const struct intel_hdcp_shim *shim = hdcp->shim;
>> +	size_t size;
>> +	int ret;
>> +	bool is_paired;
>> +
>> +	/* Init for seq_num */
>> +	hdcp->seq_num_v = 0;
>> +	hdcp->seq_num_m = 0;
>> +
>> +	ret = hdcp2_prepare_ake_init(connector, &msgs.ake_init);
>> +	if (ret < 0)
>> +		return ret;
>> +
>> +	ret = shim->write_2_2_msg(intel_dig_port, &msgs.ake_init,
>> +				  sizeof(msgs.ake_init));
>> +	if (ret < 0)
>> +		return ret;
>> +
>> +	ret = shim->read_2_2_msg(intel_dig_port, HDCP_2_2_AKE_SEND_CERT,
>> +				 &msgs.send_cert, sizeof(msgs.send_cert));
>> +	if (ret < 0)
>> +		return ret;
> sink should give us the initial key with 100ms. I guess there's going to
> be a patch later on to check that?
Timings are checked at read_2_2_msg as per the msg_id
>
>> +
>> +	if (msgs.send_cert.rx_caps[0] != HDCP_2_2_RX_CAPS_VERSION_VAL)
>> +		return -EINVAL;
>> +
>> +	hdcp->is_repeater = HDCP_2_2_RX_REPEATER(msgs.send_cert.rx_caps[2]) ?
>> +			    1 : 0;
> If you make is_repeater of type bool you can simplify this.
Yes. But it is advised to not to use bool in struct
>
>> +
>> +	/*
>> +	 * Here msgs.no_stored_km will hold msgs corresponding to the km
>> +	 * stored also.
>> +	 */
>> +	ret = hdcp2_verify_rx_cert_prepare_km(connector, &msgs.send_cert,
>> +					      &is_paired,
>> +					      &msgs.no_stored_km, &size);
>> +	if (ret < 0)
>> +		return ret;
>> +
>> +	hdcp->is_paired = is_paired ? 1 : 0;
> The ? 1 : 0 is redundant if you make is_paired type bool.
>> +
>> +	ret = shim->write_2_2_msg(intel_dig_port, &msgs.no_stored_km, size);
>> +	if (ret < 0)
>> +		return ret;
>> +
>> +	ret = shim->read_2_2_msg(intel_dig_port, HDCP_2_2_AKE_SEND_HPRIME,
>> +				 &msgs.send_hprime, sizeof(msgs.send_hprime));
>> +	if (ret < 0)
>> +		return ret;
>> +
>> +	ret = hdcp2_verify_hprime(connector, &msgs.send_hprime);
>> +	if (ret < 0)
>> +		return ret;
>> +
>> +	if (!hdcp->is_paired) {
>> +		/* Pairing is required */
>> +		ret = shim->read_2_2_msg(intel_dig_port,
>> +					 HDCP_2_2_AKE_SEND_PAIRING_INFO,
>> +					 &msgs.pairing_info,
>> +					 sizeof(msgs.pairing_info));
>> +		if (ret < 0)
>> +			return ret;
>> +
>> +		ret = hdcp2_store_pairing_info(connector, &msgs.pairing_info);
>> +		if (ret < 0)
>> +			return ret;
>> +		hdcp->is_paired = 1;
> s/1/true/
>
>> +	}
>> +
>> +	return 0;
>> +}
>> +
>> +static int hdcp2_locality_check(struct intel_connector *connector)
>> +{
>> +	struct intel_digital_port *intel_dig_port = conn_to_dig_port(connector);
>> +	struct intel_hdcp *hdcp = &connector->hdcp;
>> +	union {
>> +		struct hdcp2_lc_init lc_init;
>> +		struct hdcp2_lc_send_lprime send_lprime;
>> +	} msgs;
>> +	const struct intel_hdcp_shim *shim = hdcp->shim;
>> +	int tries = HDCP2_LC_RETRY_CNT, ret, i;
>> +
>> +	for (i = 0; i < tries; i++) {
>> +		ret = hdcp2_prepare_lc_init(connector, &msgs.lc_init);
>> +		if (ret < 0)
>> +			continue;
>> +
>> +		ret = shim->write_2_2_msg(intel_dig_port, &msgs.lc_init,
>> +				      sizeof(msgs.lc_init));
>> +		if (ret < 0)
>> +			continue;
>> +
>> +		ret = shim->read_2_2_msg(intel_dig_port,
>> +					 HDCP_2_2_LC_SEND_LPRIME,
>> +					 &msgs.send_lprime,
>> +					 sizeof(msgs.send_lprime));
>> +		if (ret < 0)
>> +			continue;
>> +
>> +		ret = hdcp2_verify_lprime(connector, &msgs.send_lprime);
>> +		if (!ret)
>> +			break;
> We're not checking that the sink replies quickly enough here. Sink needs
> to reply in 20ms. Can be a followup I guess.
>
> Also just noticed that we seem to lack all these timing checks for hdcp1
> too, at least we don't fail auth if the sink takes too long.
Shim takes care of it. It we dont compliance will fail.
>
>> +	}
>> +
>> +	return ret;
>> +}
>> +
>> +static int hdcp2_session_key_exchange(struct intel_connector *connector)
>> +{
>> +	struct intel_digital_port *intel_dig_port = conn_to_dig_port(connector);
>> +	struct intel_hdcp *hdcp = &connector->hdcp;
>> +	struct hdcp2_ske_send_eks send_eks;
>> +	int ret;
>> +
>> +	ret = hdcp2_prepare_skey(connector, &send_eks);
>> +	if (ret < 0)
>> +		return ret;
>> +
>> +	ret = hdcp->shim->write_2_2_msg(intel_dig_port, &send_eks,
>> +					sizeof(send_eks));
>> +	if (ret < 0)
>> +		return ret;
>> +
>> +	return 0;
>> +}
>> +
>>   static int hdcp2_authenticate_sink(struct intel_connector *connector)
>>   {
>> -	DRM_ERROR("Sink authentication is done in subsequent patches\n");
>> +	struct intel_digital_port *intel_dig_port = conn_to_dig_port(connector);
>> +	struct intel_hdcp *hdcp = &connector->hdcp;
>> +	const struct intel_hdcp_shim *shim = hdcp->shim;
>> +	struct hdcp2_dp_errata_stream_type stream_type_msg;
>> +	int ret;
>>   
>> -	return -EINVAL;
>> +	ret = hdcp2_authentication_key_exchange(connector);
>> +	if (ret < 0) {
>> +		DRM_DEBUG_KMS("AKE Failed. Err : %d\n", ret);
>> +		return ret;
>> +	}
>> +
>> +	ret = hdcp2_locality_check(connector);
>> +	if (ret < 0) {
>> +		DRM_DEBUG_KMS("Locality Check failed. Err : %d\n", ret);
>> +		return ret;
>> +	}
>> +
>> +	ret = hdcp2_session_key_exchange(connector);
>> +	if (ret < 0) {
>> +		DRM_DEBUG_KMS("SKE Failed. Err : %d\n", ret);
>> +		return ret;
>> +	}
>> +
>> +	if (!hdcp->is_repeater && shim->config_stream_type) {
>> +		/*
>> +		 * Errata for DP: As Stream type is used for encryption,
>> +		 * Receiver should be communicated with stream type for the
>> +		 * decryption of the content.
>> +		 * Repeater will be communicated with stream type as a
>> +		 * part of it's auth later in time.
>> +		 */
> I'm not following what you want to say with this comment, and haven't
> found anything in the hdcp2 dp spec about this either.

this is there in the errata of DP HDCP2.2 spec.
hdcp2.2 encryption algo involves the stream type as a parameter.
And as part of hdcp auth mentioned in base spec DP repeaters receive that details to decrypt the content.
But DP receivers dont get it. So errata adds the missing piece for decryption.

-Ram

>
>> +		stream_type_msg.msg_id = HDCP_2_2_ERRATA_DP_STREAM_TYP:E;
>> +		stream_type_msg.stream_type = hdcp->content_type;
>> +
>> +		ret = shim->config_stream_type(intel_dig_port, &stream_type_msg,
>> +					       sizeof(stream_type_msg));
>> +		if (ret < 0)
>> +			return ret;
>> +	}
>> +
>> +	hdcp->port_data.streams[0].stream_type = hdcp->content_type;
>> +	ret = hdcp2_authenticate_port(connector);
>> +	if (ret < 0)
>> +		return ret;
>> +
>> +	return ret;
>>   }
> With thy types changed to bool and the dp errata cleared up somehow:
>
> Reviewed-by: Daniel Vetter <daniel.vetter@ffwll.ch>
>
>>   
>>   static int hdcp2_enable_encryption(struct intel_connector *connector)
>> -- 
>> 2.7.4
>>

[-- Attachment #1.2: Type: text/html, Size: 16290 bytes --]

[-- Attachment #2: Type: text/plain, Size: 160 bytes --]

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 103+ messages in thread

* Re: [PATCH v9 07/39] drm/i915: MEI interface definition
  2018-12-19 14:00   ` Daniel Vetter
@ 2018-12-19 15:15     ` C, Ramalingam
  2018-12-19 15:21       ` Daniel Vetter
  0 siblings, 1 reply; 103+ messages in thread
From: C, Ramalingam @ 2018-12-19 15:15 UTC (permalink / raw)
  To: Daniel Vetter
  Cc: daniel.vetter, intel-gfx, dri-devel, seanpaul, tomas.winkler


[-- Attachment #1.1: Type: text/plain, Size: 13673 bytes --]


On 12/19/2018 7:30 PM, Daniel Vetter wrote:
> On Thu, Dec 13, 2018 at 09:31:09AM +0530, Ramalingam C wrote:
>> Defining the mei-i915 interface functions and initialization of
>> the interface.
>>
>> v2:
>>    Adjust to the new interface changes. [Tomas]
>>    Added further debug logs for the failures at MEI i/f.
>>    port in hdcp_port data is equipped to handle -ve values.
>> v3:
>>    mei comp is matched for global i915 comp master. [Daniel]
>>    In hdcp_shim hdcp_protocol() is replaced with const variable. [Daniel]
>>    mei wrappers are adjusted as per the i/f change [Daniel]
> Yeah looks all good. Spotted some small stuff below still.
>
>> Signed-off-by: Ramalingam C <ramalingam.c@intel.com>
>> ---
>>   drivers/gpu/drm/i915/intel_drv.h  |   5 +
>>   drivers/gpu/drm/i915/intel_hdcp.c | 248 +++++++++++++++++++++++++++++++++++++-
>>   include/drm/i915_component.h      |   7 ++
>>   3 files changed, 259 insertions(+), 1 deletion(-)
>>
>> diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
>> index dd9371647a8c..191b6e0f086c 100644
>> --- a/drivers/gpu/drm/i915/intel_drv.h
>> +++ b/drivers/gpu/drm/i915/intel_drv.h
>> @@ -39,6 +39,7 @@
>>   #include <drm/drm_dp_mst_helper.h>
>>   #include <drm/drm_rect.h>
>>   #include <drm/drm_atomic.h>
>> +#include <drm/i915_mei_hdcp_interface.h>
>>   #include <media/cec-notifier.h>
>>   
>>   /**
>> @@ -379,6 +380,9 @@ struct intel_hdcp_shim {
>>   	/* Detects panel's hdcp capability. This is optional for HDMI. */
>>   	int (*hdcp_capable)(struct intel_digital_port *intel_dig_port,
>>   			    bool *hdcp_capable);
>> +
>> +	/* HDCP adaptation(DP/HDMI) required on the port */
>> +	enum hdcp_wired_protocol protocol;
>>   };
>>   
>>   struct intel_hdcp {
>> @@ -399,6 +403,7 @@ struct intel_hdcp {
>>   	 * content can flow only through a link protected by HDCP2.2.
>>   	 */
>>   	u8 content_type;
>> +	struct hdcp_port_data port_data;
>>   };
>>   
>>   struct intel_connector {
>> diff --git a/drivers/gpu/drm/i915/intel_hdcp.c b/drivers/gpu/drm/i915/intel_hdcp.c
>> index 584d27f3c699..9405fce07b93 100644
>> --- a/drivers/gpu/drm/i915/intel_hdcp.c
>> +++ b/drivers/gpu/drm/i915/intel_hdcp.c
>> @@ -8,8 +8,10 @@
>>   
>>   #include <drm/drmP.h>
>>   #include <drm/drm_hdcp.h>
>> +#include <drm/i915_component.h>
>>   #include <linux/i2c.h>
>>   #include <linux/random.h>
>> +#include <linux/component.h>
>>   
>>   #include "intel_drv.h"
>>   #include "i915_reg.h"
>> @@ -833,6 +835,232 @@ bool is_hdcp_supported(struct drm_i915_private *dev_priv, enum port port)
>>   	return INTEL_GEN(dev_priv) >= 9 && port < PORT_E;
>>   }
>>   
>> +static __attribute__((unused)) int
>> +hdcp2_prepare_ake_init(struct intel_connector *connector,
>> +		       struct hdcp2_ake_init *ake_data)
>> +{
>> +	struct hdcp_port_data *data = &connector->hdcp.port_data;
>> +	struct drm_i915_private *dev_priv = to_i915(connector->base.dev);
>> +	struct i915_component_master *comp = dev_priv->comp_master;
>> +	int ret;
>> +
>> +	/* During the connector init encoder might not be initialized */
>> +	if (data->port == PORT_NONE)
>> +		data->port = connector->encoder->port;
>> +
>> +	ret = comp->hdcp_ops->initiate_hdcp2_session(comp->mei_dev,
>> +						     data, ake_data);
>> +	if (ret)
>> +		DRM_DEBUG_KMS("Prepare_ake_init failed. %d\n", ret);
>> +
>> +	return ret;
>> +}
>> +
>> +static __attribute__((unused)) int
>> +hdcp2_verify_rx_cert_prepare_km(struct intel_connector *connector,
>> +				struct hdcp2_ake_send_cert *rx_cert,
>> +				bool *paired,
>> +				struct hdcp2_ake_no_stored_km *ek_pub_km,
>> +				size_t *msg_sz)
>> +{
>> +	struct hdcp_port_data *data = &connector->hdcp.port_data;
>> +	struct drm_i915_private *dev_priv = to_i915(connector->base.dev);
>> +	struct i915_component_master *comp = dev_priv->comp_master;
>> +	int ret;
>> +
>> +	ret = comp->hdcp_ops->verify_receiver_cert_prepare_km(comp->mei_dev,
>> +							      data, rx_cert,
>> +							      paired, ek_pub_km,
>> +							      msg_sz);
>> +	if (ret < 0)
>> +		DRM_DEBUG_KMS("Verify rx_cert failed. %d\n", ret);
>> +
>> +	return ret;
>> +}
>> +
>> +static __attribute__((unused)) int
>> +hdcp2_verify_hprime(struct intel_connector *connector,
>> +		    struct hdcp2_ake_send_hprime *rx_hprime)
>> +{
>> +	struct hdcp_port_data *data = &connector->hdcp.port_data;
>> +	struct drm_i915_private *dev_priv = to_i915(connector->base.dev);
>> +	struct i915_component_master *comp = dev_priv->comp_master;
>> +	int ret;
>> +
>> +	ret = comp->hdcp_ops->verify_hprime(comp->mei_dev, data, rx_hprime);
>> +	if (ret < 0)
>> +		DRM_DEBUG_KMS("Verify hprime failed. %d\n", ret);
>> +
>> +	return ret;
>> +}
>> +
>> +static __attribute__((unused)) int
>> +hdcp2_store_pairing_info(struct intel_connector *connector,
>> +			 struct hdcp2_ake_send_pairing_info *pairing_info)
>> +{
>> +	struct hdcp_port_data *data = &connector->hdcp.port_data;
>> +	struct drm_i915_private *dev_priv = to_i915(connector->base.dev);
>> +	struct i915_component_master *comp = dev_priv->comp_master;
>> +	int ret;
>> +
>> +	ret = comp->hdcp_ops->store_pairing_info(comp->mei_dev, data,
>> +						 pairing_info);
>> +	if (ret < 0)
>> +		DRM_DEBUG_KMS("Store pairing info failed. %d\n", ret);
>> +
>> +	return ret;
>> +}
>> +
>> +static __attribute__((unused)) int
>> +hdcp2_prepare_lc_init(struct intel_connector *connector,
>> +		      struct hdcp2_lc_init *lc_init)
>> +{
>> +	struct hdcp_port_data *data = &connector->hdcp.port_data;
>> +	struct drm_i915_private *dev_priv = to_i915(connector->base.dev);
>> +	struct i915_component_master *comp = dev_priv->comp_master;
>> +	int ret;
>> +
>> +	ret = comp->hdcp_ops->initiate_locality_check(comp->mei_dev, data,
>> +						      lc_init);
>> +	if (ret < 0)
>> +		DRM_DEBUG_KMS("Prepare lc_init failed. %d\n", ret);
>> +
>> +	return ret;
>> +}
>> +
>> +static __attribute__((unused)) int
>> +hdcp2_verify_lprime(struct intel_connector *connector,
>> +		    struct hdcp2_lc_send_lprime *rx_lprime)
>> +{
>> +	struct hdcp_port_data *data = &connector->hdcp.port_data;
>> +	struct drm_i915_private *dev_priv = to_i915(connector->base.dev);
>> +	struct i915_component_master *comp = dev_priv->comp_master;
>> +	int ret;
>> +
>> +	ret = comp->hdcp_ops->verify_lprime(comp->mei_dev, data, rx_lprime);
>> +	if (ret < 0)
>> +		DRM_DEBUG_KMS("Verify L_Prime failed. %d\n", ret);
>> +
>> +	return ret;
>> +}
>> +
>> +static __attribute__((unused))
>> +int hdcp2_prepare_skey(struct intel_connector *connector,
>> +		       struct hdcp2_ske_send_eks *ske_data)
>> +{
>> +	struct hdcp_port_data *data = &connector->hdcp.port_data;
>> +	struct drm_i915_private *dev_priv = to_i915(connector->base.dev);
>> +	struct i915_component_master *comp = dev_priv->comp_master;
>> +	int ret;
>> +
>> +	ret = comp->hdcp_ops->get_session_key(comp->mei_dev, data, ske_data);
>> +	if (ret < 0)
>> +		DRM_DEBUG_KMS("Get session key failed. %d\n", ret);
>> +
>> +	return ret;
>> +}
>> +
>> +static __attribute__((unused)) int
>> +hdcp2_verify_rep_topology_prepare_ack(struct intel_connector *connector,
>> +				      struct hdcp2_rep_send_receiverid_list
>> +								*rep_topology,
>> +				      struct hdcp2_rep_send_ack *rep_send_ack)
>> +{
>> +	struct hdcp_port_data *data = &connector->hdcp.port_data;
>> +	struct drm_i915_private *dev_priv = to_i915(connector->base.dev);
>> +	struct i915_component_master *comp = dev_priv->comp_master;
>> +	int ret;
>> +
>> +	ret = comp->hdcp_ops->repeater_check_flow_prepare_ack(comp->mei_dev,
>> +							      data,
>> +							      rep_topology,
>> +							      rep_send_ack);
>> +	if (ret < 0)
>> +		DRM_DEBUG_KMS("Verify rep topology failed. %d\n", ret);
>> +
>> +	return ret;
>> +}
>> +
>> +static __attribute__((unused)) int
>> +hdcp2_verify_mprime(struct intel_connector *connector,
>> +		    struct hdcp2_rep_stream_ready *stream_ready)
>> +{
>> +	struct hdcp_port_data *data = &connector->hdcp.port_data;
>> +	struct drm_i915_private *dev_priv = to_i915(connector->base.dev);
>> +	struct i915_component_master *comp = dev_priv->comp_master;
>> +	int ret;
>> +
>> +	ret = comp->hdcp_ops->verify_mprime(comp->mei_dev, data, stream_ready);
>> +	if (ret < 0)
>> +		DRM_DEBUG_KMS("Verify mprime failed. %d\n", ret);
>> +
>> +	return ret;
>> +}
>> +
>> +static __attribute__((unused))
>> +int hdcp2_authenticate_port(struct intel_connector *connector)
>> +{
>> +	struct hdcp_port_data *data = &connector->hdcp.port_data;
>> +	struct drm_i915_private *dev_priv = to_i915(connector->base.dev);
>> +	struct i915_component_master *comp = dev_priv->comp_master;
>> +	int ret;
>> +
>> +	ret = comp->hdcp_ops->enable_hdcp_authentication(comp->mei_dev, data);
>> +	if (ret < 0)
>> +		DRM_DEBUG_KMS("Enable hdcp auth failed. %d\n", ret);
>> +
>> +	return ret;
>> +}
>> +
>> +static __attribute__((unused))
>> +int hdcp2_close_mei_session(struct intel_connector *connector)
>> +{
>> +	struct drm_i915_private *dev_priv = to_i915(connector->base.dev);
>> +	struct i915_component_master *comp = dev_priv->comp_master;
>> +
>> +	return comp->hdcp_ops->close_hdcp_session(comp->mei_dev,
>> +						  &connector->hdcp.port_data);
>> +}
>> +
>> +static __attribute__((unused))
>> +int hdcp2_deauthenticate_port(struct intel_connector *connector)
>> +{
>> +	return hdcp2_close_mei_session(connector);
>> +}
>> +
>> +static int i915_hdcp_component_match(struct device *dev, void *data)
>> +{
>> +	return !strcmp(dev->driver->name, "mei_hdcp");
>> +}
>> +
>> +static int initialize_hdcp_port_data(struct intel_connector *connector)
>> +{
>> +	struct intel_hdcp *hdcp = &connector->hdcp;
>> +	struct hdcp_port_data *data = &hdcp->port_data;
>> +
>> +	data->port = PORT_NONE;
>> +	if (connector->encoder)
>> +		data->port = connector->encoder->port;
> This and the code above in ake_init still look strange. I'm not really
> following how we can end up with an intialization sequence where we do not
> yet know the encoder and hence can't assign the port?
>
> That still smells like a bug. I think we should be able to set this
> uncondtionally (if not, I need to understand why).

Oops. this is caused by me by calling the hdcp_init even before intel_connector_attach_encoder.

Will fix it.

>
>> +
>> +	data->port_type = (u8)HDCP_PORT_TYPE_INTEGRATED;
>> +	data->protocol = (u8)hdcp->shim->protocol;
>> +
>> +	data->k = 1;
>> +	if (!data->streams)
>> +		data->streams = kcalloc(data->k,
>> +					sizeof(struct hdcp2_streamid_type),
>> +					GFP_KERNEL);
>> +	if (!data->streams) {
>> +		DRM_ERROR("Out of Memory\n");
>> +		return -ENOMEM;
>> +	}
>> +
>> +	data->streams[0].stream_id = 0;
>> +	data->streams[0].stream_type = hdcp->content_type;
>> +
>> +	return 0;
>> +}
>> +
>>   bool is_hdcp2_supported(struct drm_i915_private *dev_priv)
>>   {
>>   	return ((INTEL_GEN(dev_priv) >= 10 || IS_GEMINILAKE(dev_priv) ||
>> @@ -843,10 +1071,28 @@ static void intel_hdcp2_init(struct intel_connector *connector)
>>   {
>>   	struct drm_i915_private *dev_priv = to_i915(connector->base.dev);
>>   	struct intel_hdcp *hdcp = &connector->hdcp;
>> +	static bool comp_match_added;
>> +	int ret;
>>   
>>   	WARN_ON(!is_hdcp2_supported(dev_priv));
>>   
>> -	/* TODO: MEI interface needs to be initialized here */
>> +	ret = initialize_hdcp_port_data(connector);
>> +	if (ret) {
>> +		DRM_DEBUG_KMS("Mei hdcp data init failed\n");
>> +		return;
>> +	}
>> +
>> +	/*
>> +	 * Component for mei is common across the connector.
>> +	 * Adding the match once is sufficient.
>> +	 * TODO: Instead of static bool, do we need flag in dev_priv?.
>> +	 */
>> +	if (!comp_match_added) {
>> +		component_match_add(dev_priv->drm.dev, &dev_priv->master_match,
>> +				    i915_hdcp_component_match, dev_priv);
> Patch series needs to be reordered: We can only do the component_match_add
> once the mei component is merged. Maybe just split out this hunk into a
> final patch?
This function wont be called till Kconfig is defined in the mei_hdcp 
changes. But yes this chunk should be last patch of these series.
>
>> +		comp_match_added = true;
> This static here kinda works because there's only 1 gpu, but it's a bad
> hack. Please move to drm_i915_private (next to the other component stuff).
Ok
>
> Also, we need to only do this when CONFIG_MEI_HDCP is enabled, otherwise
> hdcp2 init must fail. Maybe best to put that into the is_hdcp2_supported
> helper for now. Once we get non-MEI hdcp2 (definitely needed for discrete
> gpu) we can split that up into is_mei_hdcp2_support and
> is_other_hdcp2_supported.

the check for CONFIG_INTEL_MEI_HDCP is already added into 
is_hdcp2_supported()

-Ram

>
> Otherwise lgtm I think.
> -Daniel
>
>> +	}
>> +
>>   	hdcp->hdcp2_supported = 1;
>>   }
>>   
>> diff --git a/include/drm/i915_component.h b/include/drm/i915_component.h
>> index 6f94ddd3f2c2..7a7201374cfe 100644
>> --- a/include/drm/i915_component.h
>> +++ b/include/drm/i915_component.h
>> @@ -24,6 +24,8 @@
>>   #ifndef _I915_COMPONENT_H_
>>   #define _I915_COMPONENT_H_
>>   
>> +#include <drm/i915_mei_hdcp_interface.h>
>> +
>>   #include "drm_audio_component.h"
>>   
>>   /* MAX_PORT is the number of port
>> @@ -50,8 +52,13 @@ struct i915_audio_component {
>>    * struct i915_component_master - Used for communication between i915
>>    *				  and any other drivers for the services
>>    *				  of different feature.
>> + * @mei_dev: device that provide the HDCP2.2 service from MEI Bus.
>> + * @hdcp_ops: Ops implemented by mei_hdcp driver, used by i915 driver.
>>    */
>>   struct i915_component_master {
>> +	struct device *mei_dev;
>> +	const struct i915_hdcp_component_ops *hdcp_ops;
>> +
>>   	/*
>>   	 * Add here the interface details between I915 and interested modules.
>>   	 */
>> -- 
>> 2.7.4
>>

[-- Attachment #1.2: Type: text/html, Size: 14874 bytes --]

[-- Attachment #2: Type: text/plain, Size: 160 bytes --]

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 103+ messages in thread

* Re: [PATCH v9 13/39] drm: HDCP2.2 link check related constants
  2018-12-13  4:01 ` [PATCH v9 13/39] drm: HDCP2.2 link check related constants Ramalingam C
@ 2018-12-19 15:16   ` Daniel Vetter
  2018-12-19 15:39     ` C, Ramalingam
  0 siblings, 1 reply; 103+ messages in thread
From: Daniel Vetter @ 2018-12-19 15:16 UTC (permalink / raw)
  To: Ramalingam C; +Cc: daniel.vetter, intel-gfx, dri-devel, seanpaul, tomas.winkler

On Thu, Dec 13, 2018 at 09:31:15AM +0530, Ramalingam C wrote:
> Enums and macros are defined for HDCP2.2 link check.
> 
> Signed-off-by: Ramalingam C <ramalingam.c@intel.com>
> ---
>  include/drm/drm_hdcp.h | 8 ++++++++
>  1 file changed, 8 insertions(+)
> 
> diff --git a/include/drm/drm_hdcp.h b/include/drm/drm_hdcp.h
> index d8093ecf3ddc..21a128e7020a 100644
> --- a/include/drm/drm_hdcp.h
> +++ b/include/drm/drm_hdcp.h
> @@ -11,6 +11,14 @@
>  
>  /* Period of hdcp checks (to ensure we're still authenticated) */
>  #define DRM_HDCP_CHECK_PERIOD_MS		(128 * 16)
> +#define DRM_HDCP2_CHECK_PERIOD_MS		500

This one here is good imo, and has my Reviewed-by: Daniel Vetter <daniel.vetter@ffwll.ch>

> +
> +enum check_link_response {
> +	DRM_HDCP_LINK_PROTECTED	= 0,
> +	DRM_HDCP_TOPOLOGY_CHANGE,
> +	DRM_HDCP_LINK_INTEGRITY_FAILURE,
> +	DRM_HDCP_REAUTH_REQUEST
> +};

But this one here is just a part of the intel_hdcp_shim interface. I think
we should put into the intel_drv.h header, and change the return value of
the check_2_2_link hook to this enum. I think that would clarify the code
a lot. Plus then ofc merge this part into the first patch that uses it.

With that remaining patches have my ack, too.

Cheers, Daniel

>  
>  /* Shared lengths/masks between HDMI/DVI/DisplayPort */
>  #define DRM_HDCP_AN_LEN				8
> -- 
> 2.7.4
> 

-- 
Daniel Vetter
Software Engineer, Intel Corporation
http://blog.ffwll.ch
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 103+ messages in thread

* Re: [PATCH v9 07/39] drm/i915: MEI interface definition
  2018-12-19 15:15     ` C, Ramalingam
@ 2018-12-19 15:21       ` Daniel Vetter
  2018-12-20 13:18         ` C, Ramalingam
  0 siblings, 1 reply; 103+ messages in thread
From: Daniel Vetter @ 2018-12-19 15:21 UTC (permalink / raw)
  To: C, Ramalingam
  Cc: daniel.vetter, intel-gfx, dri-devel, seanpaul, tomas.winkler

On Wed, Dec 19, 2018 at 08:45:41PM +0530, C, Ramalingam wrote:
> 
> On 12/19/2018 7:30 PM, Daniel Vetter wrote:
> > On Thu, Dec 13, 2018 at 09:31:09AM +0530, Ramalingam C wrote:
> > > Defining the mei-i915 interface functions and initialization of
> > > the interface.
> > > 
> > > v2:
> > >    Adjust to the new interface changes. [Tomas]
> > >    Added further debug logs for the failures at MEI i/f.
> > >    port in hdcp_port data is equipped to handle -ve values.
> > > v3:
> > >    mei comp is matched for global i915 comp master. [Daniel]
> > >    In hdcp_shim hdcp_protocol() is replaced with const variable. [Daniel]
> > >    mei wrappers are adjusted as per the i/f change [Daniel]
> > Yeah looks all good. Spotted some small stuff below still.
> > 
> > > Signed-off-by: Ramalingam C <ramalingam.c@intel.com>
> > > ---
> > >   drivers/gpu/drm/i915/intel_drv.h  |   5 +
> > >   drivers/gpu/drm/i915/intel_hdcp.c | 248 +++++++++++++++++++++++++++++++++++++-
> > >   include/drm/i915_component.h      |   7 ++
> > >   3 files changed, 259 insertions(+), 1 deletion(-)
> > > 
> > > diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
> > > index dd9371647a8c..191b6e0f086c 100644
> > > --- a/drivers/gpu/drm/i915/intel_drv.h
> > > +++ b/drivers/gpu/drm/i915/intel_drv.h
> > > @@ -39,6 +39,7 @@
> > >   #include <drm/drm_dp_mst_helper.h>
> > >   #include <drm/drm_rect.h>
> > >   #include <drm/drm_atomic.h>
> > > +#include <drm/i915_mei_hdcp_interface.h>
> > >   #include <media/cec-notifier.h>
> > >   /**
> > > @@ -379,6 +380,9 @@ struct intel_hdcp_shim {
> > >   	/* Detects panel's hdcp capability. This is optional for HDMI. */
> > >   	int (*hdcp_capable)(struct intel_digital_port *intel_dig_port,
> > >   			    bool *hdcp_capable);
> > > +
> > > +	/* HDCP adaptation(DP/HDMI) required on the port */
> > > +	enum hdcp_wired_protocol protocol;
> > >   };
> > >   struct intel_hdcp {
> > > @@ -399,6 +403,7 @@ struct intel_hdcp {
> > >   	 * content can flow only through a link protected by HDCP2.2.
> > >   	 */
> > >   	u8 content_type;
> > > +	struct hdcp_port_data port_data;
> > >   };
> > >   struct intel_connector {
> > > diff --git a/drivers/gpu/drm/i915/intel_hdcp.c b/drivers/gpu/drm/i915/intel_hdcp.c
> > > index 584d27f3c699..9405fce07b93 100644
> > > --- a/drivers/gpu/drm/i915/intel_hdcp.c
> > > +++ b/drivers/gpu/drm/i915/intel_hdcp.c
> > > @@ -8,8 +8,10 @@
> > >   #include <drm/drmP.h>
> > >   #include <drm/drm_hdcp.h>
> > > +#include <drm/i915_component.h>
> > >   #include <linux/i2c.h>
> > >   #include <linux/random.h>
> > > +#include <linux/component.h>
> > >   #include "intel_drv.h"
> > >   #include "i915_reg.h"
> > > @@ -833,6 +835,232 @@ bool is_hdcp_supported(struct drm_i915_private *dev_priv, enum port port)
> > >   	return INTEL_GEN(dev_priv) >= 9 && port < PORT_E;
> > >   }
> > > +static __attribute__((unused)) int
> > > +hdcp2_prepare_ake_init(struct intel_connector *connector,
> > > +		       struct hdcp2_ake_init *ake_data)
> > > +{
> > > +	struct hdcp_port_data *data = &connector->hdcp.port_data;
> > > +	struct drm_i915_private *dev_priv = to_i915(connector->base.dev);
> > > +	struct i915_component_master *comp = dev_priv->comp_master;
> > > +	int ret;
> > > +
> > > +	/* During the connector init encoder might not be initialized */
> > > +	if (data->port == PORT_NONE)
> > > +		data->port = connector->encoder->port;
> > > +
> > > +	ret = comp->hdcp_ops->initiate_hdcp2_session(comp->mei_dev,
> > > +						     data, ake_data);
> > > +	if (ret)
> > > +		DRM_DEBUG_KMS("Prepare_ake_init failed. %d\n", ret);
> > > +
> > > +	return ret;
> > > +}
> > > +
> > > +static __attribute__((unused)) int
> > > +hdcp2_verify_rx_cert_prepare_km(struct intel_connector *connector,
> > > +				struct hdcp2_ake_send_cert *rx_cert,
> > > +				bool *paired,
> > > +				struct hdcp2_ake_no_stored_km *ek_pub_km,
> > > +				size_t *msg_sz)
> > > +{
> > > +	struct hdcp_port_data *data = &connector->hdcp.port_data;
> > > +	struct drm_i915_private *dev_priv = to_i915(connector->base.dev);
> > > +	struct i915_component_master *comp = dev_priv->comp_master;
> > > +	int ret;
> > > +
> > > +	ret = comp->hdcp_ops->verify_receiver_cert_prepare_km(comp->mei_dev,
> > > +							      data, rx_cert,
> > > +							      paired, ek_pub_km,
> > > +							      msg_sz);
> > > +	if (ret < 0)
> > > +		DRM_DEBUG_KMS("Verify rx_cert failed. %d\n", ret);
> > > +
> > > +	return ret;
> > > +}
> > > +
> > > +static __attribute__((unused)) int
> > > +hdcp2_verify_hprime(struct intel_connector *connector,
> > > +		    struct hdcp2_ake_send_hprime *rx_hprime)
> > > +{
> > > +	struct hdcp_port_data *data = &connector->hdcp.port_data;
> > > +	struct drm_i915_private *dev_priv = to_i915(connector->base.dev);
> > > +	struct i915_component_master *comp = dev_priv->comp_master;
> > > +	int ret;
> > > +
> > > +	ret = comp->hdcp_ops->verify_hprime(comp->mei_dev, data, rx_hprime);
> > > +	if (ret < 0)
> > > +		DRM_DEBUG_KMS("Verify hprime failed. %d\n", ret);
> > > +
> > > +	return ret;
> > > +}
> > > +
> > > +static __attribute__((unused)) int
> > > +hdcp2_store_pairing_info(struct intel_connector *connector,
> > > +			 struct hdcp2_ake_send_pairing_info *pairing_info)
> > > +{
> > > +	struct hdcp_port_data *data = &connector->hdcp.port_data;
> > > +	struct drm_i915_private *dev_priv = to_i915(connector->base.dev);
> > > +	struct i915_component_master *comp = dev_priv->comp_master;
> > > +	int ret;
> > > +
> > > +	ret = comp->hdcp_ops->store_pairing_info(comp->mei_dev, data,
> > > +						 pairing_info);
> > > +	if (ret < 0)
> > > +		DRM_DEBUG_KMS("Store pairing info failed. %d\n", ret);
> > > +
> > > +	return ret;
> > > +}
> > > +
> > > +static __attribute__((unused)) int
> > > +hdcp2_prepare_lc_init(struct intel_connector *connector,
> > > +		      struct hdcp2_lc_init *lc_init)
> > > +{
> > > +	struct hdcp_port_data *data = &connector->hdcp.port_data;
> > > +	struct drm_i915_private *dev_priv = to_i915(connector->base.dev);
> > > +	struct i915_component_master *comp = dev_priv->comp_master;
> > > +	int ret;
> > > +
> > > +	ret = comp->hdcp_ops->initiate_locality_check(comp->mei_dev, data,
> > > +						      lc_init);
> > > +	if (ret < 0)
> > > +		DRM_DEBUG_KMS("Prepare lc_init failed. %d\n", ret);
> > > +
> > > +	return ret;
> > > +}
> > > +
> > > +static __attribute__((unused)) int
> > > +hdcp2_verify_lprime(struct intel_connector *connector,
> > > +		    struct hdcp2_lc_send_lprime *rx_lprime)
> > > +{
> > > +	struct hdcp_port_data *data = &connector->hdcp.port_data;
> > > +	struct drm_i915_private *dev_priv = to_i915(connector->base.dev);
> > > +	struct i915_component_master *comp = dev_priv->comp_master;
> > > +	int ret;
> > > +
> > > +	ret = comp->hdcp_ops->verify_lprime(comp->mei_dev, data, rx_lprime);
> > > +	if (ret < 0)
> > > +		DRM_DEBUG_KMS("Verify L_Prime failed. %d\n", ret);
> > > +
> > > +	return ret;
> > > +}
> > > +
> > > +static __attribute__((unused))
> > > +int hdcp2_prepare_skey(struct intel_connector *connector,
> > > +		       struct hdcp2_ske_send_eks *ske_data)
> > > +{
> > > +	struct hdcp_port_data *data = &connector->hdcp.port_data;
> > > +	struct drm_i915_private *dev_priv = to_i915(connector->base.dev);
> > > +	struct i915_component_master *comp = dev_priv->comp_master;
> > > +	int ret;
> > > +
> > > +	ret = comp->hdcp_ops->get_session_key(comp->mei_dev, data, ske_data);
> > > +	if (ret < 0)
> > > +		DRM_DEBUG_KMS("Get session key failed. %d\n", ret);
> > > +
> > > +	return ret;
> > > +}
> > > +
> > > +static __attribute__((unused)) int
> > > +hdcp2_verify_rep_topology_prepare_ack(struct intel_connector *connector,
> > > +				      struct hdcp2_rep_send_receiverid_list
> > > +								*rep_topology,
> > > +				      struct hdcp2_rep_send_ack *rep_send_ack)
> > > +{
> > > +	struct hdcp_port_data *data = &connector->hdcp.port_data;
> > > +	struct drm_i915_private *dev_priv = to_i915(connector->base.dev);
> > > +	struct i915_component_master *comp = dev_priv->comp_master;
> > > +	int ret;
> > > +
> > > +	ret = comp->hdcp_ops->repeater_check_flow_prepare_ack(comp->mei_dev,
> > > +							      data,
> > > +							      rep_topology,
> > > +							      rep_send_ack);
> > > +	if (ret < 0)
> > > +		DRM_DEBUG_KMS("Verify rep topology failed. %d\n", ret);
> > > +
> > > +	return ret;
> > > +}
> > > +
> > > +static __attribute__((unused)) int
> > > +hdcp2_verify_mprime(struct intel_connector *connector,
> > > +		    struct hdcp2_rep_stream_ready *stream_ready)
> > > +{
> > > +	struct hdcp_port_data *data = &connector->hdcp.port_data;
> > > +	struct drm_i915_private *dev_priv = to_i915(connector->base.dev);
> > > +	struct i915_component_master *comp = dev_priv->comp_master;
> > > +	int ret;
> > > +
> > > +	ret = comp->hdcp_ops->verify_mprime(comp->mei_dev, data, stream_ready);
> > > +	if (ret < 0)
> > > +		DRM_DEBUG_KMS("Verify mprime failed. %d\n", ret);
> > > +
> > > +	return ret;
> > > +}
> > > +
> > > +static __attribute__((unused))
> > > +int hdcp2_authenticate_port(struct intel_connector *connector)
> > > +{
> > > +	struct hdcp_port_data *data = &connector->hdcp.port_data;
> > > +	struct drm_i915_private *dev_priv = to_i915(connector->base.dev);
> > > +	struct i915_component_master *comp = dev_priv->comp_master;
> > > +	int ret;
> > > +
> > > +	ret = comp->hdcp_ops->enable_hdcp_authentication(comp->mei_dev, data);
> > > +	if (ret < 0)
> > > +		DRM_DEBUG_KMS("Enable hdcp auth failed. %d\n", ret);
> > > +
> > > +	return ret;
> > > +}
> > > +
> > > +static __attribute__((unused))
> > > +int hdcp2_close_mei_session(struct intel_connector *connector)
> > > +{
> > > +	struct drm_i915_private *dev_priv = to_i915(connector->base.dev);
> > > +	struct i915_component_master *comp = dev_priv->comp_master;
> > > +
> > > +	return comp->hdcp_ops->close_hdcp_session(comp->mei_dev,
> > > +						  &connector->hdcp.port_data);
> > > +}
> > > +
> > > +static __attribute__((unused))
> > > +int hdcp2_deauthenticate_port(struct intel_connector *connector)
> > > +{
> > > +	return hdcp2_close_mei_session(connector);
> > > +}
> > > +
> > > +static int i915_hdcp_component_match(struct device *dev, void *data)
> > > +{
> > > +	return !strcmp(dev->driver->name, "mei_hdcp");
> > > +}
> > > +
> > > +static int initialize_hdcp_port_data(struct intel_connector *connector)
> > > +{
> > > +	struct intel_hdcp *hdcp = &connector->hdcp;
> > > +	struct hdcp_port_data *data = &hdcp->port_data;
> > > +
> > > +	data->port = PORT_NONE;
> > > +	if (connector->encoder)
> > > +		data->port = connector->encoder->port;
> > This and the code above in ake_init still look strange. I'm not really
> > following how we can end up with an intialization sequence where we do not
> > yet know the encoder and hence can't assign the port?
> > 
> > That still smells like a bug. I think we should be able to set this
> > uncondtionally (if not, I need to understand why).
> 
> Oops. this is caused by me by calling the hdcp_init even before intel_connector_attach_encoder.
> 
> Will fix it.
> 
> > 
> > > +
> > > +	data->port_type = (u8)HDCP_PORT_TYPE_INTEGRATED;
> > > +	data->protocol = (u8)hdcp->shim->protocol;
> > > +
> > > +	data->k = 1;
> > > +	if (!data->streams)
> > > +		data->streams = kcalloc(data->k,
> > > +					sizeof(struct hdcp2_streamid_type),
> > > +					GFP_KERNEL);
> > > +	if (!data->streams) {
> > > +		DRM_ERROR("Out of Memory\n");
> > > +		return -ENOMEM;
> > > +	}
> > > +
> > > +	data->streams[0].stream_id = 0;
> > > +	data->streams[0].stream_type = hdcp->content_type;
> > > +
> > > +	return 0;
> > > +}
> > > +
> > >   bool is_hdcp2_supported(struct drm_i915_private *dev_priv)
> > >   {
> > >   	return ((INTEL_GEN(dev_priv) >= 10 || IS_GEMINILAKE(dev_priv) ||
> > > @@ -843,10 +1071,28 @@ static void intel_hdcp2_init(struct intel_connector *connector)
> > >   {
> > >   	struct drm_i915_private *dev_priv = to_i915(connector->base.dev);
> > >   	struct intel_hdcp *hdcp = &connector->hdcp;
> > > +	static bool comp_match_added;
> > > +	int ret;
> > >   	WARN_ON(!is_hdcp2_supported(dev_priv));
> > > -	/* TODO: MEI interface needs to be initialized here */
> > > +	ret = initialize_hdcp_port_data(connector);
> > > +	if (ret) {
> > > +		DRM_DEBUG_KMS("Mei hdcp data init failed\n");
> > > +		return;
> > > +	}
> > > +
> > > +	/*
> > > +	 * Component for mei is common across the connector.
> > > +	 * Adding the match once is sufficient.
> > > +	 * TODO: Instead of static bool, do we need flag in dev_priv?.
> > > +	 */
> > > +	if (!comp_match_added) {
> > > +		component_match_add(dev_priv->drm.dev, &dev_priv->master_match,
> > > +				    i915_hdcp_component_match, dev_priv);
> > Patch series needs to be reordered: We can only do the component_match_add
> > once the mei component is merged. Maybe just split out this hunk into a
> > final patch?
> This function wont be called till Kconfig is defined in the mei_hdcp
> changes. But yes this chunk should be last patch of these series.
> > 
> > > +		comp_match_added = true;
> > This static here kinda works because there's only 1 gpu, but it's a bad
> > hack. Please move to drm_i915_private (next to the other component stuff).
> Ok
> > 
> > Also, we need to only do this when CONFIG_MEI_HDCP is enabled, otherwise
> > hdcp2 init must fail. Maybe best to put that into the is_hdcp2_supported
> > helper for now. Once we get non-MEI hdcp2 (definitely needed for discrete
> > gpu) we can split that up into is_mei_hdcp2_support and
> > is_other_hdcp2_supported.
> 
> the check for CONFIG_INTEL_MEI_HDCP is already added into
> is_hdcp2_supported()

Indeed, I overlooked that. Maybe highlight it a bit more with a separate

	if (!CONFIG_ENABLED(MEI_HDCP))
		return false;

so it stick out more in the previous patch. Currently it's a bit burried.

With that + the init ordering fixed:

Reviewed-by: Daniel Vetter <daniel.vetter@ffwll.ch>

There's no need to split the patch out anymore, since without the mei
patches you can't enable that Kconfig option and hence no bisect issues.

Cheers, Daniel


> 
> -Ram
> 
> > 
> > Otherwise lgtm I think.
> > -Daniel
> > 
> > > +	}
> > > +
> > >   	hdcp->hdcp2_supported = 1;
> > >   }
> > > diff --git a/include/drm/i915_component.h b/include/drm/i915_component.h
> > > index 6f94ddd3f2c2..7a7201374cfe 100644
> > > --- a/include/drm/i915_component.h
> > > +++ b/include/drm/i915_component.h
> > > @@ -24,6 +24,8 @@
> > >   #ifndef _I915_COMPONENT_H_
> > >   #define _I915_COMPONENT_H_
> > > +#include <drm/i915_mei_hdcp_interface.h>
> > > +
> > >   #include "drm_audio_component.h"
> > >   /* MAX_PORT is the number of port
> > > @@ -50,8 +52,13 @@ struct i915_audio_component {
> > >    * struct i915_component_master - Used for communication between i915
> > >    *				  and any other drivers for the services
> > >    *				  of different feature.
> > > + * @mei_dev: device that provide the HDCP2.2 service from MEI Bus.
> > > + * @hdcp_ops: Ops implemented by mei_hdcp driver, used by i915 driver.
> > >    */
> > >   struct i915_component_master {
> > > +	struct device *mei_dev;
> > > +	const struct i915_hdcp_component_ops *hdcp_ops;
> > > +
> > >   	/*
> > >   	 * Add here the interface details between I915 and interested modules.
> > >   	 */
> > > -- 
> > > 2.7.4
> > > 

-- 
Daniel Vetter
Software Engineer, Intel Corporation
http://blog.ffwll.ch
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 103+ messages in thread

* Re: [PATCH v9 10/39] drm/i915: Implement HDCP2.2 receiver authentication
  2018-12-19 15:05     ` C, Ramalingam
@ 2018-12-19 15:35       ` Daniel Vetter
  2018-12-19 15:48         ` C, Ramalingam
  2018-12-19 18:40       ` Jani Nikula
  1 sibling, 1 reply; 103+ messages in thread
From: Daniel Vetter @ 2018-12-19 15:35 UTC (permalink / raw)
  To: C, Ramalingam
  Cc: daniel.vetter, intel-gfx, dri-devel, uma.shankar, seanpaul,
	tomas.winkler

On Wed, Dec 19, 2018 at 08:35:48PM +0530, C, Ramalingam wrote:
> On 12/19/2018 8:05 PM, Daniel Vetter wrote:
> > On Thu, Dec 13, 2018 at 09:31:12AM +0530, Ramalingam C wrote:
> > > +	if (!hdcp->is_repeater && shim->config_stream_type) {
> > > +		/*
> > > +		 * Errata for DP: As Stream type is used for encryption,
> > > +		 * Receiver should be communicated with stream type for the
> > > +		 * decryption of the content.
> > > +		 * Repeater will be communicated with stream type as a
> > > +		 * part of it's auth later in time.
> > > +		 */
> > I'm not following what you want to say with this comment, and haven't
> > found anything in the hdcp2 dp spec about this either.
> 
> this is there in the errata of DP HDCP2.2 spec.
> hdcp2.2 encryption algo involves the stream type as a parameter.
> And as part of hdcp auth mentioned in base spec DP repeaters receive that details to decrypt the content.
> But DP receivers dont get it. So errata adds the missing piece for decryption.

Ok I found it, but the fake HDCP_2_2_ERRATA_DP_STREAM_TYPE define is kinda
annoying. It doesn't exist in the spec, but we put it into the drm_hdcp.h
header. Since you have a special ->config_stream_type hook for this
anyway, and it's only needed for DP, please move that into the shim
implementation.

And then a follow-up patch to remove the fake #define from drm_hdcp.h.
-Daniel
-- 
Daniel Vetter
Software Engineer, Intel Corporation
http://blog.ffwll.ch
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 103+ messages in thread

* Re: [PATCH v9 12/39] drm/i915: Implement HDCP2.2 repeater authentication
  2018-12-19 14:48   ` Daniel Vetter
@ 2018-12-19 15:35     ` C, Ramalingam
  0 siblings, 0 replies; 103+ messages in thread
From: C, Ramalingam @ 2018-12-19 15:35 UTC (permalink / raw)
  To: Daniel Vetter
  Cc: daniel.vetter, intel-gfx, dri-devel, uma.shankar, seanpaul,
	tomas.winkler


On 12/19/2018 8:18 PM, Daniel Vetter wrote:
> On Thu, Dec 13, 2018 at 09:31:14AM +0530, Ramalingam C wrote:
>> Implements the HDCP2.2 repeaters authentication steps such as verifying
>> the downstream topology and sending stream management information.
>>
>> v2: Rebased.
>> v3:
>>    -EINVAL is returned for topology error and rollover scenario.
>>    Endianness conversion func from drm_hdcp.h is used [Uma]
>> v4:
>>    Rebased as part of patches reordering.
>>    Defined the mei service functions [Daniel]
>> v5:
>>    Redefined the mei service functions as per comp redesign.
>> v6:
>>    %s/uintxx_t/uxx
>>    Check for comp_master is removed.
>> v7:
>>    Adjust to the new mei interface.
>>    style issue fixed.
>> v8:
>>    drm_hdcp.h change is moved into separate patch [Daniel]
>>
>> Signed-off-by: Ramalingam C <ramalingam.c@intel.com>
>> ---
>>   drivers/gpu/drm/i915/intel_hdcp.c | 123 +++++++++++++++++++++++++++++++++++++-
>>   1 file changed, 121 insertions(+), 2 deletions(-)
>>
>> diff --git a/drivers/gpu/drm/i915/intel_hdcp.c b/drivers/gpu/drm/i915/intel_hdcp.c
>> index f1f0ef294e20..b52da5c3159d 100644
>> --- a/drivers/gpu/drm/i915/intel_hdcp.c
>> +++ b/drivers/gpu/drm/i915/intel_hdcp.c
>> @@ -978,7 +978,7 @@ static int hdcp2_prepare_skey(struct intel_connector *connector,
>>   	return ret;
>>   }
>>   
>> -static __attribute__((unused)) int
>> +static int
>>   hdcp2_verify_rep_topology_prepare_ack(struct intel_connector *connector,
>>   				      struct hdcp2_rep_send_receiverid_list
>>   								*rep_topology,
>> @@ -999,7 +999,7 @@ hdcp2_verify_rep_topology_prepare_ack(struct intel_connector *connector,
>>   	return ret;
>>   }
>>   
>> -static __attribute__((unused)) int
>> +static int
>>   hdcp2_verify_mprime(struct intel_connector *connector,
>>   		    struct hdcp2_rep_stream_ready *stream_ready)
>>   {
>> @@ -1182,6 +1182,119 @@ static int hdcp2_session_key_exchange(struct intel_connector *connector)
>>   	return 0;
>>   }
>>   
>> +static
>> +int hdcp2_propagate_stream_management_info(struct intel_connector *connector)
>> +{
>> +	struct intel_digital_port *intel_dig_port = conn_to_dig_port(connector);
>> +	struct intel_hdcp *hdcp = &connector->hdcp;
>> +	union {
>> +		struct hdcp2_rep_stream_manage stream_manage;
>> +		struct hdcp2_rep_stream_ready stream_ready;
>> +	} msgs;
>> +	const struct intel_hdcp_shim *shim = hdcp->shim;
>> +	int ret;
>> +
>> +	/* Prepare RepeaterAuth_Stream_Manage msg */
>> +	msgs.stream_manage.msg_id = HDCP_2_2_REP_STREAM_MANAGE;
>> +	drm_hdcp2_u32_to_seq_num(msgs.stream_manage.seq_num_m, hdcp->seq_num_m);
>> +
>> +	/* K no of streams is fixed as 1. Stored as big-endian. */
>> +	msgs.stream_manage.k = __swab16(1);
>> +
>> +	/* For HDMI this is forced to be 0x0. For DP SST also this is 0x0. */
>> +	msgs.stream_manage.streams[0].stream_id = 0;
>> +	msgs.stream_manage.streams[0].stream_type = hdcp->content_type;
>> +
>> +	/* Send it to Repeater */
>> +	ret = shim->write_2_2_msg(intel_dig_port, &msgs.stream_manage,
>> +				  sizeof(msgs.stream_manage));
>> +	if (ret < 0)
>> +		return ret;
>> +
>> +	ret = shim->read_2_2_msg(intel_dig_port, HDCP_2_2_REP_STREAM_READY,
>> +				 &msgs.stream_ready, sizeof(msgs.stream_ready));
>> +	if (ret < 0)
>> +		return ret;
>> +
>> +	hdcp->port_data.seq_num_m = hdcp->seq_num_m;
>> +	hdcp->port_data.streams[0].stream_type = hdcp->content_type;
>> +
>> +	ret = hdcp2_verify_mprime(connector, &msgs.stream_ready);
>> +	if (ret < 0)
>> +		return ret;
>> +
>> +	hdcp->seq_num_m++;
>> +
>> +	if (hdcp->seq_num_m > HDCP_2_2_SEQ_NUM_MAX) {
>> +		DRM_DEBUG_KMS("seq_num_m roll over.\n");
>> +		return -1;
>> +	}
>> +
>> +	return 0;
>> +}
>> +
>> +static
>> +int hdcp2_authenticate_repeater_topology(struct intel_connector *connector)
>> +{
>> +	struct intel_digital_port *intel_dig_port = conn_to_dig_port(connector);
>> +	struct intel_hdcp *hdcp = &connector->hdcp;
>> +	union {
>> +		struct hdcp2_rep_send_receiverid_list recvid_list;
>> +		struct hdcp2_rep_send_ack rep_ack;
>> +	} msgs;
>> +	const struct intel_hdcp_shim *shim = hdcp->shim;
>> +	u8 *rx_info;
>> +	u32 seq_num_v;
>> +	int ret;
>> +
>> +	ret = shim->read_2_2_msg(intel_dig_port, HDCP_2_2_REP_SEND_RECVID_LIST,
>> +				 &msgs.recvid_list, sizeof(msgs.recvid_list));
>> +	if (ret < 0)
>> +		return ret;
>> +
>> +	rx_info = msgs.recvid_list.rx_info;
> There's a 2s timeout here that we're not checking, but again probably
> follow-up patch.
Timeout is taken care at shim.
>
>> +
>> +	if (HDCP_2_2_MAX_CASCADE_EXCEEDED(rx_info[1]) ||
>> +	    HDCP_2_2_MAX_DEVS_EXCEEDED(rx_info[1])) {
>> +		DRM_DEBUG_KMS("Topology Max Size Exceeded\n");
>> +		return -EINVAL;
>> +	}
>> +
>> +	/* Converting and Storing the seq_num_v to local variable as DWORD */
>> +	drm_hdcp2_seq_num_to_u32(&seq_num_v, msgs.recvid_list.seq_num_v);
>> +
>> +	if (seq_num_v < hdcp->seq_num_v) {
>> +		/* Roll over of the seq_num_v from repeater. Reauthenticate. */
>> +		DRM_DEBUG_KMS("Seq_num_v roll over.\n");
>> +		return -EINVAL;
>> +	}
>> +
>> +	ret = hdcp2_verify_rep_topology_prepare_ack(connector,
>> +						    &msgs.recvid_list,
>> +						    &msgs.rep_ack);
>> +	if (ret < 0)
>> +		return ret;
> Spec talks about type0 vs type1 here, but for now we can ignore that.

Its already taken care at hdcp2_propagate_stream_management_info()

msgs.stream_manage.streams[0].stream_type = hdcp->content_type;
And mei also informed about the content_type through hdcp_port_data

>
>> +
>> +	hdcp->seq_num_v = seq_num_v;
>> +	ret = shim->write_2_2_msg(intel_dig_port, &msgs.rep_ack,
>> +				  sizeof(msgs.rep_ack));
>> +	if (ret < 0)
>> +		return ret;
>> +
>> +	return 0;
>> +}
>> +
>> +static int hdcp2_authenticate_repeater(struct intel_connector *connector)
>> +{
>> +	int ret;
>> +
>> +	ret = hdcp2_authenticate_repeater_topology(connector);
>> +	if (ret < 0)
>> +		return ret;
>> +
>> +	return hdcp2_propagate_stream_management_info(connector);
>> +}
>> +
>>   static int hdcp2_authenticate_sink(struct intel_connector *connector)
>>   {
>>   	struct intel_digital_port *intel_dig_port = conn_to_dig_port(connector);
>> @@ -1223,6 +1336,12 @@ static int hdcp2_authenticate_sink(struct intel_connector *connector)
>>   					       sizeof(stream_type_msg));
>>   		if (ret < 0)
>>   			return ret;
>> +	} else if (hdcp->is_repeater) {
>> +		ret = hdcp2_authenticate_repeater(connector);
>> +		if (ret < 0) {
>> +			DRM_DEBUG_KMS("Repeater Auth Failed. Err: %d\n", ret);
>> +			return ret;
>> +		}
>>   	}
> Spec for receiver auth is a bit more confusing than usual, but I think
> this matches.
>
> Reviewed-by: Daniel Vetter <daniel.vetter@ffwll.ch>

Thank you

-Ram

>>   
>>   	hdcp->port_data.streams[0].stream_type = hdcp->content_type;
>> -- 
>> 2.7.4
>>
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 103+ messages in thread

* Re: [PATCH v9 13/39] drm: HDCP2.2 link check related constants
  2018-12-19 15:16   ` Daniel Vetter
@ 2018-12-19 15:39     ` C, Ramalingam
  2018-12-19 15:58       ` Daniel Vetter
  0 siblings, 1 reply; 103+ messages in thread
From: C, Ramalingam @ 2018-12-19 15:39 UTC (permalink / raw)
  To: Daniel Vetter
  Cc: daniel.vetter, intel-gfx, dri-devel, seanpaul, tomas.winkler


On 12/19/2018 8:46 PM, Daniel Vetter wrote:
> On Thu, Dec 13, 2018 at 09:31:15AM +0530, Ramalingam C wrote:
>> Enums and macros are defined for HDCP2.2 link check.
>>
>> Signed-off-by: Ramalingam C <ramalingam.c@intel.com>
>> ---
>>   include/drm/drm_hdcp.h | 8 ++++++++
>>   1 file changed, 8 insertions(+)
>>
>> diff --git a/include/drm/drm_hdcp.h b/include/drm/drm_hdcp.h
>> index d8093ecf3ddc..21a128e7020a 100644
>> --- a/include/drm/drm_hdcp.h
>> +++ b/include/drm/drm_hdcp.h
>> @@ -11,6 +11,14 @@
>>   
>>   /* Period of hdcp checks (to ensure we're still authenticated) */
>>   #define DRM_HDCP_CHECK_PERIOD_MS		(128 * 16)
>> +#define DRM_HDCP2_CHECK_PERIOD_MS		500
> This one here is good imo, and has my Reviewed-by: Daniel Vetter <daniel.vetter@ffwll.ch>
>
>> +
>> +enum check_link_response {
>> +	DRM_HDCP_LINK_PROTECTED	= 0,
>> +	DRM_HDCP_TOPOLOGY_CHANGE,
>> +	DRM_HDCP_LINK_INTEGRITY_FAILURE,
>> +	DRM_HDCP_REAUTH_REQUEST
>> +};
> But this one here is just a part of the intel_hdcp_shim interface. I think
> we should put into the intel_drv.h header, and change the return value of
> the check_2_2_link hook to this enum. I think that would clarify the code
> a lot. Plus then ofc merge this part into the first patch that uses it.

daniel,

this is generic link check results as per the HDCP spec. This could be 
used by any other driver in DRM. Still should i move as local to intel?

-Ram

>
> With that remaining patches have my ack, too.
>
> Cheers, Daniel
>
>>   
>>   /* Shared lengths/masks between HDMI/DVI/DisplayPort */
>>   #define DRM_HDCP_AN_LEN				8
>> -- 
>> 2.7.4
>>
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 103+ messages in thread

* Re: [PATCH v9 37/39] drm/i915: Fix KBL HDCP2.2 encrypt status signalling
  2018-12-13  4:01 ` [PATCH v9 37/39] drm/i915: Fix KBL HDCP2.2 encrypt status signalling Ramalingam C
@ 2018-12-19 15:40   ` Daniel Vetter
  2018-12-19 16:16     ` C, Ramalingam
  0 siblings, 1 reply; 103+ messages in thread
From: Daniel Vetter @ 2018-12-19 15:40 UTC (permalink / raw)
  To: Ramalingam C; +Cc: daniel.vetter, intel-gfx, dri-devel, seanpaul, tomas.winkler

On Thu, Dec 13, 2018 at 09:31:39AM +0530, Ramalingam C wrote:
> Implement the required WA sequence for KBL to fix the
> incorrect positioning of the window of oppurtunity and enc_en
> signalling.
> 
> Signed-off-by: Ramalingam C <ramalingam.c@intel.com>
> ---
>  drivers/gpu/drm/i915/intel_hdcp.c | 29 +++++++++++++++++++++++++++++
>  1 file changed, 29 insertions(+)
> 
> diff --git a/drivers/gpu/drm/i915/intel_hdcp.c b/drivers/gpu/drm/i915/intel_hdcp.c
> index 42327ed30903..2b9e1b6d0b1e 100644
> --- a/drivers/gpu/drm/i915/intel_hdcp.c
> +++ b/drivers/gpu/drm/i915/intel_hdcp.c
> @@ -12,6 +12,7 @@
>  #include <linux/i2c.h>
>  #include <linux/random.h>
>  #include <linux/component.h>
> +#include <linux/delay.h>
>  
>  #include "intel_drv.h"
>  #include "i915_reg.h"
> @@ -20,6 +21,27 @@
>  #define ENCRYPT_STATUS_CHANGE_TIMEOUT_MS	50
>  #define HDCP2_LC_RETRY_CNT			3
>  
> +static void kbl_repositioning_enc_en_signal(struct intel_connector *connector)
> +{
> +	struct drm_i915_private *dev_priv = to_i915(connector->base.dev);
> +	struct intel_digital_port *intel_dig_port = conn_to_dig_port(connector);
> +	struct intel_hdcp *hdcp = &connector->hdcp;
> +	struct drm_crtc *crtc = connector->base.state->crtc;
> +	struct intel_crtc *intel_crtc = container_of(crtc,
> +						     struct intel_crtc, base);
> +	u32 scanline;
> +
> +	for (;;) {
> +		scanline = I915_READ(PIPEDSL(intel_crtc->pipe));
> +		if (scanline > 100 && scanline < 200)
> +			break;
> +		usleep_range(25, 50);
> +	}
> +
> +	hdcp->shim->toggle_signalling(intel_dig_port, false);
> +	hdcp->shim->toggle_signalling(intel_dig_port, true);
> +}
> +
>  static
>  bool intel_hdcp_is_ksv_valid(u8 *ksv)
>  {
> @@ -1382,6 +1404,13 @@ static int hdcp2_enable_encryption(struct intel_connector *connector)
>  	}
>  
>  	if (I915_READ(HDCP2_STATUS_DDI(port)) & LINK_AUTH_STATUS) {
> +		/*
> +		 * WA: To fix incorrect positioning of the window of
> +		 * opportunity and enc_en signalling in KABYLAKE.
> +		 */
> +		if (IS_KABYLAKE(dev_priv) && hdcp->shim->toggle_signalling)
> +			kbl_repositioning_enc_en_signal(connector);

This is a bit a layering violation of the shim. I think it'd be better to
push this into the toggle_signalling implementation, which you call right
above. That can easily check this register too, and retry. That way the
kbl flow is all in one place.

Bspec is down for me, so can't check the w/a itself :-(
-Daniel

> +
>  		/* Link is Authenticated. Now set for Encryption */
>  		I915_WRITE(HDCP2_CTL_DDI(port),
>  			   I915_READ(HDCP2_CTL_DDI(port)) |
> -- 
> 2.7.4
> 

-- 
Daniel Vetter
Software Engineer, Intel Corporation
http://blog.ffwll.ch
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 103+ messages in thread

* Re: [PATCH v9 08/39] drm/i915: hdcp1.4 CP_IRQ handling and SW encryption tracking
  2018-12-13  4:01 ` [PATCH v9 08/39] drm/i915: hdcp1.4 CP_IRQ handling and SW encryption tracking Ramalingam C
@ 2018-12-19 15:48   ` Daniel Vetter
  2018-12-20 11:29     ` C, Ramalingam
  0 siblings, 1 reply; 103+ messages in thread
From: Daniel Vetter @ 2018-12-19 15:48 UTC (permalink / raw)
  To: Ramalingam C; +Cc: daniel.vetter, intel-gfx, dri-devel, seanpaul, tomas.winkler

On Thu, Dec 13, 2018 at 09:31:10AM +0530, Ramalingam C wrote:
> "hdcp_encrypted" flag is defined to denote the HDCP1.4 encryption status.
> This SW tracking is used to determine the need for real hdcp1.4 disable
> and hdcp_check_link upon CP_IRQ.
> 
> On CP_IRQ we filter the CP_IRQ related to the states like Link failure
> and reauthentication req etc and handle them in hdcp_check_link.
> CP_IRQ corresponding to the authentication msg availability are ignored.
> 
> WARN_ON is added for the abrupt stop of HDCP encryption of a port.
> 
> Signed-off-by: Ramalingam C <ramalingam.c@intel.com>
> ---
>  drivers/gpu/drm/i915/intel_dp.c   |  2 +-
>  drivers/gpu/drm/i915/intel_drv.h  |  5 ++-
>  drivers/gpu/drm/i915/intel_hdcp.c | 89 ++++++++++++++++++++++++++++++---------
>  3 files changed, 74 insertions(+), 22 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
> index aba884c64879..89315e15fb34 100644
> --- a/drivers/gpu/drm/i915/intel_dp.c
> +++ b/drivers/gpu/drm/i915/intel_dp.c
> @@ -4758,7 +4758,7 @@ static void intel_dp_check_service_irq(struct intel_dp *intel_dp)
>  		intel_dp_handle_test_request(intel_dp);
>  
>  	if (val & DP_CP_IRQ)
> -		intel_hdcp_check_link(intel_dp->attached_connector);
> +		intel_hdcp_handle_cp_irq(intel_dp->attached_connector);
>  
>  	if (val & DP_SINK_SPECIFIC_IRQ)
>  		DRM_DEBUG_DRIVER("Sink specific irq unhandled\n");
> diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
> index 191b6e0f086c..decd0346c6a7 100644
> --- a/drivers/gpu/drm/i915/intel_drv.h
> +++ b/drivers/gpu/drm/i915/intel_drv.h
> @@ -393,6 +393,9 @@ struct intel_hdcp {
>  	struct delayed_work check_work;
>  	struct work_struct prop_work;
>  
> +	/* HDCP1.4 Encryption status */
> +	u8 hdcp_encrypted;

Another bool I guess? Or unsigned : 1;

> +
>  	/* HDCP2.2 related definitions */
>  	/* Flag indicates whether this connector supports HDCP2.2 or not. */
>  	u8 hdcp2_supported;
> @@ -2058,10 +2061,10 @@ int intel_hdcp_init(struct intel_connector *connector,
>  		    bool hdcp2_supported);
>  int intel_hdcp_enable(struct intel_connector *connector);
>  int intel_hdcp_disable(struct intel_connector *connector);
> -int intel_hdcp_check_link(struct intel_connector *connector);
>  bool is_hdcp_supported(struct drm_i915_private *dev_priv, enum port port);
>  bool intel_hdcp_capable(struct intel_connector *connector);
>  bool is_hdcp2_supported(struct drm_i915_private *dev_priv);
> +void intel_hdcp_handle_cp_irq(struct intel_connector *connector);
>  
>  /* intel_psr.c */
>  #define CAN_PSR(dev_priv) (HAS_PSR(dev_priv) && dev_priv->psr.sink_support)
> diff --git a/drivers/gpu/drm/i915/intel_hdcp.c b/drivers/gpu/drm/i915/intel_hdcp.c
> index 9405fce07b93..2b7814a6f12b 100644
> --- a/drivers/gpu/drm/i915/intel_hdcp.c
> +++ b/drivers/gpu/drm/i915/intel_hdcp.c
> @@ -75,6 +75,16 @@ bool intel_hdcp_capable(struct intel_connector *connector)
>  	return capable;
>  }
>  
> +static inline bool intel_hdcp_in_use(struct intel_connector *connector)
> +{
> +	struct drm_i915_private *dev_priv = to_i915(connector->base.dev);
> +	enum port port = connector->encoder->port;
> +	u32 reg;
> +
> +	reg = I915_READ(PORT_HDCP_STATUS(port));
> +	return reg & HDCP_STATUS_ENC;
> +}
> +
>  static int intel_hdcp_poll_ksv_fifo(struct intel_digital_port *intel_dig_port,
>  				    const struct intel_hdcp_shim *shim)
>  {
> @@ -669,6 +679,7 @@ static int _intel_hdcp_disable(struct intel_connector *connector)
>  	DRM_DEBUG_KMS("[%s:%d] HDCP is being disabled...\n",
>  		      connector->base.name, connector->base.base.id);
>  
> +	hdcp->hdcp_encrypted = 0;
>  	I915_WRITE(PORT_HDCP_CONF(port), 0);
>  	if (intel_wait_for_register(dev_priv, PORT_HDCP_STATUS(port), ~0, 0,
>  				    ENCRYPT_STATUS_CHANGE_TIMEOUT_MS)) {
> @@ -714,8 +725,10 @@ static int _intel_hdcp_enable(struct intel_connector *connector)
>  	/* Incase of authentication failures, HDCP spec expects reauth. */
>  	for (i = 0; i < tries; i++) {
>  		ret = intel_hdcp_auth(conn_to_dig_port(connector), hdcp->shim);
> -		if (!ret)
> +		if (!ret) {
> +			hdcp->hdcp_encrypted = 1;
>  			return 0;
> +		}
>  
>  		DRM_DEBUG_KMS("HDCP Auth failure (%d)\n", ret);
>  
> @@ -742,16 +755,17 @@ int intel_hdcp_check_link(struct intel_connector *connector)
>  	enum port port = intel_dig_port->base.port;
>  	int ret = 0;
>  
> -	if (!hdcp->shim)
> -		return -ENOENT;
> -
>  	mutex_lock(&hdcp->mutex);
>  
> -	if (hdcp->value == DRM_MODE_CONTENT_PROTECTION_UNDESIRED)
> +	/* Check_link valid only when HDCP1.4 is enabled */
> +	if (hdcp->value != DRM_MODE_CONTENT_PROTECTION_ENABLED ||
> +	    !hdcp->hdcp_encrypted) {
> +		ret = -EINVAL;
>  		goto out;
> +	}
>  
> -	if (!(I915_READ(PORT_HDCP_STATUS(port)) & HDCP_STATUS_ENC)) {
> -		DRM_ERROR("%s:%d HDCP check failed: link is not encrypted,%x\n",
> +	if (WARN_ON(!intel_hdcp_in_use(connector))) {
> +		DRM_ERROR("%s:%d HDCP link stopped encryption,%x\n",
>  			  connector->base.name, connector->base.base.id,
>  			  I915_READ(PORT_HDCP_STATUS(port)));
>  		ret = -ENXIO;
> @@ -792,18 +806,6 @@ int intel_hdcp_check_link(struct intel_connector *connector)
>  	return ret;
>  }
>  
> -static void intel_hdcp_check_work(struct work_struct *work)
> -{
> -	struct intel_hdcp *hdcp = container_of(to_delayed_work(work),
> -					       struct intel_hdcp,
> -					       check_work);
> -	struct intel_connector *connector = intel_hdcp_to_connector(hdcp);
> -
> -	if (!intel_hdcp_check_link(connector))
> -		schedule_delayed_work(&hdcp->check_work,
> -				      DRM_HDCP_CHECK_PERIOD_MS);
> -}

Why move the function?
> -
>  static void intel_hdcp_prop_work(struct work_struct *work)
>  {
>  	struct intel_hdcp *hdcp = container_of(work, struct intel_hdcp,
> @@ -1028,6 +1030,25 @@ int hdcp2_deauthenticate_port(struct intel_connector *connector)
>  	return hdcp2_close_mei_session(connector);
>  }
>  
> +static inline void _intel_hdcp_check_work(struct intel_connector *connector)
> +{
> +	struct intel_hdcp *hdcp = &connector->hdcp;
> +
> +	if (!intel_hdcp_check_link(connector))
> +		schedule_delayed_work(&hdcp->check_work,
> +				      DRM_HDCP_CHECK_PERIOD_MS);
> +}
> +
> +static void intel_hdcp_check_work(struct work_struct *work)
> +{
> +	struct intel_hdcp *hdcp = container_of(to_delayed_work(work),
> +					       struct intel_hdcp,
> +					       check_work);
> +	struct intel_connector *connector = intel_hdcp_to_connector(hdcp);
> +
> +	_intel_hdcp_check_work(connector);
> +}
> +
>  static int i915_hdcp_component_match(struct device *dev, void *data)
>  {
>  	return !strcmp(dev->driver->name, "mei_hdcp");
> @@ -1156,7 +1177,8 @@ int intel_hdcp_disable(struct intel_connector *connector)
>  
>  	if (hdcp->value != DRM_MODE_CONTENT_PROTECTION_UNDESIRED) {
>  		hdcp->value = DRM_MODE_CONTENT_PROTECTION_UNDESIRED;
> -		ret = _intel_hdcp_disable(connector);
> +		if (hdcp->hdcp_encrypted)
> +			ret = _intel_hdcp_disable(connector);
>  	}
>  
>  	mutex_unlock(&hdcp->mutex);
> @@ -1196,3 +1218,30 @@ void intel_hdcp_atomic_check(struct drm_connector *connector,
>  						   new_state->crtc);
>  	crtc_state->mode_changed = true;
>  }
> +
> +/* Handles the CP_IRQ raised from the DP HDCP sink */
> +void intel_hdcp_handle_cp_irq(struct intel_connector *connector)
> +{
> +	struct intel_hdcp *hdcp = &connector->hdcp;
> +
> +	if (!hdcp->shim)
> +		return;
> +
> +	/*
> +	 * As of now we want to handle CP_IRQ triggered while encryption is
> +	 * enabled. This includes the notification for Topology change,
> +	 * Link failure, reauth request etc.
> +	 * Auth msg availability notifications are ignored with mutex_trylock
> +	 * as authentication holds the lock. Lock might be taken for link check
> +	 * or hdcp_disable too. In either of state we need not handle the
> +	 * CP_IRQ, for known reasons.
> +	 */
> +	if (!mutex_trylock(&hdcp->mutex))

This is not a good way to fix recursions, because the lock might be held
by someone else for other reasons, and then you just drop events on the
floor. Worse, usually it works, except when it stops working.

Since you already have a separate worker just schedule that one, and leave
it up to the worker to filter out events we don't care about.

> +		return;
> +
> +	if (!hdcp->hdcp_encrypted)
> +		return;

This check would need to be moved intel_hdcp_check_link().
> +
> +	mutex_unlock(&hdcp->mutex);
> +	_intel_hdcp_check_work(connector);

So instead of the direct call we need a schedule_work() here (without
delay ofc). Note that if the work is already scheduled it won't be
scheduled to run twice, so should just work as-is I think.
-Daniel
> +}
> -- 
> 2.7.4
> 

-- 
Daniel Vetter
Software Engineer, Intel Corporation
http://blog.ffwll.ch
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 103+ messages in thread

* Re: [PATCH v9 10/39] drm/i915: Implement HDCP2.2 receiver authentication
  2018-12-19 15:35       ` Daniel Vetter
@ 2018-12-19 15:48         ` C, Ramalingam
  0 siblings, 0 replies; 103+ messages in thread
From: C, Ramalingam @ 2018-12-19 15:48 UTC (permalink / raw)
  To: Daniel Vetter
  Cc: daniel.vetter, intel-gfx, dri-devel, seanpaul, tomas.winkler


[-- Attachment #1.1: Type: text/plain, Size: 1621 bytes --]


On 12/19/2018 9:05 PM, Daniel Vetter wrote:
> On Wed, Dec 19, 2018 at 08:35:48PM +0530, C, Ramalingam wrote:
>> On 12/19/2018 8:05 PM, Daniel Vetter wrote:
>>> On Thu, Dec 13, 2018 at 09:31:12AM +0530, Ramalingam C wrote:
>>>> +	if (!hdcp->is_repeater && shim->config_stream_type) {
>>>> +		/*
>>>> +		 * Errata for DP: As Stream type is used for encryption,
>>>> +		 * Receiver should be communicated with stream type for the
>>>> +		 * decryption of the content.
>>>> +		 * Repeater will be communicated with stream type as a
>>>> +		 * part of it's auth later in time.
>>>> +		 */
>>> I'm not following what you want to say with this comment, and haven't
>>> found anything in the hdcp2 dp spec about this either.
>> this is there in the errata of DP HDCP2.2 spec.
>> hdcp2.2 encryption algo involves the stream type as a parameter.
>> And as part of hdcp auth mentioned in base spec DP repeaters receive that details to decrypt the content.
>> But DP receivers dont get it. So errata adds the missing piece for decryption.
> Ok I found it, but the fake HDCP_2_2_ERRATA_DP_STREAM_TYPE define is kinda
> annoying. It doesn't exist in the spec, but we put it into the drm_hdcp.h
> header. Since you have a special ->config_stream_type hook for this
> anyway, and it's only needed for DP, please move that into the shim
> implementation.
>
> And then a follow-up patch to remove the fake #define from drm_hdcp.h.

This is defined to make the hdcp_shim interface to look common between DP and HDMI.
We can move this errata msg definition and its msg_id into intel_drv.h just for the intel's consumption.

-Ram

> -Daniel

[-- Attachment #1.2: Type: text/html, Size: 2581 bytes --]

[-- Attachment #2: Type: text/plain, Size: 160 bytes --]

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 103+ messages in thread

* Re: [PATCH v9 09/39] drm/i915: Enable and Disable of HDCP2.2
  2018-12-13  4:01 ` [PATCH v9 09/39] drm/i915: Enable and Disable of HDCP2.2 Ramalingam C
@ 2018-12-19 15:54   ` Daniel Vetter
  0 siblings, 0 replies; 103+ messages in thread
From: Daniel Vetter @ 2018-12-19 15:54 UTC (permalink / raw)
  To: Ramalingam C
  Cc: daniel.vetter, intel-gfx, dri-devel, uma.shankar, seanpaul,
	tomas.winkler

On Thu, Dec 13, 2018 at 09:31:11AM +0530, Ramalingam C wrote:
> Considering that HDCP2.2 is more secure than HDCP1.4, When a setup
> supports HDCP2.2 and HDCP1.4, HDCP2.2 will be enabled.
> 
> When HDCP2.2 enabling fails and HDCP1.4 is supported, HDCP1.4 is
> enabled.
> 
> This change implements a sequence of enabling and disabling of
> HDCP2.2 authentication and HDCP2.2 port encryption.
> 
> v2:
>   Included few optimization suggestions [Chris Wilson]
>   Commit message is updated as per the rebased version.
>   intel_wait_for_register is used instead of wait_for. [Chris Wilson]
> v3:
>   Extra comment added and Style issue fixed [Uma]
> v4:
>   Rebased as part of patch reordering.
>   HDCP2 encryption status is tracked.
>   HW state check is moved into WARN_ON [Daniel]
> v5:
>   Redefined the mei service functions as per comp redesign.
>   Merged patches related to hdcp2.2 enabling and disabling [Sean Paul].
>   Required shim functionality is defined [Sean Paul]
> v6:
>   Return values are handles [Uma]
>   Realigned the code.
>   Check for comp_master is removed.
> v7:
>   HDCP2.2 is attempted only if mei interface is up.
>   Adjust to the new interface
>   Avoid bool usage in struct [Tomas]
> v8:
>   mei_binded status check is removed.
>   %s/hdcp2_in_use/hdcp2_encrypted
> 
> Signed-off-by: Ramalingam C <ramalingam.c@intel.com>

lgtm now.

Reviewed-by: Daniel Vetter <daniel.vetter@ffwll.ch>

> ---
>  drivers/gpu/drm/i915/intel_drv.h  |   7 ++
>  drivers/gpu/drm/i915/intel_hdcp.c | 202 +++++++++++++++++++++++++++++++++++---
>  2 files changed, 195 insertions(+), 14 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
> index decd0346c6a7..6d5361616ca3 100644
> --- a/drivers/gpu/drm/i915/intel_drv.h
> +++ b/drivers/gpu/drm/i915/intel_drv.h
> @@ -383,6 +383,10 @@ struct intel_hdcp_shim {
>  
>  	/* HDCP adaptation(DP/HDMI) required on the port */
>  	enum hdcp_wired_protocol protocol;
> +
> +	/* Detects whether Panel is HDCP2.2 capable */
> +	int (*hdcp_2_2_capable)(struct intel_digital_port *intel_dig_port,
> +				bool *capable);
>  };
>  
>  struct intel_hdcp {
> @@ -400,6 +404,9 @@ struct intel_hdcp {
>  	/* Flag indicates whether this connector supports HDCP2.2 or not. */
>  	u8 hdcp2_supported;
>  
> +	/* HDCP2.2 Encryption status */
> +	u8 hdcp2_encrypted;
> +
>  	/*
>  	 * Content Stream Type defined by content owner. TYPE0(0x0) content can
>  	 * flow in the link protected by HDCP2.2 or HDCP1.4, where as TYPE1(0x1)
> diff --git a/drivers/gpu/drm/i915/intel_hdcp.c b/drivers/gpu/drm/i915/intel_hdcp.c
> index 2b7814a6f12b..f0ee448e6546 100644
> --- a/drivers/gpu/drm/i915/intel_hdcp.c
> +++ b/drivers/gpu/drm/i915/intel_hdcp.c
> @@ -75,6 +75,23 @@ bool intel_hdcp_capable(struct intel_connector *connector)
>  	return capable;
>  }
>  
> +/* Is HDCP2.2 capable on Platform and Sink */
> +static bool intel_hdcp2_capable(struct intel_connector *connector)
> +{
> +	struct intel_digital_port *intel_dig_port = conn_to_dig_port(connector);
> +	struct intel_hdcp *hdcp = &connector->hdcp;
> +	bool capable = false;
> +
> +	/* I915 support for HDCP2.2 */
> +	if (!hdcp->hdcp2_supported)
> +		return false;
> +
> +	/* Sink's capability for HDCP2.2 */
> +	hdcp->shim->hdcp_2_2_capable(intel_dig_port, &capable);
> +
> +	return capable;
> +}
> +
>  static inline bool intel_hdcp_in_use(struct intel_connector *connector)
>  {
>  	struct drm_i915_private *dev_priv = to_i915(connector->base.dev);
> @@ -1014,8 +1031,7 @@ int hdcp2_authenticate_port(struct intel_connector *connector)
>  	return ret;
>  }
>  
> -static __attribute__((unused))
> -int hdcp2_close_mei_session(struct intel_connector *connector)
> +static int hdcp2_close_mei_session(struct intel_connector *connector)
>  {
>  	struct drm_i915_private *dev_priv = to_i915(connector->base.dev);
>  	struct i915_component_master *comp = dev_priv->comp_master;
> @@ -1024,12 +1040,157 @@ int hdcp2_close_mei_session(struct intel_connector *connector)
>  						  &connector->hdcp.port_data);
>  }
>  
> -static __attribute__((unused))
> -int hdcp2_deauthenticate_port(struct intel_connector *connector)
> +static int hdcp2_deauthenticate_port(struct intel_connector *connector)
>  {
>  	return hdcp2_close_mei_session(connector);
>  }
>  
> +static int hdcp2_authenticate_sink(struct intel_connector *connector)
> +{
> +	DRM_ERROR("Sink authentication is done in subsequent patches\n");
> +
> +	return -EINVAL;
> +}
> +
> +static int hdcp2_enable_encryption(struct intel_connector *connector)
> +{
> +	struct intel_digital_port *intel_dig_port = conn_to_dig_port(connector);
> +	struct drm_i915_private *dev_priv = to_i915(connector->base.dev);
> +	struct intel_hdcp *hdcp = &connector->hdcp;
> +	enum port port = connector->encoder->port;
> +	int ret;
> +
> +	WARN_ON(I915_READ(HDCP2_STATUS_DDI(port)) & LINK_ENCRYPTION_STATUS);
> +
> +	if (hdcp->shim->toggle_signalling) {
> +		ret = hdcp->shim->toggle_signalling(intel_dig_port, true);
> +		if (ret) {
> +			DRM_ERROR("Failed to enable HDCP signalling. %d\n",
> +				  ret);
> +			return ret;
> +		}
> +	}
> +
> +	if (I915_READ(HDCP2_STATUS_DDI(port)) & LINK_AUTH_STATUS) {
> +		/* Link is Authenticated. Now set for Encryption */
> +		I915_WRITE(HDCP2_CTL_DDI(port),
> +			   I915_READ(HDCP2_CTL_DDI(port)) |
> +			   CTL_LINK_ENCRYPTION_REQ);
> +	}
> +
> +	ret = intel_wait_for_register(dev_priv, HDCP2_STATUS_DDI(port),
> +				      LINK_ENCRYPTION_STATUS,
> +				      LINK_ENCRYPTION_STATUS,
> +				      ENCRYPT_STATUS_CHANGE_TIMEOUT_MS);
> +
> +	return ret;
> +}
> +
> +static int hdcp2_disable_encryption(struct intel_connector *connector)
> +{
> +	struct intel_digital_port *intel_dig_port = conn_to_dig_port(connector);
> +	struct drm_i915_private *dev_priv = to_i915(connector->base.dev);
> +	struct intel_hdcp *hdcp = &connector->hdcp;
> +	enum port port = connector->encoder->port;
> +	int ret;
> +
> +	WARN_ON(!(I915_READ(HDCP2_STATUS_DDI(port)) & LINK_ENCRYPTION_STATUS));
> +
> +	I915_WRITE(HDCP2_CTL_DDI(port),
> +		   I915_READ(HDCP2_CTL_DDI(port)) & ~CTL_LINK_ENCRYPTION_REQ);
> +
> +	ret = intel_wait_for_register(dev_priv, HDCP2_STATUS_DDI(port),
> +				      LINK_ENCRYPTION_STATUS, 0x0,
> +				      ENCRYPT_STATUS_CHANGE_TIMEOUT_MS);
> +	if (ret == -ETIMEDOUT)
> +		DRM_DEBUG_KMS("Disable Encryption Timedout");
> +
> +	if (hdcp->shim->toggle_signalling) {
> +		ret = hdcp->shim->toggle_signalling(intel_dig_port, false);
> +		if (ret) {
> +			DRM_ERROR("Failed to disable HDCP signalling. %d\n",
> +				  ret);
> +			return ret;
> +		}
> +	}
> +
> +	return ret;
> +}
> +
> +static int hdcp2_authenticate_and_encrypt(struct intel_connector *connector)
> +{
> +	int ret, i, tries = 3;
> +
> +	for (i = 0; i < tries; i++) {
> +		ret = hdcp2_authenticate_sink(connector);
> +		if (!ret)
> +			break;
> +
> +		/* Clearing the mei hdcp session */
> +		DRM_DEBUG_KMS("HDCP2.2 Auth %d of %d Failed.(%d)\n",
> +			      i + 1, tries, ret);
> +		if (hdcp2_deauthenticate_port(connector) < 0)
> +			DRM_DEBUG_KMS("Port deauth failed.\n");
> +	}
> +
> +	if (i != tries) {
> +		/*
> +		 * Ensuring the required 200mSec min time interval between
> +		 * Session Key Exchange and encryption.
> +		 */
> +		msleep(HDCP_2_2_DELAY_BEFORE_ENCRYPTION_EN);
> +		ret = hdcp2_enable_encryption(connector);
> +		if (ret < 0) {
> +			DRM_DEBUG_KMS("Encryption Enable Failed.(%d)\n", ret);
> +			if (hdcp2_deauthenticate_port(connector) < 0)
> +				DRM_DEBUG_KMS("Port deauth failed.\n");
> +		}
> +	}
> +
> +	return ret;
> +}
> +
> +static int _intel_hdcp2_enable(struct intel_connector *connector)
> +{
> +	struct intel_hdcp *hdcp = &connector->hdcp;
> +	int ret;
> +
> +	DRM_DEBUG_KMS("[%s:%d] HDCP2.2 is being enabled. Type: %d\n",
> +		      connector->base.name, connector->base.base.id,
> +		      hdcp->content_type);
> +
> +	ret = hdcp2_authenticate_and_encrypt(connector);
> +	if (ret) {
> +		DRM_DEBUG_KMS("HDCP2 Type%d  Enabling Failed. (%d)\n",
> +			      hdcp->content_type, ret);
> +		return ret;
> +	}
> +
> +	DRM_DEBUG_KMS("[%s:%d] HDCP2.2 is enabled. Type %d\n",
> +		      connector->base.name, connector->base.base.id,
> +		      hdcp->content_type);
> +
> +	hdcp->hdcp2_encrypted = 1;
> +	return 0;
> +}
> +
> +static int _intel_hdcp2_disable(struct intel_connector *connector)
> +{
> +	int ret;
> +
> +	DRM_DEBUG_KMS("[%s:%d] HDCP2.2 is being Disabled\n",
> +		      connector->base.name, connector->base.base.id);
> +
> +	ret = hdcp2_disable_encryption(connector);
> +
> +	if (hdcp2_deauthenticate_port(connector) < 0)
> +		DRM_DEBUG_KMS("Port deauth failed.\n");
> +
> +	connector->hdcp.hdcp2_encrypted = 0;
> +
> +	return ret;
> +}
> +
>  static inline void _intel_hdcp_check_work(struct intel_connector *connector)
>  {
>  	struct intel_hdcp *hdcp = &connector->hdcp;
> @@ -1145,22 +1306,33 @@ int intel_hdcp_init(struct intel_connector *connector,
>  int intel_hdcp_enable(struct intel_connector *connector)
>  {
>  	struct intel_hdcp *hdcp = &connector->hdcp;
> -	int ret;
> +	int ret = -EINVAL;
>  
>  	if (!hdcp->shim)
>  		return -ENOENT;
>  
>  	mutex_lock(&hdcp->mutex);
>  
> -	ret = _intel_hdcp_enable(connector);
> -	if (ret)
> -		goto out;
> +	/*
> +	 * Considering that HDCP2.2 is more secure than HDCP1.4, If the setup
> +	 * is capable of HDCP2.2, it is preferred to use HDCP2.2.
> +	 */
> +	if (intel_hdcp2_capable(connector))
> +		ret = _intel_hdcp2_enable(connector);
> +
> +	/* When HDCP2.2 fails, HDCP1.4 will be attempted */
> +	if (ret && intel_hdcp_capable(connector)) {
> +		ret = _intel_hdcp_enable(connector);
> +		if (!ret)
> +			schedule_delayed_work(&hdcp->check_work,
> +					      DRM_HDCP_CHECK_PERIOD_MS);
> +	}
> +
> +	if (!ret) {
> +		hdcp->value = DRM_MODE_CONTENT_PROTECTION_ENABLED;
> +		schedule_work(&hdcp->prop_work);
> +	}
>  
> -	hdcp->value = DRM_MODE_CONTENT_PROTECTION_ENABLED;
> -	schedule_work(&hdcp->prop_work);
> -	schedule_delayed_work(&hdcp->check_work,
> -			      DRM_HDCP_CHECK_PERIOD_MS);
> -out:
>  	mutex_unlock(&hdcp->mutex);
>  	return ret;
>  }
> @@ -1177,7 +1349,9 @@ int intel_hdcp_disable(struct intel_connector *connector)
>  
>  	if (hdcp->value != DRM_MODE_CONTENT_PROTECTION_UNDESIRED) {
>  		hdcp->value = DRM_MODE_CONTENT_PROTECTION_UNDESIRED;
> -		if (hdcp->hdcp_encrypted)
> +		if (hdcp->hdcp2_encrypted)
> +			ret = _intel_hdcp2_disable(connector);
> +		else if (hdcp->hdcp_encrypted)
>  			ret = _intel_hdcp_disable(connector);
>  	}
>  
> -- 
> 2.7.4
> 

-- 
Daniel Vetter
Software Engineer, Intel Corporation
http://blog.ffwll.ch
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 103+ messages in thread

* Re: [PATCH v9 13/39] drm: HDCP2.2 link check related constants
  2018-12-19 15:39     ` C, Ramalingam
@ 2018-12-19 15:58       ` Daniel Vetter
  2018-12-19 16:22         ` C, Ramalingam
  0 siblings, 1 reply; 103+ messages in thread
From: Daniel Vetter @ 2018-12-19 15:58 UTC (permalink / raw)
  To: C, Ramalingam
  Cc: daniel.vetter, intel-gfx, dri-devel, uma.shankar, seanpaul,
	tomas.winkler

On Wed, Dec 19, 2018 at 09:09:00PM +0530, C, Ramalingam wrote:
> 
> On 12/19/2018 8:46 PM, Daniel Vetter wrote:
> > On Thu, Dec 13, 2018 at 09:31:15AM +0530, Ramalingam C wrote:
> > > Enums and macros are defined for HDCP2.2 link check.
> > > 
> > > Signed-off-by: Ramalingam C <ramalingam.c@intel.com>
> > > ---
> > >   include/drm/drm_hdcp.h | 8 ++++++++
> > >   1 file changed, 8 insertions(+)
> > > 
> > > diff --git a/include/drm/drm_hdcp.h b/include/drm/drm_hdcp.h
> > > index d8093ecf3ddc..21a128e7020a 100644
> > > --- a/include/drm/drm_hdcp.h
> > > +++ b/include/drm/drm_hdcp.h
> > > @@ -11,6 +11,14 @@
> > >   /* Period of hdcp checks (to ensure we're still authenticated) */
> > >   #define DRM_HDCP_CHECK_PERIOD_MS		(128 * 16)
> > > +#define DRM_HDCP2_CHECK_PERIOD_MS		500
> > This one here is good imo, and has my Reviewed-by: Daniel Vetter <daniel.vetter@ffwll.ch>
> > 
> > > +
> > > +enum check_link_response {
> > > +	DRM_HDCP_LINK_PROTECTED	= 0,
> > > +	DRM_HDCP_TOPOLOGY_CHANGE,
> > > +	DRM_HDCP_LINK_INTEGRITY_FAILURE,
> > > +	DRM_HDCP_REAUTH_REQUEST
> > > +};
> > But this one here is just a part of the intel_hdcp_shim interface. I think
> > we should put into the intel_drv.h header, and change the return value of
> > the check_2_2_link hook to this enum. I think that would clarify the code
> > a lot. Plus then ofc merge this part into the first patch that uses it.
> 
> daniel,
> 
> this is generic link check results as per the HDCP spec. This could be used
> by any other driver in DRM. Still should i move as local to intel?

Yeah I think makes more sense. intel_hdcp_shim could also be used as
fairly generic hdcp implementation, but right now it isn't. Better to keep
things together that are used together.
-Daniel

> 
> -Ram
> 
> > 
> > With that remaining patches have my ack, too.
> > 
> > Cheers, Daniel
> > 
> > >   /* Shared lengths/masks between HDMI/DVI/DisplayPort */
> > >   #define DRM_HDCP_AN_LEN				8
> > > -- 
> > > 2.7.4
> > > 

-- 
Daniel Vetter
Software Engineer, Intel Corporation
http://blog.ffwll.ch
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 103+ messages in thread

* Re: [PATCH v9 37/39] drm/i915: Fix KBL HDCP2.2 encrypt status signalling
  2018-12-19 15:40   ` Daniel Vetter
@ 2018-12-19 16:16     ` C, Ramalingam
  0 siblings, 0 replies; 103+ messages in thread
From: C, Ramalingam @ 2018-12-19 16:16 UTC (permalink / raw)
  To: Daniel Vetter
  Cc: daniel.vetter, intel-gfx, dri-devel, seanpaul, tomas.winkler


On 12/19/2018 9:10 PM, Daniel Vetter wrote:
> On Thu, Dec 13, 2018 at 09:31:39AM +0530, Ramalingam C wrote:
>> Implement the required WA sequence for KBL to fix the
>> incorrect positioning of the window of oppurtunity and enc_en
>> signalling.
>>
>> Signed-off-by: Ramalingam C <ramalingam.c@intel.com>
>> ---
>>   drivers/gpu/drm/i915/intel_hdcp.c | 29 +++++++++++++++++++++++++++++
>>   1 file changed, 29 insertions(+)
>>
>> diff --git a/drivers/gpu/drm/i915/intel_hdcp.c b/drivers/gpu/drm/i915/intel_hdcp.c
>> index 42327ed30903..2b9e1b6d0b1e 100644
>> --- a/drivers/gpu/drm/i915/intel_hdcp.c
>> +++ b/drivers/gpu/drm/i915/intel_hdcp.c
>> @@ -12,6 +12,7 @@
>>   #include <linux/i2c.h>
>>   #include <linux/random.h>
>>   #include <linux/component.h>
>> +#include <linux/delay.h>
>>   
>>   #include "intel_drv.h"
>>   #include "i915_reg.h"
>> @@ -20,6 +21,27 @@
>>   #define ENCRYPT_STATUS_CHANGE_TIMEOUT_MS	50
>>   #define HDCP2_LC_RETRY_CNT			3
>>   
>> +static void kbl_repositioning_enc_en_signal(struct intel_connector *connector)
>> +{
>> +	struct drm_i915_private *dev_priv = to_i915(connector->base.dev);
>> +	struct intel_digital_port *intel_dig_port = conn_to_dig_port(connector);
>> +	struct intel_hdcp *hdcp = &connector->hdcp;
>> +	struct drm_crtc *crtc = connector->base.state->crtc;
>> +	struct intel_crtc *intel_crtc = container_of(crtc,
>> +						     struct intel_crtc, base);
>> +	u32 scanline;
>> +
>> +	for (;;) {
>> +		scanline = I915_READ(PIPEDSL(intel_crtc->pipe));
>> +		if (scanline > 100 && scanline < 200)
>> +			break;
>> +		usleep_range(25, 50);
>> +	}
>> +
>> +	hdcp->shim->toggle_signalling(intel_dig_port, false);
>> +	hdcp->shim->toggle_signalling(intel_dig_port, true);
>> +}
>> +
>>   static
>>   bool intel_hdcp_is_ksv_valid(u8 *ksv)
>>   {
>> @@ -1382,6 +1404,13 @@ static int hdcp2_enable_encryption(struct intel_connector *connector)
>>   	}
>>   
>>   	if (I915_READ(HDCP2_STATUS_DDI(port)) & LINK_AUTH_STATUS) {
>> +		/*
>> +		 * WA: To fix incorrect positioning of the window of
>> +		 * opportunity and enc_en signalling in KABYLAKE.
>> +		 */
>> +		if (IS_KABYLAKE(dev_priv) && hdcp->shim->toggle_signalling)
>> +			kbl_repositioning_enc_en_signal(connector);
> This is a bit a layering violation of the shim. I think it'd be better to
> push this into the toggle_signalling implementation, which you call right
> above. That can easily check this register too, and retry. That way the
> kbl flow is all in one place.

Yes, any way this is a fix for hdcp_signalling for kbl. I will do that.

-Ram

>
> Bspec is down for me, so can't check the w/a itself :-(
> -Daniel
>
>> +
>>   		/* Link is Authenticated. Now set for Encryption */
>>   		I915_WRITE(HDCP2_CTL_DDI(port),
>>   			   I915_READ(HDCP2_CTL_DDI(port)) |
>> -- 
>> 2.7.4
>>
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 103+ messages in thread

* Re: [PATCH v9 13/39] drm: HDCP2.2 link check related constants
  2018-12-19 15:58       ` Daniel Vetter
@ 2018-12-19 16:22         ` C, Ramalingam
  2018-12-19 16:35           ` Daniel Vetter
  0 siblings, 1 reply; 103+ messages in thread
From: C, Ramalingam @ 2018-12-19 16:22 UTC (permalink / raw)
  To: Daniel Vetter
  Cc: daniel.vetter, intel-gfx, dri-devel, seanpaul, tomas.winkler


On 12/19/2018 9:28 PM, Daniel Vetter wrote:
> On Wed, Dec 19, 2018 at 09:09:00PM +0530, C, Ramalingam wrote:
>> On 12/19/2018 8:46 PM, Daniel Vetter wrote:
>>> On Thu, Dec 13, 2018 at 09:31:15AM +0530, Ramalingam C wrote:
>>>> Enums and macros are defined for HDCP2.2 link check.
>>>>
>>>> Signed-off-by: Ramalingam C <ramalingam.c@intel.com>
>>>> ---
>>>>    include/drm/drm_hdcp.h | 8 ++++++++
>>>>    1 file changed, 8 insertions(+)
>>>>
>>>> diff --git a/include/drm/drm_hdcp.h b/include/drm/drm_hdcp.h
>>>> index d8093ecf3ddc..21a128e7020a 100644
>>>> --- a/include/drm/drm_hdcp.h
>>>> +++ b/include/drm/drm_hdcp.h
>>>> @@ -11,6 +11,14 @@
>>>>    /* Period of hdcp checks (to ensure we're still authenticated) */
>>>>    #define DRM_HDCP_CHECK_PERIOD_MS		(128 * 16)
>>>> +#define DRM_HDCP2_CHECK_PERIOD_MS		500
>>> This one here is good imo, and has my Reviewed-by: Daniel Vetter <daniel.vetter@ffwll.ch>
>>>
>>>> +
>>>> +enum check_link_response {
>>>> +	DRM_HDCP_LINK_PROTECTED	= 0,
>>>> +	DRM_HDCP_TOPOLOGY_CHANGE,
>>>> +	DRM_HDCP_LINK_INTEGRITY_FAILURE,
>>>> +	DRM_HDCP_REAUTH_REQUEST
>>>> +};
>>> But this one here is just a part of the intel_hdcp_shim interface. I think
>>> we should put into the intel_drv.h header, and change the return value of
>>> the check_2_2_link hook to this enum. I think that would clarify the code
>>> a lot. Plus then ofc merge this part into the first patch that uses it.
>> daniel,
>>
>> this is generic link check results as per the HDCP spec. This could be used
>> by any other driver in DRM. Still should i move as local to intel?
> Yeah I think makes more sense. intel_hdcp_shim could also be used as
> fairly generic hdcp implementation, but right now it isn't. Better to keep
> things together that are used together.

thanks. With this i will use your R-b ?

-Ram

> -Daniel
>
>> -Ram
>>
>>> With that remaining patches have my ack, too.
>>>
>>> Cheers, Daniel
>>>
>>>>    /* Shared lengths/masks between HDMI/DVI/DisplayPort */
>>>>    #define DRM_HDCP_AN_LEN				8
>>>> -- 
>>>> 2.7.4
>>>>
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 103+ messages in thread

* Re: [PATCH v9 13/39] drm: HDCP2.2 link check related constants
  2018-12-19 16:22         ` C, Ramalingam
@ 2018-12-19 16:35           ` Daniel Vetter
  2018-12-19 17:01             ` C, Ramalingam
  0 siblings, 1 reply; 103+ messages in thread
From: Daniel Vetter @ 2018-12-19 16:35 UTC (permalink / raw)
  To: C, Ramalingam; +Cc: intel-gfx, dri-devel, Uma Shankar, Sean Paul, Tomas Winkler

On Wed, Dec 19, 2018 at 5:22 PM C, Ramalingam <ramalingam.c@intel.com> wrote:
>
>
> On 12/19/2018 9:28 PM, Daniel Vetter wrote:
> > On Wed, Dec 19, 2018 at 09:09:00PM +0530, C, Ramalingam wrote:
> >> On 12/19/2018 8:46 PM, Daniel Vetter wrote:
> >>> On Thu, Dec 13, 2018 at 09:31:15AM +0530, Ramalingam C wrote:
> >>>> Enums and macros are defined for HDCP2.2 link check.
> >>>>
> >>>> Signed-off-by: Ramalingam C <ramalingam.c@intel.com>
> >>>> ---
> >>>>    include/drm/drm_hdcp.h | 8 ++++++++
> >>>>    1 file changed, 8 insertions(+)
> >>>>
> >>>> diff --git a/include/drm/drm_hdcp.h b/include/drm/drm_hdcp.h
> >>>> index d8093ecf3ddc..21a128e7020a 100644
> >>>> --- a/include/drm/drm_hdcp.h
> >>>> +++ b/include/drm/drm_hdcp.h
> >>>> @@ -11,6 +11,14 @@
> >>>>    /* Period of hdcp checks (to ensure we're still authenticated) */
> >>>>    #define DRM_HDCP_CHECK_PERIOD_MS                (128 * 16)
> >>>> +#define DRM_HDCP2_CHECK_PERIOD_MS         500
> >>> This one here is good imo, and has my Reviewed-by: Daniel Vetter <daniel.vetter@ffwll.ch>
> >>>
> >>>> +
> >>>> +enum check_link_response {
> >>>> +  DRM_HDCP_LINK_PROTECTED = 0,
> >>>> +  DRM_HDCP_TOPOLOGY_CHANGE,
> >>>> +  DRM_HDCP_LINK_INTEGRITY_FAILURE,
> >>>> +  DRM_HDCP_REAUTH_REQUEST
> >>>> +};
> >>> But this one here is just a part of the intel_hdcp_shim interface. I think
> >>> we should put into the intel_drv.h header, and change the return value of
> >>> the check_2_2_link hook to this enum. I think that would clarify the code
> >>> a lot. Plus then ofc merge this part into the first patch that uses it.
> >> daniel,
> >>
> >> this is generic link check results as per the HDCP spec. This could be used
> >> by any other driver in DRM. Still should i move as local to intel?
> > Yeah I think makes more sense. intel_hdcp_shim could also be used as
> > fairly generic hdcp implementation, but right now it isn't. Better to keep
> > things together that are used together.
>
> thanks. With this i will use your R-b ?

Just to clarify: R-b with the enum moved to intel_drv.h, together with
the intel_hdcp_shim using it. Just realized that my reply is a bit
confusing.
-Daniel

>
> -Ram
>
> > -Daniel
> >
> >> -Ram
> >>
> >>> With that remaining patches have my ack, too.
> >>>
> >>> Cheers, Daniel
> >>>
> >>>>    /* Shared lengths/masks between HDMI/DVI/DisplayPort */
> >>>>    #define DRM_HDCP_AN_LEN                         8
> >>>> --
> >>>> 2.7.4
> >>>>



-- 
Daniel Vetter
Software Engineer, Intel Corporation
+41 (0) 79 365 57 48 - http://blog.ffwll.ch
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 103+ messages in thread

* Re: [PATCH v9 13/39] drm: HDCP2.2 link check related constants
  2018-12-19 16:35           ` Daniel Vetter
@ 2018-12-19 17:01             ` C, Ramalingam
  0 siblings, 0 replies; 103+ messages in thread
From: C, Ramalingam @ 2018-12-19 17:01 UTC (permalink / raw)
  To: Daniel Vetter; +Cc: intel-gfx, dri-devel, Sean Paul, Tomas Winkler


On 12/19/2018 10:05 PM, Daniel Vetter wrote:
> On Wed, Dec 19, 2018 at 5:22 PM C, Ramalingam <ramalingam.c@intel.com> wrote:
>>
>> On 12/19/2018 9:28 PM, Daniel Vetter wrote:
>>> On Wed, Dec 19, 2018 at 09:09:00PM +0530, C, Ramalingam wrote:
>>>> On 12/19/2018 8:46 PM, Daniel Vetter wrote:
>>>>> On Thu, Dec 13, 2018 at 09:31:15AM +0530, Ramalingam C wrote:
>>>>>> Enums and macros are defined for HDCP2.2 link check.
>>>>>>
>>>>>> Signed-off-by: Ramalingam C <ramalingam.c@intel.com>
>>>>>> ---
>>>>>>     include/drm/drm_hdcp.h | 8 ++++++++
>>>>>>     1 file changed, 8 insertions(+)
>>>>>>
>>>>>> diff --git a/include/drm/drm_hdcp.h b/include/drm/drm_hdcp.h
>>>>>> index d8093ecf3ddc..21a128e7020a 100644
>>>>>> --- a/include/drm/drm_hdcp.h
>>>>>> +++ b/include/drm/drm_hdcp.h
>>>>>> @@ -11,6 +11,14 @@
>>>>>>     /* Period of hdcp checks (to ensure we're still authenticated) */
>>>>>>     #define DRM_HDCP_CHECK_PERIOD_MS                (128 * 16)
>>>>>> +#define DRM_HDCP2_CHECK_PERIOD_MS         500
>>>>> This one here is good imo, and has my Reviewed-by: Daniel Vetter <daniel.vetter@ffwll.ch>
>>>>>
>>>>>> +
>>>>>> +enum check_link_response {
>>>>>> +  DRM_HDCP_LINK_PROTECTED = 0,
>>>>>> +  DRM_HDCP_TOPOLOGY_CHANGE,
>>>>>> +  DRM_HDCP_LINK_INTEGRITY_FAILURE,
>>>>>> +  DRM_HDCP_REAUTH_REQUEST
>>>>>> +};
>>>>> But this one here is just a part of the intel_hdcp_shim interface. I think
>>>>> we should put into the intel_drv.h header, and change the return value of
>>>>> the check_2_2_link hook to this enum. I think that would clarify the code
>>>>> a lot. Plus then ofc merge this part into the first patch that uses it.
>>>> daniel,
>>>>
>>>> this is generic link check results as per the HDCP spec. This could be used
>>>> by any other driver in DRM. Still should i move as local to intel?
>>> Yeah I think makes more sense. intel_hdcp_shim could also be used as
>>> fairly generic hdcp implementation, but right now it isn't. Better to keep
>>> things together that are used together.
>> thanks. With this i will use your R-b ?
> Just to clarify: R-b with the enum moved to intel_drv.h, together with
> the intel_hdcp_shim using it. Just realized that my reply is a bit
> confusing.

True. I thought you didn't suggest any change :) I will do that the 
changes mentioned.

-Ram

> -Daniel
>
>> -Ram
>>
>>> -Daniel
>>>
>>>> -Ram
>>>>
>>>>> With that remaining patches have my ack, too.
>>>>>
>>>>> Cheers, Daniel
>>>>>
>>>>>>     /* Shared lengths/masks between HDMI/DVI/DisplayPort */
>>>>>>     #define DRM_HDCP_AN_LEN                         8
>>>>>> --
>>>>>> 2.7.4
>>>>>>
>
>
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 103+ messages in thread

* Re: [PATCH v9 10/39] drm/i915: Implement HDCP2.2 receiver authentication
  2018-12-19 15:05     ` C, Ramalingam
  2018-12-19 15:35       ` Daniel Vetter
@ 2018-12-19 18:40       ` Jani Nikula
  2018-12-19 21:36         ` Winkler, Tomas
  1 sibling, 1 reply; 103+ messages in thread
From: Jani Nikula @ 2018-12-19 18:40 UTC (permalink / raw)
  To: C, Ramalingam, Daniel Vetter
  Cc: daniel.vetter, intel-gfx, seanpaul, tomas.winkler, dri-devel

On Wed, 19 Dec 2018, "C, Ramalingam" <ramalingam.c@intel.com> wrote:
> On 12/19/2018 8:05 PM, Daniel Vetter wrote:
>> On Thu, Dec 13, 2018 at 09:31:12AM +0530, Ramalingam C wrote:
>>>   struct intel_hdcp {
>>> @@ -414,6 +430,24 @@ struct intel_hdcp {
>>>   	 */
>>>   	u8 content_type;
>>>   	struct hdcp_port_data port_data;
>>> +
>>> +	u8 is_paired;
>>> +	u8 is_repeater;
>> Make these two bool, will simplify the code a bunch.
>
> Seems there is a movement for not to use the bool in structures.

No. Please use bools in structs when it makes sense. Avoid bools in
structs when you need to care about memory footprint or alignment or
packing or the like. This is not one of those cases.

> Thats why I have changed these from bool to u8 from v8
> onwards. Checkpatch also complains on this

Sorry to say, checkpatch is not the authority although we do send out
automated checkpatch results.

BR,
Jani.

-- 
Jani Nikula, Intel Open Source Graphics Center
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 103+ messages in thread

* Re: [PATCH v9 10/39] drm/i915: Implement HDCP2.2 receiver authentication
  2018-12-19 18:40       ` Jani Nikula
@ 2018-12-19 21:36         ` Winkler, Tomas
  2018-12-20  7:42           ` Jani Nikula
  0 siblings, 1 reply; 103+ messages in thread
From: Winkler, Tomas @ 2018-12-19 21:36 UTC (permalink / raw)
  To: Jani Nikula, C, Ramalingam, Daniel Vetter
  Cc: daniel.vetter, intel-gfx, seanpaul, dri-devel


> 
> On Wed, 19 Dec 2018, "C, Ramalingam" <ramalingam.c@intel.com> wrote:
> > On 12/19/2018 8:05 PM, Daniel Vetter wrote:
> >> On Thu, Dec 13, 2018 at 09:31:12AM +0530, Ramalingam C wrote:
> >>>   struct intel_hdcp {
> >>> @@ -414,6 +430,24 @@ struct intel_hdcp {
> >>>   	 */
> >>>   	u8 content_type;
> >>>   	struct hdcp_port_data port_data;
> >>> +
> >>> +	u8 is_paired;
> >>> +	u8 is_repeater;
> >> Make these two bool, will simplify the code a bunch.
> >
> > Seems there is a movement for not to use the bool in structures.
> 
> No. Please use bools in structs when it makes sense. Avoid bools in structs
> when you need to care about memory footprint or alignment or packing or
> the like. This is not one of those cases.
> 
> > Thats why I have changed these from bool to u8 from v8 onwards.
> > Checkpatch also complains on this
> 
> Sorry to say, checkpatch is not the authority although we do send out
> automated checkpatch results.

I believe it was Linus' call to not use  bool in structs at all
https://lkml.org/lkml/2017/11/21/384

Thanks
Tomas

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 103+ messages in thread

* Re: [PATCH v9 10/39] drm/i915: Implement HDCP2.2 receiver authentication
  2018-12-19 21:36         ` Winkler, Tomas
@ 2018-12-20  7:42           ` Jani Nikula
  2018-12-20 14:28             ` Winkler, Tomas
  0 siblings, 1 reply; 103+ messages in thread
From: Jani Nikula @ 2018-12-20  7:42 UTC (permalink / raw)
  To: Winkler, Tomas, C, Ramalingam, Daniel Vetter
  Cc: daniel.vetter, intel-gfx, seanpaul, dri-devel

On Wed, 19 Dec 2018, "Winkler, Tomas" <tomas.winkler@intel.com> wrote:
>> 
>> On Wed, 19 Dec 2018, "C, Ramalingam" <ramalingam.c@intel.com> wrote:
>> > On 12/19/2018 8:05 PM, Daniel Vetter wrote:
>> >> On Thu, Dec 13, 2018 at 09:31:12AM +0530, Ramalingam C wrote:
>> >>>   struct intel_hdcp {
>> >>> @@ -414,6 +430,24 @@ struct intel_hdcp {
>> >>>   	 */
>> >>>   	u8 content_type;
>> >>>   	struct hdcp_port_data port_data;
>> >>> +
>> >>> +	u8 is_paired;
>> >>> +	u8 is_repeater;
>> >> Make these two bool, will simplify the code a bunch.
>> >
>> > Seems there is a movement for not to use the bool in structures.
>> 
>> No. Please use bools in structs when it makes sense. Avoid bools in structs
>> when you need to care about memory footprint or alignment or packing or
>> the like. This is not one of those cases.
>> 
>> > Thats why I have changed these from bool to u8 from v8 onwards.
>> > Checkpatch also complains on this
>> 
>> Sorry to say, checkpatch is not the authority although we do send out
>> automated checkpatch results.
>
> I believe it was Linus' call to not use  bool in structs at all
> https://lkml.org/lkml/2017/11/21/384

I don't care. That's a valid judgement in the context referenced, but
the conclusion "no bools in structs at all" isn't. In this case, I think
bools are the better option, and anything else makes the code worse.

BR,
Jani.

-- 
Jani Nikula, Intel Open Source Graphics Center
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 103+ messages in thread

* Re: [PATCH v9 08/39] drm/i915: hdcp1.4 CP_IRQ handling and SW encryption tracking
  2018-12-19 15:48   ` Daniel Vetter
@ 2018-12-20 11:29     ` C, Ramalingam
  2018-12-20 14:53       ` Daniel Vetter
  0 siblings, 1 reply; 103+ messages in thread
From: C, Ramalingam @ 2018-12-20 11:29 UTC (permalink / raw)
  To: Daniel Vetter
  Cc: daniel.vetter, intel-gfx, dri-devel, seanpaul, tomas.winkler


[-- Attachment #1.1: Type: text/plain, Size: 10249 bytes --]


On 12/19/2018 9:18 PM, Daniel Vetter wrote:
> On Thu, Dec 13, 2018 at 09:31:10AM +0530, Ramalingam C wrote:
>> "hdcp_encrypted" flag is defined to denote the HDCP1.4 encryption status.
>> This SW tracking is used to determine the need for real hdcp1.4 disable
>> and hdcp_check_link upon CP_IRQ.
>>
>> On CP_IRQ we filter the CP_IRQ related to the states like Link failure
>> and reauthentication req etc and handle them in hdcp_check_link.
>> CP_IRQ corresponding to the authentication msg availability are ignored.
>>
>> WARN_ON is added for the abrupt stop of HDCP encryption of a port.
>>
>> Signed-off-by: Ramalingam C <ramalingam.c@intel.com>
>> ---
>>   drivers/gpu/drm/i915/intel_dp.c   |  2 +-
>>   drivers/gpu/drm/i915/intel_drv.h  |  5 ++-
>>   drivers/gpu/drm/i915/intel_hdcp.c | 89 ++++++++++++++++++++++++++++++---------
>>   3 files changed, 74 insertions(+), 22 deletions(-)
>>
>> diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
>> index aba884c64879..89315e15fb34 100644
>> --- a/drivers/gpu/drm/i915/intel_dp.c
>> +++ b/drivers/gpu/drm/i915/intel_dp.c
>> @@ -4758,7 +4758,7 @@ static void intel_dp_check_service_irq(struct intel_dp *intel_dp)
>>   		intel_dp_handle_test_request(intel_dp);
>>   
>>   	if (val & DP_CP_IRQ)
>> -		intel_hdcp_check_link(intel_dp->attached_connector);
>> +		intel_hdcp_handle_cp_irq(intel_dp->attached_connector);
>>   
>>   	if (val & DP_SINK_SPECIFIC_IRQ)
>>   		DRM_DEBUG_DRIVER("Sink specific irq unhandled\n");
>> diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
>> index 191b6e0f086c..decd0346c6a7 100644
>> --- a/drivers/gpu/drm/i915/intel_drv.h
>> +++ b/drivers/gpu/drm/i915/intel_drv.h
>> @@ -393,6 +393,9 @@ struct intel_hdcp {
>>   	struct delayed_work check_work;
>>   	struct work_struct prop_work;
>>   
>> +	/* HDCP1.4 Encryption status */
>> +	u8 hdcp_encrypted;
> Another bool I guess? Or unsigned : 1;
as per #intel-gfx discussion I will fallback to bool.
>
>> +
>>   	/* HDCP2.2 related definitions */
>>   	/* Flag indicates whether this connector supports HDCP2.2 or not. */
>>   	u8 hdcp2_supported;
>> @@ -2058,10 +2061,10 @@ int intel_hdcp_init(struct intel_connector *connector,
>>   		    bool hdcp2_supported);
>>   int intel_hdcp_enable(struct intel_connector *connector);
>>   int intel_hdcp_disable(struct intel_connector *connector);
>> -int intel_hdcp_check_link(struct intel_connector *connector);
>>   bool is_hdcp_supported(struct drm_i915_private *dev_priv, enum port port);
>>   bool intel_hdcp_capable(struct intel_connector *connector);
>>   bool is_hdcp2_supported(struct drm_i915_private *dev_priv);
>> +void intel_hdcp_handle_cp_irq(struct intel_connector *connector);
>>   
>>   /* intel_psr.c */
>>   #define CAN_PSR(dev_priv) (HAS_PSR(dev_priv) && dev_priv->psr.sink_support)
>> diff --git a/drivers/gpu/drm/i915/intel_hdcp.c b/drivers/gpu/drm/i915/intel_hdcp.c
>> index 9405fce07b93..2b7814a6f12b 100644
>> --- a/drivers/gpu/drm/i915/intel_hdcp.c
>> +++ b/drivers/gpu/drm/i915/intel_hdcp.c
>> @@ -75,6 +75,16 @@ bool intel_hdcp_capable(struct intel_connector *connector)
>>   	return capable;
>>   }
>>   
>> +static inline bool intel_hdcp_in_use(struct intel_connector *connector)
>> +{
>> +	struct drm_i915_private *dev_priv = to_i915(connector->base.dev);
>> +	enum port port = connector->encoder->port;
>> +	u32 reg;
>> +
>> +	reg = I915_READ(PORT_HDCP_STATUS(port));
>> +	return reg & HDCP_STATUS_ENC;
>> +}
>> +
>>   static int intel_hdcp_poll_ksv_fifo(struct intel_digital_port *intel_dig_port,
>>   				    const struct intel_hdcp_shim *shim)
>>   {
>> @@ -669,6 +679,7 @@ static int _intel_hdcp_disable(struct intel_connector *connector)
>>   	DRM_DEBUG_KMS("[%s:%d] HDCP is being disabled...\n",
>>   		      connector->base.name, connector->base.base.id);
>>   
>> +	hdcp->hdcp_encrypted = 0;
>>   	I915_WRITE(PORT_HDCP_CONF(port), 0);
>>   	if (intel_wait_for_register(dev_priv, PORT_HDCP_STATUS(port), ~0, 0,
>>   				    ENCRYPT_STATUS_CHANGE_TIMEOUT_MS)) {
>> @@ -714,8 +725,10 @@ static int _intel_hdcp_enable(struct intel_connector *connector)
>>   	/* Incase of authentication failures, HDCP spec expects reauth. */
>>   	for (i = 0; i < tries; i++) {
>>   		ret = intel_hdcp_auth(conn_to_dig_port(connector), hdcp->shim);
>> -		if (!ret)
>> +		if (!ret) {
>> +			hdcp->hdcp_encrypted = 1;
>>   			return 0;
>> +		}
>>   
>>   		DRM_DEBUG_KMS("HDCP Auth failure (%d)\n", ret);
>>   
>> @@ -742,16 +755,17 @@ int intel_hdcp_check_link(struct intel_connector *connector)
>>   	enum port port = intel_dig_port->base.port;
>>   	int ret = 0;
>>   
>> -	if (!hdcp->shim)
>> -		return -ENOENT;
>> -
>>   	mutex_lock(&hdcp->mutex);
>>   
>> -	if (hdcp->value == DRM_MODE_CONTENT_PROTECTION_UNDESIRED)
>> +	/* Check_link valid only when HDCP1.4 is enabled */
>> +	if (hdcp->value != DRM_MODE_CONTENT_PROTECTION_ENABLED ||
>> +	    !hdcp->hdcp_encrypted) {
>> +		ret = -EINVAL;
>>   		goto out;
>> +	}
>>   
>> -	if (!(I915_READ(PORT_HDCP_STATUS(port)) & HDCP_STATUS_ENC)) {
>> -		DRM_ERROR("%s:%d HDCP check failed: link is not encrypted,%x\n",
>> +	if (WARN_ON(!intel_hdcp_in_use(connector))) {
>> +		DRM_ERROR("%s:%d HDCP link stopped encryption,%x\n",
>>   			  connector->base.name, connector->base.base.id,
>>   			  I915_READ(PORT_HDCP_STATUS(port)));
>>   		ret = -ENXIO;
>> @@ -792,18 +806,6 @@ int intel_hdcp_check_link(struct intel_connector *connector)
>>   	return ret;
>>   }
>>   
>> -static void intel_hdcp_check_work(struct work_struct *work)
>> -{
>> -	struct intel_hdcp *hdcp = container_of(to_delayed_work(work),
>> -					       struct intel_hdcp,
>> -					       check_work);
>> -	struct intel_connector *connector = intel_hdcp_to_connector(hdcp);
>> -
>> -	if (!intel_hdcp_check_link(connector))
>> -		schedule_delayed_work(&hdcp->check_work,
>> -				      DRM_HDCP_CHECK_PERIOD_MS);
>> -}
> Why move the function?

This will be used as common work fn for both 1.4 and 2.2. hdcp2_check_link will be defined below.
So moving this to the group of common functions. Basically to avoid the function declarations.

>> -
>>   static void intel_hdcp_prop_work(struct work_struct *work)
>>   {
>>   	struct intel_hdcp *hdcp = container_of(work, struct intel_hdcp,
>> @@ -1028,6 +1030,25 @@ int hdcp2_deauthenticate_port(struct intel_connector *connector)
>>   	return hdcp2_close_mei_session(connector);
>>   }
>>   
>> +static inline void _intel_hdcp_check_work(struct intel_connector *connector)
>> +{
>> +	struct intel_hdcp *hdcp = &connector->hdcp;
>> +
>> +	if (!intel_hdcp_check_link(connector))
>> +		schedule_delayed_work(&hdcp->check_work,
>> +				      DRM_HDCP_CHECK_PERIOD_MS);
>> +}
>> +
>> +static void intel_hdcp_check_work(struct work_struct *work)
>> +{
>> +	struct intel_hdcp *hdcp = container_of(to_delayed_work(work),
>> +					       struct intel_hdcp,
>> +					       check_work);
>> +	struct intel_connector *connector = intel_hdcp_to_connector(hdcp);
>> +
>> +	_intel_hdcp_check_work(connector);
>> +}
>> +
>>   static int i915_hdcp_component_match(struct device *dev, void *data)
>>   {
>>   	return !strcmp(dev->driver->name, "mei_hdcp");
>> @@ -1156,7 +1177,8 @@ int intel_hdcp_disable(struct intel_connector *connector)
>>   
>>   	if (hdcp->value != DRM_MODE_CONTENT_PROTECTION_UNDESIRED) {
>>   		hdcp->value = DRM_MODE_CONTENT_PROTECTION_UNDESIRED;
>> -		ret = _intel_hdcp_disable(connector);
>> +		if (hdcp->hdcp_encrypted)
>> +			ret = _intel_hdcp_disable(connector);
>>   	}
>>   
>>   	mutex_unlock(&hdcp->mutex);
>> @@ -1196,3 +1218,30 @@ void intel_hdcp_atomic_check(struct drm_connector *connector,
>>   						   new_state->crtc);
>>   	crtc_state->mode_changed = true;
>>   }
>> +
>> +/* Handles the CP_IRQ raised from the DP HDCP sink */
>> +void intel_hdcp_handle_cp_irq(struct intel_connector *connector)
>> +{
>> +	struct intel_hdcp *hdcp = &connector->hdcp;
>> +
>> +	if (!hdcp->shim)
>> +		return;
>> +
>> +	/*
>> +	 * As of now we want to handle CP_IRQ triggered while encryption is
>> +	 * enabled. This includes the notification for Topology change,
>> +	 * Link failure, reauth request etc.
>> +	 * Auth msg availability notifications are ignored with mutex_trylock
>> +	 * as authentication holds the lock. Lock might be taken for link check
>> +	 * or hdcp_disable too. In either of state we need not handle the
>> +	 * CP_IRQ, for known reasons.
>> +	 */
>> +	if (!mutex_trylock(&hdcp->mutex))
> This is not a good way to fix recursions, because the lock might be held
> by someone else for other reasons, and then you just drop events on the
> floor. Worse, usually it works, except when it stops working.

This is attempt to drop the CP_IRQ received during mutex is locked. 
Because of the below reasoning:

This mutex is taken by authentication enable/disable and check_link worker

when enable is in process this CP_IRQ will be notifying the msg availability to read. at present we dont use the CP_IRQ for msg read.
when disable is in process it doesn't matter why this CP_IRQ is triggered, we just want to ignore.

When check_link is in progress, that means hdcp is enabled. So this CP_IRQ is for topology change/reauth request etc,
which are handled by check_link. so once again we dont care for this CP_IRQs too.

So basically if the mutex is already taken we can ignore/drop the CP_IRQ. So mutex_trylock helps us to do this.
May be I should add all of these in the comment!?

While rethinking on that we can reschedule the check_link work on every CP_IRQ. As this is harmless i will do that. Makes things simple.

>
> Since you already have a separate worker just schedule that one, and leave
> it up to the worker to filter out events we don't care about.
>> +		return;
>> +
>> +	if (!hdcp->hdcp_encrypted)
>> +		return;
> This check would need to be moved intel_hdcp_check_link().

Function has the check already. I can avoid the check here and directly 
land into check_link work fn.

-Ram

>> +
>> +	mutex_unlock(&hdcp->mutex);
>> +	_intel_hdcp_check_work(connector);
> So instead of the direct call we need a schedule_work() here (without
> delay ofc). Note that if the work is already scheduled it won't be
> scheduled to run twice, so should just work as-is I think.
> -Daniel
>> +}
>> -- 
>> 2.7.4
>>

[-- Attachment #1.2: Type: text/html, Size: 12035 bytes --]

[-- Attachment #2: Type: text/plain, Size: 160 bytes --]

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 103+ messages in thread

* Re: [PATCH v9 07/39] drm/i915: MEI interface definition
  2018-12-19 15:21       ` Daniel Vetter
@ 2018-12-20 13:18         ` C, Ramalingam
  2018-12-20 14:47           ` Daniel Vetter
  0 siblings, 1 reply; 103+ messages in thread
From: C, Ramalingam @ 2018-12-20 13:18 UTC (permalink / raw)
  To: Daniel Vetter
  Cc: daniel.vetter, intel-gfx, dri-devel, seanpaul, tomas.winkler


[-- Attachment #1.1: Type: text/plain, Size: 729 bytes --]


On 12/19/2018 8:51 PM, Daniel Vetter wrote:
> Indeed, I overlooked that. Maybe highlight it a bit more with a separate
>
> 	if (!CONFIG_ENABLED(MEI_HDCP))
> 		return false;
>
> so it stick out more in the previous patch. Currently it's a bit burried.
>
> With that + the init ordering fixed:
>
> Reviewed-by: Daniel Vetter<daniel.vetter@ffwll.ch>

Sure. Thank you.

>
> There's no need to split the patch out anymore, since without the mei
> patches you can't enable that Kconfig option and hence no bisect issues.

Still Kconfig and makefile is added at 22nd patch but component support in mei_hdcp is added at 35th patch.
So even now this chunk needs to be kept after the component support addition.

-Ram

>
> Cheers, Daniel

[-- Attachment #1.2: Type: text/html, Size: 1529 bytes --]

[-- Attachment #2: Type: text/plain, Size: 160 bytes --]

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 103+ messages in thread

* Re: [PATCH v9 10/39] drm/i915: Implement HDCP2.2 receiver authentication
  2018-12-20  7:42           ` Jani Nikula
@ 2018-12-20 14:28             ` Winkler, Tomas
  2018-12-20 14:55               ` Daniel Vetter
  0 siblings, 1 reply; 103+ messages in thread
From: Winkler, Tomas @ 2018-12-20 14:28 UTC (permalink / raw)
  To: Jani Nikula, C, Ramalingam, Daniel Vetter
  Cc: daniel.vetter, intel-gfx, seanpaul, dri-devel



> On Wed, 19 Dec 2018, "Winkler, Tomas" <tomas.winkler@intel.com> wrote:
> >>
> >> On Wed, 19 Dec 2018, "C, Ramalingam" <ramalingam.c@intel.com> wrote:
> >> > On 12/19/2018 8:05 PM, Daniel Vetter wrote:
> >> >> On Thu, Dec 13, 2018 at 09:31:12AM +0530, Ramalingam C wrote:
> >> >>>   struct intel_hdcp {
> >> >>> @@ -414,6 +430,24 @@ struct intel_hdcp {
> >> >>>   	 */
> >> >>>   	u8 content_type;
> >> >>>   	struct hdcp_port_data port_data;
> >> >>> +
> >> >>> +	u8 is_paired;
> >> >>> +	u8 is_repeater;
> >> >> Make these two bool, will simplify the code a bunch.
> >> >
> >> > Seems there is a movement for not to use the bool in structures.
> >>
> >> No. Please use bools in structs when it makes sense. Avoid bools in
> >> structs when you need to care about memory footprint or alignment or
> >> packing or the like. This is not one of those cases.
> >>
> >> > Thats why I have changed these from bool to u8 from v8 onwards.
> >> > Checkpatch also complains on this
> >>
> >> Sorry to say, checkpatch is not the authority although we do send out
> >> automated checkpatch results.
> >
> > I believe it was Linus' call to not use  bool in structs at all
> > https://lkml.org/lkml/2017/11/21/384
> 
> I don't care. That's a valid judgement in the context referenced, but the
> conclusion "no bools in structs at all" isn't. In this case, I think bools are the
> better option, and anything else makes the code worse.

The solution was to use bit fields, 
 unsinged int is_paired:1;
unsinged int is_repeter:1
There is a strong point in consistency so there are no mistakes.

But frankly I don't really have strong feelings about it.

Thanks
Tomas

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 103+ messages in thread

* Re: [PATCH v9 07/39] drm/i915: MEI interface definition
  2018-12-20 13:18         ` C, Ramalingam
@ 2018-12-20 14:47           ` Daniel Vetter
  0 siblings, 0 replies; 103+ messages in thread
From: Daniel Vetter @ 2018-12-20 14:47 UTC (permalink / raw)
  To: C, Ramalingam
  Cc: daniel.vetter, intel-gfx, dri-devel, uma.shankar, seanpaul,
	tomas.winkler

On Thu, Dec 20, 2018 at 06:48:08PM +0530, C, Ramalingam wrote:
> 
> On 12/19/2018 8:51 PM, Daniel Vetter wrote:
> > Indeed, I overlooked that. Maybe highlight it a bit more with a separate
> > 
> > 	if (!CONFIG_ENABLED(MEI_HDCP))
> > 		return false;
> > 
> > so it stick out more in the previous patch. Currently it's a bit burried.
> > 
> > With that + the init ordering fixed:
> > 
> > Reviewed-by: Daniel Vetter<daniel.vetter@ffwll.ch>
> 
> Sure. Thank you.
> 
> > 
> > There's no need to split the patch out anymore, since without the mei
> > patches you can't enable that Kconfig option and hence no bisect issues.
> 
> Still Kconfig and makefile is added at 22nd patch but component support in mei_hdcp is added at 35th patch.
> So even now this chunk needs to be kept after the component support addition.

IS_ENABLED(CONFIG_FOO) will just always evaluate to false if the Kconfig
symbol isn't defined yet. Kconfig works by injection additional #define
contstants into the build. So current ordering is safe.
-Daniel
-- 
Daniel Vetter
Software Engineer, Intel Corporation
http://blog.ffwll.ch
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 103+ messages in thread

* Re: [PATCH v9 08/39] drm/i915: hdcp1.4 CP_IRQ handling and SW encryption tracking
  2018-12-20 11:29     ` C, Ramalingam
@ 2018-12-20 14:53       ` Daniel Vetter
  0 siblings, 0 replies; 103+ messages in thread
From: Daniel Vetter @ 2018-12-20 14:53 UTC (permalink / raw)
  To: C, Ramalingam
  Cc: daniel.vetter, intel-gfx, dri-devel, uma.shankar, seanpaul,
	tomas.winkler

On Thu, Dec 20, 2018 at 04:59:13PM +0530, C, Ramalingam wrote:
> 
> On 12/19/2018 9:18 PM, Daniel Vetter wrote:
> > On Thu, Dec 13, 2018 at 09:31:10AM +0530, Ramalingam C wrote:
> > > "hdcp_encrypted" flag is defined to denote the HDCP1.4 encryption status.
> > > This SW tracking is used to determine the need for real hdcp1.4 disable
> > > and hdcp_check_link upon CP_IRQ.
> > > 
> > > On CP_IRQ we filter the CP_IRQ related to the states like Link failure
> > > and reauthentication req etc and handle them in hdcp_check_link.
> > > CP_IRQ corresponding to the authentication msg availability are ignored.
> > > 
> > > WARN_ON is added for the abrupt stop of HDCP encryption of a port.
> > > 
> > > Signed-off-by: Ramalingam C <ramalingam.c@intel.com>
> > > ---
> > >   drivers/gpu/drm/i915/intel_dp.c   |  2 +-
> > >   drivers/gpu/drm/i915/intel_drv.h  |  5 ++-
> > >   drivers/gpu/drm/i915/intel_hdcp.c | 89 ++++++++++++++++++++++++++++++---------
> > >   3 files changed, 74 insertions(+), 22 deletions(-)
> > > 
> > > diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
> > > index aba884c64879..89315e15fb34 100644
> > > --- a/drivers/gpu/drm/i915/intel_dp.c
> > > +++ b/drivers/gpu/drm/i915/intel_dp.c
> > > @@ -4758,7 +4758,7 @@ static void intel_dp_check_service_irq(struct intel_dp *intel_dp)
> > >   		intel_dp_handle_test_request(intel_dp);
> > >   	if (val & DP_CP_IRQ)
> > > -		intel_hdcp_check_link(intel_dp->attached_connector);
> > > +		intel_hdcp_handle_cp_irq(intel_dp->attached_connector);
> > >   	if (val & DP_SINK_SPECIFIC_IRQ)
> > >   		DRM_DEBUG_DRIVER("Sink specific irq unhandled\n");
> > > diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
> > > index 191b6e0f086c..decd0346c6a7 100644
> > > --- a/drivers/gpu/drm/i915/intel_drv.h
> > > +++ b/drivers/gpu/drm/i915/intel_drv.h
> > > @@ -393,6 +393,9 @@ struct intel_hdcp {
> > >   	struct delayed_work check_work;
> > >   	struct work_struct prop_work;
> > > +	/* HDCP1.4 Encryption status */
> > > +	u8 hdcp_encrypted;
> > Another bool I guess? Or unsigned : 1;
> as per #intel-gfx discussion I will fallback to bool.
> > 
> > > +
> > >   	/* HDCP2.2 related definitions */
> > >   	/* Flag indicates whether this connector supports HDCP2.2 or not. */
> > >   	u8 hdcp2_supported;
> > > @@ -2058,10 +2061,10 @@ int intel_hdcp_init(struct intel_connector *connector,
> > >   		    bool hdcp2_supported);
> > >   int intel_hdcp_enable(struct intel_connector *connector);
> > >   int intel_hdcp_disable(struct intel_connector *connector);
> > > -int intel_hdcp_check_link(struct intel_connector *connector);
> > >   bool is_hdcp_supported(struct drm_i915_private *dev_priv, enum port port);
> > >   bool intel_hdcp_capable(struct intel_connector *connector);
> > >   bool is_hdcp2_supported(struct drm_i915_private *dev_priv);
> > > +void intel_hdcp_handle_cp_irq(struct intel_connector *connector);
> > >   /* intel_psr.c */
> > >   #define CAN_PSR(dev_priv) (HAS_PSR(dev_priv) && dev_priv->psr.sink_support)
> > > diff --git a/drivers/gpu/drm/i915/intel_hdcp.c b/drivers/gpu/drm/i915/intel_hdcp.c
> > > index 9405fce07b93..2b7814a6f12b 100644
> > > --- a/drivers/gpu/drm/i915/intel_hdcp.c
> > > +++ b/drivers/gpu/drm/i915/intel_hdcp.c
> > > @@ -75,6 +75,16 @@ bool intel_hdcp_capable(struct intel_connector *connector)
> > >   	return capable;
> > >   }
> > > +static inline bool intel_hdcp_in_use(struct intel_connector *connector)
> > > +{
> > > +	struct drm_i915_private *dev_priv = to_i915(connector->base.dev);
> > > +	enum port port = connector->encoder->port;
> > > +	u32 reg;
> > > +
> > > +	reg = I915_READ(PORT_HDCP_STATUS(port));
> > > +	return reg & HDCP_STATUS_ENC;
> > > +}
> > > +
> > >   static int intel_hdcp_poll_ksv_fifo(struct intel_digital_port *intel_dig_port,
> > >   				    const struct intel_hdcp_shim *shim)
> > >   {
> > > @@ -669,6 +679,7 @@ static int _intel_hdcp_disable(struct intel_connector *connector)
> > >   	DRM_DEBUG_KMS("[%s:%d] HDCP is being disabled...\n",
> > >   		      connector->base.name, connector->base.base.id);
> > > +	hdcp->hdcp_encrypted = 0;
> > >   	I915_WRITE(PORT_HDCP_CONF(port), 0);
> > >   	if (intel_wait_for_register(dev_priv, PORT_HDCP_STATUS(port), ~0, 0,
> > >   				    ENCRYPT_STATUS_CHANGE_TIMEOUT_MS)) {
> > > @@ -714,8 +725,10 @@ static int _intel_hdcp_enable(struct intel_connector *connector)
> > >   	/* Incase of authentication failures, HDCP spec expects reauth. */
> > >   	for (i = 0; i < tries; i++) {
> > >   		ret = intel_hdcp_auth(conn_to_dig_port(connector), hdcp->shim);
> > > -		if (!ret)
> > > +		if (!ret) {
> > > +			hdcp->hdcp_encrypted = 1;
> > >   			return 0;
> > > +		}
> > >   		DRM_DEBUG_KMS("HDCP Auth failure (%d)\n", ret);
> > > @@ -742,16 +755,17 @@ int intel_hdcp_check_link(struct intel_connector *connector)
> > >   	enum port port = intel_dig_port->base.port;
> > >   	int ret = 0;
> > > -	if (!hdcp->shim)
> > > -		return -ENOENT;
> > > -
> > >   	mutex_lock(&hdcp->mutex);
> > > -	if (hdcp->value == DRM_MODE_CONTENT_PROTECTION_UNDESIRED)
> > > +	/* Check_link valid only when HDCP1.4 is enabled */
> > > +	if (hdcp->value != DRM_MODE_CONTENT_PROTECTION_ENABLED ||
> > > +	    !hdcp->hdcp_encrypted) {
> > > +		ret = -EINVAL;
> > >   		goto out;
> > > +	}
> > > -	if (!(I915_READ(PORT_HDCP_STATUS(port)) & HDCP_STATUS_ENC)) {
> > > -		DRM_ERROR("%s:%d HDCP check failed: link is not encrypted,%x\n",
> > > +	if (WARN_ON(!intel_hdcp_in_use(connector))) {
> > > +		DRM_ERROR("%s:%d HDCP link stopped encryption,%x\n",
> > >   			  connector->base.name, connector->base.base.id,
> > >   			  I915_READ(PORT_HDCP_STATUS(port)));
> > >   		ret = -ENXIO;
> > > @@ -792,18 +806,6 @@ int intel_hdcp_check_link(struct intel_connector *connector)
> > >   	return ret;
> > >   }
> > > -static void intel_hdcp_check_work(struct work_struct *work)
> > > -{
> > > -	struct intel_hdcp *hdcp = container_of(to_delayed_work(work),
> > > -					       struct intel_hdcp,
> > > -					       check_work);
> > > -	struct intel_connector *connector = intel_hdcp_to_connector(hdcp);
> > > -
> > > -	if (!intel_hdcp_check_link(connector))
> > > -		schedule_delayed_work(&hdcp->check_work,
> > > -				      DRM_HDCP_CHECK_PERIOD_MS);
> > > -}
> > Why move the function?
> 
> This will be used as common work fn for both 1.4 and 2.2. hdcp2_check_link will be defined below.
> So moving this to the group of common functions. Basically to avoid the function declarations.

Yeah, but moving the function down is never required to avoid a forward
declaration. If you want to move it for better grouping that makes sense,
but as-is it was confusing.

> > > -
> > >   static void intel_hdcp_prop_work(struct work_struct *work)
> > >   {
> > >   	struct intel_hdcp *hdcp = container_of(work, struct intel_hdcp,
> > > @@ -1028,6 +1030,25 @@ int hdcp2_deauthenticate_port(struct intel_connector *connector)
> > >   	return hdcp2_close_mei_session(connector);
> > >   }
> > > +static inline void _intel_hdcp_check_work(struct intel_connector *connector)
> > > +{
> > > +	struct intel_hdcp *hdcp = &connector->hdcp;
> > > +
> > > +	if (!intel_hdcp_check_link(connector))
> > > +		schedule_delayed_work(&hdcp->check_work,
> > > +				      DRM_HDCP_CHECK_PERIOD_MS);
> > > +}
> > > +
> > > +static void intel_hdcp_check_work(struct work_struct *work)
> > > +{
> > > +	struct intel_hdcp *hdcp = container_of(to_delayed_work(work),
> > > +					       struct intel_hdcp,
> > > +					       check_work);
> > > +	struct intel_connector *connector = intel_hdcp_to_connector(hdcp);
> > > +
> > > +	_intel_hdcp_check_work(connector);
> > > +}
> > > +
> > >   static int i915_hdcp_component_match(struct device *dev, void *data)
> > >   {
> > >   	return !strcmp(dev->driver->name, "mei_hdcp");
> > > @@ -1156,7 +1177,8 @@ int intel_hdcp_disable(struct intel_connector *connector)
> > >   	if (hdcp->value != DRM_MODE_CONTENT_PROTECTION_UNDESIRED) {
> > >   		hdcp->value = DRM_MODE_CONTENT_PROTECTION_UNDESIRED;
> > > -		ret = _intel_hdcp_disable(connector);
> > > +		if (hdcp->hdcp_encrypted)
> > > +			ret = _intel_hdcp_disable(connector);
> > >   	}
> > >   	mutex_unlock(&hdcp->mutex);
> > > @@ -1196,3 +1218,30 @@ void intel_hdcp_atomic_check(struct drm_connector *connector,
> > >   						   new_state->crtc);
> > >   	crtc_state->mode_changed = true;
> > >   }
> > > +
> > > +/* Handles the CP_IRQ raised from the DP HDCP sink */
> > > +void intel_hdcp_handle_cp_irq(struct intel_connector *connector)
> > > +{
> > > +	struct intel_hdcp *hdcp = &connector->hdcp;
> > > +
> > > +	if (!hdcp->shim)
> > > +		return;
> > > +
> > > +	/*
> > > +	 * As of now we want to handle CP_IRQ triggered while encryption is
> > > +	 * enabled. This includes the notification for Topology change,
> > > +	 * Link failure, reauth request etc.
> > > +	 * Auth msg availability notifications are ignored with mutex_trylock
> > > +	 * as authentication holds the lock. Lock might be taken for link check
> > > +	 * or hdcp_disable too. In either of state we need not handle the
> > > +	 * CP_IRQ, for known reasons.
> > > +	 */
> > > +	if (!mutex_trylock(&hdcp->mutex))
> > This is not a good way to fix recursions, because the lock might be held
> > by someone else for other reasons, and then you just drop events on the
> > floor. Worse, usually it works, except when it stops working.
> 
> This is attempt to drop the CP_IRQ received during mutex is locked. Because
> of the below reasoning:
> 
> This mutex is taken by authentication enable/disable and check_link worker
> 
> when enable is in process this CP_IRQ will be notifying the msg availability to read. at present we dont use the CP_IRQ for msg read.
> when disable is in process it doesn't matter why this CP_IRQ is triggered, we just want to ignore.
> 
> When check_link is in progress, that means hdcp is enabled. So this CP_IRQ is for topology change/reauth request etc,
> which are handled by check_link. so once again we dont care for this CP_IRQs too.
> 
> So basically if the mutex is already taken we can ignore/drop the CP_IRQ. So mutex_trylock helps us to do this.
> May be I should add all of these in the comment!?
> 
> While rethinking on that we can reschedule the check_link work on every
> CP_IRQ. As this is harmless i will do that. Makes things simple.

Yeah that was my point: If the work is already running then re-scheduling
it won't cause additional work. Whereas your mutex_trylock trick above
sets of all kinds of alarm bell about races and causing issues when we
_do_ want to handle the CP_IRQ.

If we do need this optimization, then we need to rework the CP_IRQ
handling to do check the interrupt sources before scheduling the work,
which is going to be complicated because locking. And then filter out the
right interrupt sources, and not use something which is only correct in
99% of all cases like mutex_trylock.

We've had other such code in drm/i915 abusing mutex_trylock, works great
in a quick test locally, fails in production, so I don't like that trick
:-)

> > Since you already have a separate worker just schedule that one, and leave
> > it up to the worker to filter out events we don't care about.
> > > +		return;
> > > +
> > > +	if (!hdcp->hdcp_encrypted)
> > > +		return;
> > This check would need to be moved intel_hdcp_check_link().
> 
> Function has the check already. I can avoid the check here and directly land
> into check_link work fn.

Yeah that's what I meant.
-Daniel

> 
> -Ram
> 
> > > +
> > > +	mutex_unlock(&hdcp->mutex);
> > > +	_intel_hdcp_check_work(connector);
> > So instead of the direct call we need a schedule_work() here (without
> > delay ofc). Note that if the work is already scheduled it won't be
> > scheduled to run twice, so should just work as-is I think.
> > -Daniel
> > > +}
> > > -- 
> > > 2.7.4
> > > 

-- 
Daniel Vetter
Software Engineer, Intel Corporation
http://blog.ffwll.ch
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 103+ messages in thread

* Re: [PATCH v9 10/39] drm/i915: Implement HDCP2.2 receiver authentication
  2018-12-20 14:28             ` Winkler, Tomas
@ 2018-12-20 14:55               ` Daniel Vetter
  2018-12-21 18:06                 ` Ville Syrjälä
  0 siblings, 1 reply; 103+ messages in thread
From: Daniel Vetter @ 2018-12-20 14:55 UTC (permalink / raw)
  To: Winkler, Tomas; +Cc: intel-gfx, dri-devel, seanpaul, daniel.vetter

On Thu, Dec 20, 2018 at 02:28:55PM +0000, Winkler, Tomas wrote:
> 
> 
> > On Wed, 19 Dec 2018, "Winkler, Tomas" <tomas.winkler@intel.com> wrote:
> > >>
> > >> On Wed, 19 Dec 2018, "C, Ramalingam" <ramalingam.c@intel.com> wrote:
> > >> > On 12/19/2018 8:05 PM, Daniel Vetter wrote:
> > >> >> On Thu, Dec 13, 2018 at 09:31:12AM +0530, Ramalingam C wrote:
> > >> >>>   struct intel_hdcp {
> > >> >>> @@ -414,6 +430,24 @@ struct intel_hdcp {
> > >> >>>   	 */
> > >> >>>   	u8 content_type;
> > >> >>>   	struct hdcp_port_data port_data;
> > >> >>> +
> > >> >>> +	u8 is_paired;
> > >> >>> +	u8 is_repeater;
> > >> >> Make these two bool, will simplify the code a bunch.
> > >> >
> > >> > Seems there is a movement for not to use the bool in structures.
> > >>
> > >> No. Please use bools in structs when it makes sense. Avoid bools in
> > >> structs when you need to care about memory footprint or alignment or
> > >> packing or the like. This is not one of those cases.
> > >>
> > >> > Thats why I have changed these from bool to u8 from v8 onwards.
> > >> > Checkpatch also complains on this
> > >>
> > >> Sorry to say, checkpatch is not the authority although we do send out
> > >> automated checkpatch results.
> > >
> > > I believe it was Linus' call to not use  bool in structs at all
> > > https://lkml.org/lkml/2017/11/21/384
> > 
> > I don't care. That's a valid judgement in the context referenced, but the
> > conclusion "no bools in structs at all" isn't. In this case, I think bools are the
> > better option, and anything else makes the code worse.
> 
> The solution was to use bit fields, 
>  unsinged int is_paired:1;
> unsinged int is_repeter:1

This doesn't work with READ_ONCE/WRITE_ONCE, and it generates terrible
assembly (at least gcc is well known for struggling with these, compared
to open-coded bitops). So depending upon what you want to do, and where
youre space/performance tradeoff lies, doing this unconditionally is just
wrong.

It was the right thing for the patch Linus commented on though.
-Daniel

> There is a strong point in consistency so there are no mistakes.
> 
> But frankly I don't really have strong feelings about it.
> 
> Thanks
> Tomas
> 

-- 
Daniel Vetter
Software Engineer, Intel Corporation
http://blog.ffwll.ch
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 103+ messages in thread

* Re: [PATCH v9 35/39] misc/mei/hdcp: Component framework for I915 Interface
  2018-12-19  6:45                   ` C, Ramalingam
@ 2018-12-20 15:59                     ` C, Ramalingam
  2018-12-20 16:06                       ` Winkler, Tomas
  0 siblings, 1 reply; 103+ messages in thread
From: C, Ramalingam @ 2018-12-20 15:59 UTC (permalink / raw)
  To: Daniel Vetter, Winkler, Tomas
  Cc: Rafael J. Wysocki, Greg KH, intel-gfx, dri-devel, Sean Paul


[-- Attachment #1.1: Type: text/plain, Size: 6432 bytes --]


On 12/19/2018 12:15 PM, C, Ramalingam wrote:
> Tomas and Daniel,
>
>  From the discussion on this thread, I infer following understanding:
>
>   * At present(v9) I915 wants to be hard binded to mei_hdcp
>     device-driver binding status through components
>       o This means I915 driver load will get complete only when the
>         mei_hdcp's device and driver are bound.
>       o if mei_hdcp device reset I915 will unregister itself from
>         userspace, and wait for the mei_hdcp device-deriver rebinding.
>           + Could be due to FW error or any unexpected failures those
>             are rare occurances.
>       o when mei_hdcp module is removed i915 will unregister itself.
>       o Becasue of this, Ideally I915 dont expect the device reset
>         from mei for suspend and resume.
>   * At present Mei bus is designed as below:
>       o Device will disappear on FW failures, FW upgrade, suspend of
>         the system etc.
>       o And when the errors are handled or on system resume mei device
>         will reappear, hence binding with corresponding driver.
>   * Mei doesn't plan to avoid the device reset(disappearance and
>     reappearance) for suspend and resume in near future.
>
> Based on above understanding, I propose the below approach. Please correct or approve it.
>
>   * At present(v9) component_add from mei_hdcp indicates the
>     mei_hdcp's device-driver binded state.
>   * Instead lets use component to indicate the mei_hdcp's module
>     availability,
>       o by adding the component at module_init and removing it from
>         module_exit.
>   * This way I915 will not be impacted due to the mei device reset at
>     suspend.
>   * In such scenario I915 will have no idea about the device-driver
>     bind status of mei_hdcp.
>       o So incase of device is not available, mei_hdcp is responsible
>         to prune such calls with -EIO error.
>   * This approach avoid any future impact to I915, incase mei intended
>     to support suspend and resume.
>
> I am aware this is not the ideal solution we want. But I feel this is the best at present we could do for this I915-mei interface.
> Best regards,
> Ram

something like (un compiled code)

diff --git a/drivers/misc/mei/hdcp/mei_hdcp.c b/drivers/misc/mei/hdcp/mei_hdcp.c
index b22a71e8c5d7..b5b57a883e3b 100644
--- a/drivers/misc/mei/hdcp/mei_hdcp.c
+++ b/drivers/misc/mei/hdcp/mei_hdcp.c
@@ -23,11 +23,15 @@
  #include <linux/slab.h>
  #include <linux/uuid.h>
  #include <linux/mei_cl_bus.h>
+#include <linux/component.h>
  #include <drm/drm_connector.h>
  #include <drm/i915_component.h>

  #include "mei_hdcp.h"

+struct i915_component_master *i915_master_comp;
+static bool mei_hdcp_component_registered;
+
  /**
   * mei_initiate_hdcp2_session() - Initiate a Wired HDCP2.2 Tx Session in ME FW
   * @dev: device corresponding to the mei_cl_device
@@ -691,8 +695,7 @@ mei_close_hdcp_session(struct device *dev, struct hdcp_port_data *data)
         return 0;
  }

-static __attribute__((unused))
-struct i915_hdcp_component_ops mei_hdcp_ops = {
+static struct i915_hdcp_component_ops mei_hdcp_ops = {
         .owner = THIS_MODULE,
         .initiate_hdcp2_session = mei_initiate_hdcp2_session,
         .verify_receiver_cert_prepare_km = mei_verify_receiver_cert_prepare_km,
@@ -707,20 +710,84 @@ struct i915_hdcp_component_ops mei_hdcp_ops = {
         .close_hdcp_session = mei_close_hdcp_session,
  };

+static int mei_hdcp_component_bind(struct device *mei_kdev,
+                                  struct device *i915_kdev, void *data)
+{
+       struct i915_component_master *master_comp = data;
+
+       dev_info(mei_kdev, "MEI HDCP comp bind\n");
+       WARN_ON(master_comp->hdcp_ops);
+       master_comp->hdcp_ops = &mei_hdcp_ops;
+       master_comp->mei_dev = mei_kdev;
+
+       i915_master_comp = master_comp;
+
+       return 0;
+}
+
+static void mei_hdcp_component_unbind(struct device *mei_kdev,
+                                     struct device *i915_kdev, void *data)
+{
+       struct i915_component_master *master_comp = data;
+
+       dev_info(mei_kdev, "MEI HDCP comp unbind\n");
+       master_comp->hdcp_ops = NULL;
+       master_comp->mei_dev = NULL;
+       i915_master_comp = NULL;
+}
+
+static const struct component_ops mei_hdcp_component_bind_ops = {
+       .bind   = mei_hdcp_component_bind,
+       .unbind = mei_hdcp_component_unbind,
+};
+
+static void mei_hdcp_component_init(struct device *dev)
+{
+       int ret;
+
+       if (mei_hdcp_component_registered && i915_master_comp) {
+               i915_master_comp->mei_dev = dev;
+               return;
+       }
+
+       dev_info(dev, "MEI HDCP comp init\n");
+       ret = component_add(dev, &mei_hdcp_component_bind_ops);
+       if (ret < 0) {
+               dev_err(dev, "Failed to add MEI HDCP comp (%d)\n", ret);
+               return;
+       }
+
+       mei_hdcp_component_registered = true;
+}
+
+static void mei_hdcp_component_cleanup(struct device *dev)
+{
+       if (!mei_hdcp_component_registered)
+               return;
+
+       dev_info(dev, "MEI HDCP comp cleanup\n");
+       component_del(dev, &mei_hdcp_component_bind_ops);
+       mei_hdcp_component_registered = false;
+}
+
  static int mei_hdcp_probe(struct mei_cl_device *cldev,
                           const struct mei_cl_device_id *id)
  {
         int ret;

         ret = mei_cldev_enable(cldev);
-       if (ret < 0)
+       if (ret < 0) {
                 dev_err(&cldev->dev, "mei_cldev_enable Failed. %d\n", ret);
+               return ret;
+       }
+       mei_hdcp_component_init(&cldev->dev);

-       return ret;
+       return 0;
  }

  static int mei_hdcp_remove(struct mei_cl_device *cldev)
  {
+       i915_master_comp->mei_dev = NULL;
         return mei_cldev_disable(cldev);
  }

@@ -741,7 +808,23 @@ static struct mei_cl_driver mei_hdcp_driver = {
         .remove         = mei_hdcp_remove,
  };

-module_mei_cl_driver(mei_hdcp_driver);
+static int __init mei_hdcp_init(void)
+{
+       int ret;
+
+       ret = mei_cldev_driver_register(mei_hdcp_driver);
+       if (ret)
+               return ret;
+}
+
+static void __exit mei_hdcp_exit(void)
+{
+       mei_hdcp_component_cleanup(&cldev->dev);
+       mei_cldev_driver_unregister(mei_hdcp_driver);
+}
+
+module_init(mei_hdcp_init);
+module_exit(mei_hdcp_exit);

  MODULE_AUTHOR("Intel Corporation");
  MODULE_LICENSE("Dual BSD/GPL");
--
2.7.4


-Ram


[-- Attachment #1.2: Type: text/html, Size: 7525 bytes --]

[-- Attachment #2: Type: text/plain, Size: 160 bytes --]

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply related	[flat|nested] 103+ messages in thread

* RE: [PATCH v9 35/39] misc/mei/hdcp: Component framework for I915 Interface
  2018-12-20 15:59                     ` C, Ramalingam
@ 2018-12-20 16:06                       ` Winkler, Tomas
  2018-12-20 16:47                         ` C, Ramalingam
  0 siblings, 1 reply; 103+ messages in thread
From: Winkler, Tomas @ 2018-12-20 16:06 UTC (permalink / raw)
  To: C, Ramalingam, Daniel Vetter
  Cc: Rafael J. Wysocki, Greg KH, intel-gfx, dri-devel, Shankar, Uma,
	Sean Paul


[-- Attachment #1.1: Type: text/plain, Size: 7403 bytes --]



From: C, Ramalingam
Sent: Thursday, December 20, 2018 18:00
To: Daniel Vetter <daniel@ffwll.ch>; Winkler, Tomas <tomas.winkler@intel.com>
Cc: Greg KH <gregkh@linuxfoundation.org>; Rafael J. Wysocki <rafael@kernel.org>; intel-gfx <intel-gfx@lists.freedesktop.org>; dri-devel <dri-devel@lists.freedesktop.org>; Sean Paul <seanpaul@chromium.org>; Shankar, Uma <uma.shankar@intel.com>; Syrjala, Ville <ville.syrjala@linux.intel.com>; Chris Wilson <chris@chris-wilson.co.uk>
Subject: Re: [PATCH v9 35/39] misc/mei/hdcp: Component framework for I915 Interface



On 12/19/2018 12:15 PM, C, Ramalingam wrote:

Tomas and Daniel,



From the discussion on this thread, I infer following understanding:

  *   At present(v9) I915 wants to be hard binded to mei_hdcp device-driver binding status through components

     *   This means I915 driver load will get complete only when the mei_hdcp's device and driver are bound.
     *   if mei_hdcp device reset I915 will unregister itself from userspace, and wait for the mei_hdcp device-deriver rebinding.

        *   Could be due to FW error or any unexpected failures those are rare occurances.

     *   when mei_hdcp module is removed i915 will unregister itself.
     *   Becasue of this, Ideally I915 dont expect the device reset from mei for suspend and resume.

  *   At present Mei bus is designed as below:

     *   Device will disappear on FW failures, FW upgrade, suspend of the system etc.
     *   And when the errors are handled or on system resume mei device will reappear, hence binding with corresponding driver.

  *   Mei doesn't plan to avoid the device reset(disappearance and reappearance) for suspend and resume in near future.

Based on above understanding, I propose the below approach. Please correct or approve it.



  *   At present(v9) component_add from mei_hdcp indicates the mei_hdcp's device-driver binded state.
  *   Instead lets use component to indicate the mei_hdcp's module availability,

     *   by adding the component at module_init and removing it from module_exit.

  *   This way I915 will not be impacted due to the mei device reset at suspend.
  *   In such scenario I915 will have no idea about the device-driver bind status of mei_hdcp.

     *   So incase of device is not available, mei_hdcp is responsible to prune such calls with -EIO error.

  *   This approach avoid any future impact to I915, incase mei intended to support suspend and resume.

I am aware this is not the ideal solution we want. But I feel this is the best at present we could do for this I915-mei interface.

Best regards,

Ram

something like (un compiled code)

diff --git a/drivers/misc/mei/hdcp/mei_hdcp.c b/drivers/misc/mei/hdcp/mei_hdcp.c

index b22a71e8c5d7..b5b57a883e3b 100644

--- a/drivers/misc/mei/hdcp/mei_hdcp.c

+++ b/drivers/misc/mei/hdcp/mei_hdcp.c

@@ -23,11 +23,15 @@

 #include <linux/slab.h>

 #include <linux/uuid.h>

 #include <linux/mei_cl_bus.h>

+#include <linux/component.h>

 #include <drm/drm_connector.h>

 #include <drm/i915_component.h>



 #include "mei_hdcp.h"



+struct i915_component_master *i915_master_comp;

+static bool mei_hdcp_component_registered;

+

 /**

  * mei_initiate_hdcp2_session() - Initiate a Wired HDCP2.2 Tx Session in ME FW

  * @dev: device corresponding to the mei_cl_device

@@ -691,8 +695,7 @@ mei_close_hdcp_session(struct device *dev, struct hdcp_port_data *data)

        return 0;

 }



-static __attribute__((unused))

-struct i915_hdcp_component_ops mei_hdcp_ops = {

+static struct i915_hdcp_component_ops mei_hdcp_ops = {

        .owner = THIS_MODULE,

        .initiate_hdcp2_session = mei_initiate_hdcp2_session,

        .verify_receiver_cert_prepare_km = mei_verify_receiver_cert_prepare_km,

@@ -707,20 +710,84 @@ struct i915_hdcp_component_ops mei_hdcp_ops = {

        .close_hdcp_session = mei_close_hdcp_session,

 };



+static int mei_hdcp_component_bind(struct device *mei_kdev,

+                                  struct device *i915_kdev, void *data)

+{

+       struct i915_component_master *master_comp = data;

+

+       dev_info(mei_kdev, "MEI HDCP comp bind\n");

+       WARN_ON(master_comp->hdcp_ops);

+       master_comp->hdcp_ops = &mei_hdcp_ops;

+       master_comp->mei_dev = mei_kdev;

+

+       i915_master_comp = master_comp;

+

+       return 0;

+}

+

+static void mei_hdcp_component_unbind(struct device *mei_kdev,

+                                     struct device *i915_kdev, void *data)

+{

+       struct i915_component_master *master_comp = data;

+

+       dev_info(mei_kdev, "MEI HDCP comp unbind\n");

+       master_comp->hdcp_ops = NULL;

+       master_comp->mei_dev = NULL;

+       i915_master_comp = NULL;

+}

+

+static const struct component_ops mei_hdcp_component_bind_ops = {

+       .bind   = mei_hdcp_component_bind,

+       .unbind = mei_hdcp_component_unbind,

+};

+

+static void mei_hdcp_component_init(struct device *dev)

+{

+       int ret;

+

+       if (mei_hdcp_component_registered && i915_master_comp) {

+               i915_master_comp->mei_dev = dev;

+               return;

+       }

+

+       dev_info(dev, "MEI HDCP comp init\n");

+       ret = component_add(dev, &mei_hdcp_component_bind_ops);

+       if (ret < 0) {

+               dev_err(dev, "Failed to add MEI HDCP comp (%d)\n", ret);

+               return;

+       }

+

+       mei_hdcp_component_registered = true;

+}

+

+static void mei_hdcp_component_cleanup(struct device *dev)

+{

+       if (!mei_hdcp_component_registered)

+               return;

+

+       dev_info(dev, "MEI HDCP comp cleanup\n");

+       component_del(dev, &mei_hdcp_component_bind_ops);

+       mei_hdcp_component_registered = false;

+}

+

 static int mei_hdcp_probe(struct mei_cl_device *cldev,

                          const struct mei_cl_device_id *id)

 {

        int ret;



        ret = mei_cldev_enable(cldev);

-       if (ret < 0)

+       if (ret < 0) {

                dev_err(&cldev->dev, "mei_cldev_enable Failed. %d\n", ret);

+               return ret;

+       }

+       mei_hdcp_component_init(&cldev->dev);



-       return ret;

+       return 0;

 }



 static int mei_hdcp_remove(struct mei_cl_device *cldev)

 {

+       i915_master_comp->mei_dev = NULL;

        return mei_cldev_disable(cldev);

 }



@@ -741,7 +808,23 @@ static struct mei_cl_driver mei_hdcp_driver = {

        .remove         = mei_hdcp_remove,

 };



-module_mei_cl_driver(mei_hdcp_driver);

+static int __init mei_hdcp_init(void)

+{

+       int ret;

+

+       ret = mei_cldev_driver_register(mei_hdcp_driver);

+       if (ret)

+               return ret;

+}

+

+static void __exit mei_hdcp_exit(void)

+{

+       mei_hdcp_component_cleanup(&cldev->dev);

Don’t think you can do that,  no guarantees this will be valid pointer



+       mei_cldev_driver_unregister(mei_hdcp_driver);

+}

+

+module_init(mei_hdcp_init);

+module_exit(mei_hdcp_exit);



 MODULE_AUTHOR("Intel Corporation");

 MODULE_LICENSE("Dual BSD/GPL");

--

2.7.4





-Ram



[-- Attachment #1.2: Type: text/html, Size: 24082 bytes --]

[-- Attachment #2: Type: text/plain, Size: 160 bytes --]

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 103+ messages in thread

* Re: [PATCH v9 35/39] misc/mei/hdcp: Component framework for I915 Interface
  2018-12-20 16:06                       ` Winkler, Tomas
@ 2018-12-20 16:47                         ` C, Ramalingam
  0 siblings, 0 replies; 103+ messages in thread
From: C, Ramalingam @ 2018-12-20 16:47 UTC (permalink / raw)
  To: Winkler, Tomas, Daniel Vetter
  Cc: Rafael J. Wysocki, Greg KH, intel-gfx, dri-devel, Shankar, Uma,
	Sean Paul


[-- Attachment #1.1: Type: text/plain, Size: 658 bytes --]


On 12/20/2018 9:36 PM, Winkler, Tomas wrote:
> +static void __exit mei_hdcp_exit(void)
> +{
> +       mei_hdcp_component_cleanup(&cldev->dev);
> Don’t think you can do that,  no guarantees this will be valid pointer

As we discussed offline, we have the below line at cleanup.
So valid pointer is made sure. I will protect init and cleanup with mutex too.

+static void mei_hdcp_component_cleanup(struct device *dev)
+{
+       if (!mei_hdcp_component_registered)
+               return;

-Ram

> +       mei_cldev_driver_unregister(mei_hdcp_driver);
> +}
> +
> +module_init(mei_hdcp_init);
> +module_exit(mei_hdcp_exit);

[-- Attachment #1.2: Type: text/html, Size: 1724 bytes --]

[-- Attachment #2: Type: text/plain, Size: 160 bytes --]

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 103+ messages in thread

* ✗ Fi.CI.BAT: failure for drm/i915: Implement HDCP2.2 (rev12)
  2018-12-13  4:01 [PATCH v9 00/39] drm/i915: Implement HDCP2.2 Ramalingam C
                   ` (41 preceding siblings ...)
  2018-12-13  4:44 ` ✗ Fi.CI.BAT: failure " Patchwork
@ 2018-12-20 16:58 ` Patchwork
  42 siblings, 0 replies; 103+ messages in thread
From: Patchwork @ 2018-12-20 16:58 UTC (permalink / raw)
  To: C, Ramalingam; +Cc: intel-gfx

== Series Details ==

Series: drm/i915: Implement HDCP2.2 (rev12)
URL   : https://patchwork.freedesktop.org/series/38254/
State : failure

== Summary ==

Applying: drm/i915: Gathering the HDCP1.4 routines together
Applying: drm: header for i915 - MEI_HDCP interface
Applying: drivers/base: use a worker for sysfs unbind
Applying: component: alloc component_match without any comp to match
Applying: drm/i915: component master at i915 driver load
Using index info to reconstruct a base tree...
M	drivers/gpu/drm/i915/i915_drv.c
M	drivers/gpu/drm/i915/i915_drv.h
Falling back to patching base and 3-way merge...
Auto-merging drivers/gpu/drm/i915/i915_drv.h
Auto-merging drivers/gpu/drm/i915/i915_drv.c
Applying: drm/i915: Initialize HDCP2.2
Applying: drm/i915: MEI interface definition
Applying: drm/i915: hdcp1.4 CP_IRQ handling and SW encryption tracking
Applying: drm/i915: Enable and Disable of HDCP2.2
Applying: drm/i915: Implement HDCP2.2 receiver authentication
Applying: drm: helper functions for hdcp2 seq_num to from u32
Applying: drm/i915: Implement HDCP2.2 repeater authentication
Applying: drm: HDCP2.2 link check related constants
Applying: drm/i915: Implement HDCP2.2 link integrity check
Applying: drm/i915: Handle HDCP2.2 downstream topology change
Applying: drm/i915: Implement the HDCP2.2 support for DP
Applying: drm/i915: Implement the HDCP2.2 support for HDMI
Applying: drm/i915: Add HDCP2.2 support for DP connectors
Applying: drm/i915: Add HDCP2.2 support for HDMI connectors
Applying: mei: bus: whitelist hdcp client
Applying: mei: bus: export to_mei_cl_device for mei client device drivers
Applying: misc/mei/hdcp: Client driver for HDCP application
Applying: misc/mei/hdcp: Define ME FW interface for HDCP2.2
Applying: misc/mei/hdcp: Initiate Wired HDCP2.2 Tx Session
Applying: misc/mei/hdcp: Verify Receiver Cert and prepare km
Applying: misc/mei/hdcp: Verify H_prime
Applying: misc/mei/hdcp: Store the HDCP Pairing info
Applying: misc/mei/hdcp: Initiate Locality check
Applying: misc/mei/hdcp: Verify L_prime
Applying: misc/mei/hdcp: Prepare Session Key
Applying: misc/mei/hdcp: Repeater topology verification and ack
Applying: misc/mei/hdcp: Verify M_prime
Applying: misc/mei/hdcp: Enabling the HDCP authentication
Applying: misc/mei/hdcp: Closing wired HDCP2.2 Tx Session
Applying: misc/mei/hdcp: Component framework for I915 Interface
error: patch failed: drivers/misc/mei/hdcp/mei_hdcp.c:23
error: drivers/misc/mei/hdcp/mei_hdcp.c: patch does not apply
error: Did you hand edit your patch?
It does not apply to blobs recorded in its index.
hint: Use 'git am --show-current-patch' to see the failed patch
Using index info to reconstruct a base tree...
Patch failed at 0035 misc/mei/hdcp: Component framework for I915 Interface
When you have resolved this problem, run "git am --continue".
If you prefer to skip this patch, run "git am --skip" instead.
To restore the original branch and stop patching, run "git am --abort".

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 103+ messages in thread

* Re: [PATCH v9 10/39] drm/i915: Implement HDCP2.2 receiver authentication
  2018-12-20 14:55               ` Daniel Vetter
@ 2018-12-21 18:06                 ` Ville Syrjälä
  0 siblings, 0 replies; 103+ messages in thread
From: Ville Syrjälä @ 2018-12-21 18:06 UTC (permalink / raw)
  To: Daniel Vetter
  Cc: daniel.vetter, Winkler, Tomas, seanpaul, intel-gfx, dri-devel

On Thu, Dec 20, 2018 at 03:55:27PM +0100, Daniel Vetter wrote:
> On Thu, Dec 20, 2018 at 02:28:55PM +0000, Winkler, Tomas wrote:
> > 
> > 
> > > On Wed, 19 Dec 2018, "Winkler, Tomas" <tomas.winkler@intel.com> wrote:
> > > >>
> > > >> On Wed, 19 Dec 2018, "C, Ramalingam" <ramalingam.c@intel.com> wrote:
> > > >> > On 12/19/2018 8:05 PM, Daniel Vetter wrote:
> > > >> >> On Thu, Dec 13, 2018 at 09:31:12AM +0530, Ramalingam C wrote:
> > > >> >>>   struct intel_hdcp {
> > > >> >>> @@ -414,6 +430,24 @@ struct intel_hdcp {
> > > >> >>>   	 */
> > > >> >>>   	u8 content_type;
> > > >> >>>   	struct hdcp_port_data port_data;
> > > >> >>> +
> > > >> >>> +	u8 is_paired;
> > > >> >>> +	u8 is_repeater;
> > > >> >> Make these two bool, will simplify the code a bunch.
> > > >> >
> > > >> > Seems there is a movement for not to use the bool in structures.
> > > >>
> > > >> No. Please use bools in structs when it makes sense. Avoid bools in
> > > >> structs when you need to care about memory footprint or alignment or
> > > >> packing or the like. This is not one of those cases.
> > > >>
> > > >> > Thats why I have changed these from bool to u8 from v8 onwards.
> > > >> > Checkpatch also complains on this
> > > >>
> > > >> Sorry to say, checkpatch is not the authority although we do send out
> > > >> automated checkpatch results.
> > > >
> > > > I believe it was Linus' call to not use  bool in structs at all
> > > > https://lkml.org/lkml/2017/11/21/384
> > > 
> > > I don't care. That's a valid judgement in the context referenced, but the
> > > conclusion "no bools in structs at all" isn't. In this case, I think bools are the
> > > better option, and anything else makes the code worse.
> > 
> > The solution was to use bit fields, 
> >  unsinged int is_paired:1;
> > unsinged int is_repeter:1
> 
> This doesn't work with READ_ONCE/WRITE_ONCE, and it generates terrible
> assembly (at least gcc is well known for struggling with these, compared
> to open-coded bitops). So depending upon what you want to do, and where
> youre space/performance tradeoff lies, doing this unconditionally is just
> wrong.

Another annoying downside with non-bool bitfields:

unsigned int foo:1;
foo = 2;
-> foo == 0

So you'll need to remmber to convert everything to
0/1 before the assignment.

-- 
Ville Syrjälä
Intel
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 103+ messages in thread

end of thread, other threads:[~2018-12-21 18:06 UTC | newest]

Thread overview: 103+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-12-13  4:01 [PATCH v9 00/39] drm/i915: Implement HDCP2.2 Ramalingam C
2018-12-13  4:01 ` [PATCH v9 01/39] drm/i915: Gathering the HDCP1.4 routines together Ramalingam C
2018-12-13  8:17   ` Winkler, Tomas
2018-12-13 11:21     ` C, Ramalingam
2018-12-19 13:35   ` Daniel Vetter
2018-12-13  4:01 ` [PATCH v9 02/39] drm: header for i915 - MEI_HDCP interface Ramalingam C
2018-12-17 11:28   ` Winkler, Tomas
2018-12-17 13:27     ` Daniel Vetter
2018-12-17 13:42       ` Winkler, Tomas
2018-12-17 13:59         ` Daniel Vetter
2018-12-19 13:37   ` Daniel Vetter
2018-12-13  4:01 ` [PATCH v9 03/39] drivers/base: use a worker for sysfs unbind Ramalingam C
2018-12-19 13:38   ` Daniel Vetter
2018-12-13  4:01 ` [PATCH v9 04/39] component: alloc component_match without any comp to match Ramalingam C
2018-12-19 13:42   ` Daniel Vetter
2018-12-19 15:04     ` Greg Kroah-Hartman
2018-12-19 15:04       ` Greg Kroah-Hartman
2018-12-13  4:01 ` [PATCH v9 05/39] drm/i915: component master at i915 driver load Ramalingam C
2018-12-19 13:45   ` Daniel Vetter
2018-12-13  4:01 ` [PATCH v9 06/39] drm/i915: Initialize HDCP2.2 Ramalingam C
2018-12-19 13:45   ` Daniel Vetter
2018-12-13  4:01 ` [PATCH v9 07/39] drm/i915: MEI interface definition Ramalingam C
2018-12-19 14:00   ` Daniel Vetter
2018-12-19 15:15     ` C, Ramalingam
2018-12-19 15:21       ` Daniel Vetter
2018-12-20 13:18         ` C, Ramalingam
2018-12-20 14:47           ` Daniel Vetter
2018-12-13  4:01 ` [PATCH v9 08/39] drm/i915: hdcp1.4 CP_IRQ handling and SW encryption tracking Ramalingam C
2018-12-19 15:48   ` Daniel Vetter
2018-12-20 11:29     ` C, Ramalingam
2018-12-20 14:53       ` Daniel Vetter
2018-12-13  4:01 ` [PATCH v9 09/39] drm/i915: Enable and Disable of HDCP2.2 Ramalingam C
2018-12-19 15:54   ` Daniel Vetter
2018-12-13  4:01 ` [PATCH v9 10/39] drm/i915: Implement HDCP2.2 receiver authentication Ramalingam C
2018-12-19 14:35   ` Daniel Vetter
2018-12-19 15:05     ` C, Ramalingam
2018-12-19 15:35       ` Daniel Vetter
2018-12-19 15:48         ` C, Ramalingam
2018-12-19 18:40       ` Jani Nikula
2018-12-19 21:36         ` Winkler, Tomas
2018-12-20  7:42           ` Jani Nikula
2018-12-20 14:28             ` Winkler, Tomas
2018-12-20 14:55               ` Daniel Vetter
2018-12-21 18:06                 ` Ville Syrjälä
2018-12-13  4:01 ` [PATCH v9 11/39] drm: helper functions for hdcp2 seq_num to from u32 Ramalingam C
2018-12-19 14:38   ` Daniel Vetter
2018-12-13  4:01 ` [PATCH v9 12/39] drm/i915: Implement HDCP2.2 repeater authentication Ramalingam C
2018-12-13  8:22   ` Winkler, Tomas
2018-12-13 11:18     ` C, Ramalingam
2018-12-19 14:48   ` Daniel Vetter
2018-12-19 15:35     ` C, Ramalingam
2018-12-13  4:01 ` [PATCH v9 13/39] drm: HDCP2.2 link check related constants Ramalingam C
2018-12-19 15:16   ` Daniel Vetter
2018-12-19 15:39     ` C, Ramalingam
2018-12-19 15:58       ` Daniel Vetter
2018-12-19 16:22         ` C, Ramalingam
2018-12-19 16:35           ` Daniel Vetter
2018-12-19 17:01             ` C, Ramalingam
2018-12-13  4:01 ` [PATCH v9 14/39] drm/i915: Implement HDCP2.2 link integrity check Ramalingam C
2018-12-13  4:01 ` [PATCH v9 15/39] drm/i915: Handle HDCP2.2 downstream topology change Ramalingam C
2018-12-13  4:01 ` [PATCH v9 16/39] drm/i915: Implement the HDCP2.2 support for DP Ramalingam C
2018-12-13  4:01 ` [PATCH v9 17/39] drm/i915: Implement the HDCP2.2 support for HDMI Ramalingam C
2018-12-13  4:01 ` [PATCH v9 18/39] drm/i915: Add HDCP2.2 support for DP connectors Ramalingam C
2018-12-13  4:01 ` [PATCH v9 19/39] drm/i915: Add HDCP2.2 support for HDMI connectors Ramalingam C
2018-12-13  4:01 ` [PATCH v9 20/39] mei: bus: whitelist hdcp client Ramalingam C
2018-12-13  4:01 ` [PATCH v9 21/39] mei: bus: export to_mei_cl_device for mei client device drivers Ramalingam C
2018-12-13  4:01 ` [PATCH v9 22/39] misc/mei/hdcp: Client driver for HDCP application Ramalingam C
2018-12-13  4:01 ` [PATCH v9 23/39] misc/mei/hdcp: Define ME FW interface for HDCP2.2 Ramalingam C
2018-12-13  4:01 ` [PATCH v9 24/39] misc/mei/hdcp: Initiate Wired HDCP2.2 Tx Session Ramalingam C
2018-12-13  4:01 ` [PATCH v9 25/39] misc/mei/hdcp: Verify Receiver Cert and prepare km Ramalingam C
2018-12-13  4:01 ` [PATCH v9 26/39] misc/mei/hdcp: Verify H_prime Ramalingam C
2018-12-13  4:01 ` [PATCH v9 27/39] misc/mei/hdcp: Store the HDCP Pairing info Ramalingam C
2018-12-13  4:01 ` [PATCH v9 28/39] misc/mei/hdcp: Initiate Locality check Ramalingam C
2018-12-13  4:01 ` [PATCH v9 29/39] misc/mei/hdcp: Verify L_prime Ramalingam C
2018-12-13  4:01 ` [PATCH v9 30/39] misc/mei/hdcp: Prepare Session Key Ramalingam C
2018-12-13  4:01 ` [PATCH v9 31/39] misc/mei/hdcp: Repeater topology verification and ack Ramalingam C
2018-12-13  4:01 ` [PATCH v9 32/39] misc/mei/hdcp: Verify M_prime Ramalingam C
2018-12-13  4:01 ` [PATCH v9 33/39] misc/mei/hdcp: Enabling the HDCP authentication Ramalingam C
2018-12-13  4:01 ` [PATCH v9 34/39] misc/mei/hdcp: Closing wired HDCP2.2 Tx Session Ramalingam C
2018-12-13  4:01 ` [PATCH v9 35/39] misc/mei/hdcp: Component framework for I915 Interface Ramalingam C
2018-12-13 12:36   ` C, Ramalingam
2018-12-13 16:11     ` Daniel Vetter
2018-12-13 16:27       ` Winkler, Tomas
2018-12-13 17:35         ` Daniel Vetter
2018-12-15 21:20           ` Winkler, Tomas
2018-12-17  9:39             ` Daniel Vetter
2018-12-17  9:59               ` Daniel Vetter
2018-12-17 10:57               ` Winkler, Tomas
2018-12-17 13:46                 ` Daniel Vetter
2018-12-19  6:45                   ` C, Ramalingam
2018-12-20 15:59                     ` C, Ramalingam
2018-12-20 16:06                       ` Winkler, Tomas
2018-12-20 16:47                         ` C, Ramalingam
2018-12-13  4:01 ` [PATCH v9 36/39] drm/i915: Commit CP without modeset Ramalingam C
2018-12-13  4:01 ` [PATCH v9 37/39] drm/i915: Fix KBL HDCP2.2 encrypt status signalling Ramalingam C
2018-12-19 15:40   ` Daniel Vetter
2018-12-19 16:16     ` C, Ramalingam
2018-12-13  4:01 ` [PATCH v9 38/39] FOR_TEST: i915/Kconfig: Select mei_hdcp by I915 Ramalingam C
2018-12-13  4:01 ` [PATCH v9 39/39] FOR_TESTING_ONLY: debugfs: Excluding the LSPCon for HDCP1.4 Ramalingam C
2018-12-13  4:17 ` ✗ Fi.CI.CHECKPATCH: warning for drm/i915: Implement HDCP2.2 (rev11) Patchwork
2018-12-13  4:27 ` ✗ Fi.CI.SPARSE: " Patchwork
2018-12-13  4:44 ` ✗ Fi.CI.BAT: failure " Patchwork
2018-12-20 16:58 ` ✗ Fi.CI.BAT: failure for drm/i915: Implement HDCP2.2 (rev12) Patchwork

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.