All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v10 00/40] drm/i915: Implement HDCP2.2
@ 2019-01-31  6:59 Ramalingam C
  2019-01-31  6:59 ` [PATCH v10 01/40] components: multiple components for a device Ramalingam C
                   ` (42 more replies)
  0 siblings, 43 replies; 121+ messages in thread
From: Ramalingam C @ 2019-01-31  6:59 UTC (permalink / raw)
  To: intel-gfx, dri-devel, daniel.vetter, tomas.winkler, uma.shankar

This series enables the HDCP2.2 Type 0 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 streams.

Major changes in v10:
  - I915-MEI interface is implemented with component framework.
  - I915 detects the mei_hdcp device availability to enabled HDCP2.2.

Hopefully we are near the end of this series.

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

Daniel Vetter (2):
  components: multiple components for a device
  i915/snd_hdac: I915 subcomponent for the snd_hdac

Ramalingam C (36):
  drm/i915: Gathering the HDCP1.4 routines together
  drm: header for i915 - MEI_HDCP interface
  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 period
  drm/i915: Implement HDCP2.2 link integrity check
  drm/i915: Handle HDCP2.2 downstream topology change
  drm: removing the DP Errata msg and its msg id
  drm/i915: Implement the HDCP2.2 support for DP
  drm/i915: Implement the HDCP2.2 support for HDMI
  drm/i915: CP_IRQ handling for DP HDCP2.2 msgs
  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/component.c              |   67 +-
 drivers/gpu/drm/i915/i915_debugfs.c   |   10 +-
 drivers/gpu/drm/i915/i915_drv.c       |    1 +
 drivers/gpu/drm/i915/i915_drv.h       |    7 +
 drivers/gpu/drm/i915/intel_audio.c    |    4 +-
 drivers/gpu/drm/i915/intel_ddi.c      |    7 -
 drivers/gpu/drm/i915/intel_display.c  |   10 +
 drivers/gpu/drm/i915/intel_dp.c       |  355 +++++++++-
 drivers/gpu/drm/i915/intel_drv.h      |   88 ++-
 drivers/gpu/drm/i915/intel_hdcp.c     | 1248 ++++++++++++++++++++++++++++++---
 drivers/gpu/drm/i915/intel_hdmi.c     |  240 ++++++-
 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      |  835 ++++++++++++++++++++++
 drivers/misc/mei/hdcp/mei_hdcp.h      |  399 +++++++++++
 include/drm/drm_hdcp.h                |   25 +-
 include/drm/i915_component.h          |    7 +
 include/drm/i915_mei_hdcp_interface.h |  148 ++++
 include/linux/component.h             |    5 +
 include/linux/mei_cl_bus.h            |    2 +
 include/sound/hda_component.h         |    5 +-
 sound/hda/hdac_component.c            |    4 +-
 sound/hda/hdac_i915.c                 |    6 +-
 26 files changed, 3352 insertions(+), 155 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] 121+ messages in thread

* [PATCH v10 01/40] components: multiple components for a device
  2019-01-31  6:59 [PATCH v10 00/40] drm/i915: Implement HDCP2.2 Ramalingam C
@ 2019-01-31  6:59 ` Ramalingam C
  2019-01-31  7:50   ` Greg Kroah-Hartman
                     ` (2 more replies)
  2019-01-31  6:59 ` [PATCH v10 02/40] i915/snd_hdac: I915 subcomponent for the snd_hdac Ramalingam C
                   ` (41 subsequent siblings)
  42 siblings, 3 replies; 121+ messages in thread
From: Ramalingam C @ 2019-01-31  6:59 UTC (permalink / raw)
  To: intel-gfx, dri-devel, daniel.vetter, tomas.winkler, uma.shankar
  Cc: Rafael J . Wysocki, Rodrigo Vivi, Takashi Iwai, Jaroslav Kysela,
	Greg Kroah-Hartman, Russell King

From: Daniel Vetter <daniel.vetter@ffwll.ch>

Component framework is extended to support multiple components for
a struct device. These will be matched with different masters based on
its sub component value.

We are introducing this, as I915 needs two different components
with different subcomponent value, which will be matched to two
different component masters(Audio and HDCP) based on the subcomponent
values.

Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
Signed-off-by: Ramalingam C <ramalingam.c@intel.com>
cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
cc: Russell King <rmk+kernel@arm.linux.org.uk>
cc: Rafael J. Wysocki <rafael@kernel.org>
cc: Jaroslav Kysela <perex@perex.cz>
cc: Takashi Iwai <tiwai@suse.com>
cc: Rodrigo Vivi <rodrigo.vivi@intel.com>
cc: Jani Nikula <jani.nikula@linux.intel.com>
---
 drivers/base/component.c  | 67 +++++++++++++++++++++++++++++++++++++++--------
 include/linux/component.h |  5 ++++
 2 files changed, 61 insertions(+), 11 deletions(-)

diff --git a/drivers/base/component.c b/drivers/base/component.c
index ddcea8739c12..30309c0449ed 100644
--- a/drivers/base/component.c
+++ b/drivers/base/component.c
@@ -21,6 +21,7 @@ struct component;
 struct component_match_array {
 	void *data;
 	int (*compare)(struct device *, void *);
+	int (*compare_typed)(struct device *, int, void *);
 	void (*release)(struct device *, void *);
 	struct component *component;
 	bool duplicate;
@@ -48,6 +49,7 @@ struct component {
 	bool bound;
 
 	const struct component_ops *ops;
+	int subcomponent;
 	struct device *dev;
 };
 
@@ -132,7 +134,7 @@ static struct master *__master_find(struct device *dev,
 }
 
 static struct component *find_component(struct master *master,
-	int (*compare)(struct device *, void *), void *compare_data)
+	struct component_match_array *mc)
 {
 	struct component *c;
 
@@ -140,8 +142,13 @@ static struct component *find_component(struct master *master,
 		if (c->master && c->master != master)
 			continue;
 
-		if (compare(c->dev, compare_data))
+		if (mc->compare_typed) {
+			if (mc->compare_typed(c->dev, c->subcomponent,
+					      mc->data))
+				return c;
+		} else if (mc->compare(c->dev, mc->data)) {
 			return c;
+		}
 	}
 
 	return NULL;
@@ -166,7 +173,7 @@ static int find_components(struct master *master)
 		if (match->compare[i].component)
 			continue;
 
-		c = find_component(master, mc->compare, mc->data);
+		c = find_component(master, mc);
 		if (!c) {
 			ret = -ENXIO;
 			break;
@@ -301,15 +308,12 @@ static int component_match_realloc(struct device *dev,
 	return 0;
 }
 
-/*
- * Add a component to be matched, with a release function.
- *
- * The match array is first created or extended if necessary.
- */
-void component_match_add_release(struct device *master,
+static void __component_match_add(struct device *master,
 	struct component_match **matchptr,
 	void (*release)(struct device *, void *),
-	int (*compare)(struct device *, void *), void *compare_data)
+	int (*compare)(struct device *, void *),
+	int (*compare_typed)(struct device *, int, void *),
+	void *compare_data)
 {
 	struct component_match *match = *matchptr;
 
@@ -341,13 +345,37 @@ void component_match_add_release(struct device *master,
 	}
 
 	match->compare[match->num].compare = compare;
+	match->compare[match->num].compare_typed = compare_typed;
 	match->compare[match->num].release = release;
 	match->compare[match->num].data = compare_data;
 	match->compare[match->num].component = NULL;
 	match->num++;
 }
+
+/*
+ * Add a component to be matched, with a release function.
+ *
+ * The match array is first created or extended if necessary.
+ */
+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)
+{
+	__component_match_add(master, matchptr, release, compare, NULL,
+			      compare_data);
+}
 EXPORT_SYMBOL(component_match_add_release);
 
+void component_match_add_typed(struct device *master,
+	struct component_match **matchptr,
+	int (*compare_typed)(struct device *, int, void *), void *compare_data)
+{
+	__component_match_add(master, matchptr, NULL, NULL, compare_typed,
+			      compare_data);
+}
+EXPORT_SYMBOL(component_match_add_typed);
+
 static void free_master(struct master *master)
 {
 	struct component_match *match = master->match;
@@ -537,7 +565,8 @@ int component_bind_all(struct device *master_dev, void *data)
 }
 EXPORT_SYMBOL_GPL(component_bind_all);
 
-int component_add(struct device *dev, const struct component_ops *ops)
+static int __component_add(struct device *dev, const struct component_ops *ops,
+	int subcomponent)
 {
 	struct component *component;
 	int ret;
@@ -548,6 +577,7 @@ int component_add(struct device *dev, const struct component_ops *ops)
 
 	component->ops = ops;
 	component->dev = dev;
+	component->subcomponent = subcomponent;
 
 	dev_dbg(dev, "adding component (ops %ps)\n", ops);
 
@@ -566,6 +596,21 @@ int component_add(struct device *dev, const struct component_ops *ops)
 
 	return ret < 0 ? ret : 0;
 }
+
+int component_add_typed(struct device *dev, const struct component_ops *ops,
+	int subcomponent)
+{
+	if (WARN_ON(subcomponent == 0))
+		return -EINVAL;
+
+	return __component_add(dev, ops, subcomponent);
+}
+EXPORT_SYMBOL_GPL(component_add_typed);
+
+int component_add(struct device *dev, const struct component_ops *ops)
+{
+	return __component_add(dev, ops, 0);
+}
 EXPORT_SYMBOL_GPL(component_add);
 
 void component_del(struct device *dev, const struct component_ops *ops)
diff --git a/include/linux/component.h b/include/linux/component.h
index e71fbbbc74e2..6d7516f0546e 100644
--- a/include/linux/component.h
+++ b/include/linux/component.h
@@ -14,6 +14,8 @@ struct component_ops {
 };
 
 int component_add(struct device *, const struct component_ops *);
+int component_add_typed(struct device *dev, const struct component_ops *ops,
+	int subcomponent);
 void component_del(struct device *, const struct component_ops *);
 
 int component_bind_all(struct device *master, void *master_data);
@@ -37,6 +39,9 @@ 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_add_typed(struct device *master,
+	struct component_match **matchptr,
+	int (*compare_typed)(struct device *, int, void *), void *compare_data);
 
 static inline void component_match_add(struct device *master,
 	struct component_match **matchptr,
-- 
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] 121+ messages in thread

* [PATCH v10 02/40] i915/snd_hdac: I915 subcomponent for the snd_hdac
  2019-01-31  6:59 [PATCH v10 00/40] drm/i915: Implement HDCP2.2 Ramalingam C
  2019-01-31  6:59 ` [PATCH v10 01/40] components: multiple components for a device Ramalingam C
@ 2019-01-31  6:59 ` Ramalingam C
  2019-02-04 15:00   ` Daniel Vetter
  2019-01-31  6:59 ` [PATCH v10 03/40] drm/i915: Gathering the HDCP1.4 routines together Ramalingam C
                   ` (40 subsequent siblings)
  42 siblings, 1 reply; 121+ messages in thread
From: Ramalingam C @ 2019-01-31  6:59 UTC (permalink / raw)
  To: intel-gfx, dri-devel, daniel.vetter, tomas.winkler, uma.shankar
  Cc: Rafael J . Wysocki, Takashi Iwai, Jaroslav Kysela,
	Greg Kroah-Hartman, Russell King

From: Daniel Vetter <daniel.vetter@ffwll.ch>

Since we need multiple components for I915 for different purposes
(Audio & Mei_hdcp), we adopt the subcomponents methodology introduced
by the previous patch (mentioned below).

	Author: Daniel Vetter <daniel.vetter@ffwll.ch>
	Date:   Mon Jan 28 17:08:20 2019 +0530

	    components: multiple components for a device

Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
Signed-off-by: Ramalingam C <ramalingam.c@intel.com>
cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
cc: Russell King <rmk+kernel@arm.linux.org.uk>
cc: Rafael J. Wysocki <rafael@kernel.org>
cc: Jaroslav Kysela <perex@perex.cz>
cc: Takashi Iwai <tiwai@suse.com>
cc: Rodrigo Vivi <rodrigo.vivi@intel.com>
cc: Jani Nikula <jani.nikula@linux.intel.com>
---
 drivers/gpu/drm/i915/intel_audio.c | 4 +++-
 include/drm/i915_component.h       | 4 ++++
 include/sound/hda_component.h      | 5 +++--
 sound/hda/hdac_component.c         | 4 ++--
 sound/hda/hdac_i915.c              | 6 ++++--
 5 files changed, 16 insertions(+), 7 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_audio.c b/drivers/gpu/drm/i915/intel_audio.c
index de26cd0a5497..5104c6bbd66f 100644
--- a/drivers/gpu/drm/i915/intel_audio.c
+++ b/drivers/gpu/drm/i915/intel_audio.c
@@ -984,7 +984,9 @@ void i915_audio_component_init(struct drm_i915_private *dev_priv)
 {
 	int ret;
 
-	ret = component_add(dev_priv->drm.dev, &i915_audio_component_bind_ops);
+	ret = component_add_typed(dev_priv->drm.dev,
+				  &i915_audio_component_bind_ops,
+				  I915_COMPONENT_AUDIO);
 	if (ret < 0) {
 		DRM_ERROR("failed to add audio component (%d)\n", ret);
 		/* continue with reduced functionality */
diff --git a/include/drm/i915_component.h b/include/drm/i915_component.h
index fca22d463e1b..72fbb037f9b3 100644
--- a/include/drm/i915_component.h
+++ b/include/drm/i915_component.h
@@ -26,6 +26,10 @@
 
 #include "drm_audio_component.h"
 
+enum i915_component_type {
+	I915_COMPONENT_AUDIO = 1,
+};
+
 /* MAX_PORT is the number of port
  * It must be sync with I915_MAX_PORTS defined i915_drv.h
  */
diff --git a/include/sound/hda_component.h b/include/sound/hda_component.h
index 2ec31b358950..d4804c72d959 100644
--- a/include/sound/hda_component.h
+++ b/include/sound/hda_component.h
@@ -20,7 +20,7 @@ int snd_hdac_acomp_get_eld(struct hdac_device *codec, hda_nid_t nid, int dev_id,
 			   bool *audio_enabled, char *buffer, int max_bytes);
 int snd_hdac_acomp_init(struct hdac_bus *bus,
 			const struct drm_audio_component_audio_ops *aops,
-			int (*match_master)(struct device *, void *),
+			int (*match_master)(struct device *, int, void *),
 			size_t extra_size);
 int snd_hdac_acomp_exit(struct hdac_bus *bus);
 int snd_hdac_acomp_register_notifier(struct hdac_bus *bus,
@@ -47,7 +47,8 @@ static inline int snd_hdac_acomp_get_eld(struct hdac_device *codec, hda_nid_t ni
 }
 static inline int snd_hdac_acomp_init(struct hdac_bus *bus,
 				      const struct drm_audio_component_audio_ops *aops,
-				      int (*match_master)(struct device *, void *),
+				      int (*match_master)(struct device *,
+							  int, void *),
 				      size_t extra_size)
 {
 	return -ENODEV;
diff --git a/sound/hda/hdac_component.c b/sound/hda/hdac_component.c
index a6d37b9d6413..5c95933e739a 100644
--- a/sound/hda/hdac_component.c
+++ b/sound/hda/hdac_component.c
@@ -269,7 +269,7 @@ EXPORT_SYMBOL_GPL(snd_hdac_acomp_register_notifier);
  */
 int snd_hdac_acomp_init(struct hdac_bus *bus,
 			const struct drm_audio_component_audio_ops *aops,
-			int (*match_master)(struct device *, void *),
+			int (*match_master)(struct device *, int, void *),
 			size_t extra_size)
 {
 	struct component_match *match = NULL;
@@ -288,7 +288,7 @@ int snd_hdac_acomp_init(struct hdac_bus *bus,
 	bus->audio_component = acomp;
 	devres_add(dev, acomp);
 
-	component_match_add(dev, &match, match_master, bus);
+	component_match_add_typed(dev, &match, match_master, bus);
 	ret = component_master_add_with_match(dev, &hdac_component_master_ops,
 					      match);
 	if (ret < 0)
diff --git a/sound/hda/hdac_i915.c b/sound/hda/hdac_i915.c
index 617ff1aa818f..7aee090e3d27 100644
--- a/sound/hda/hdac_i915.c
+++ b/sound/hda/hdac_i915.c
@@ -82,9 +82,11 @@ void snd_hdac_i915_set_bclk(struct hdac_bus *bus)
 }
 EXPORT_SYMBOL_GPL(snd_hdac_i915_set_bclk);
 
-static int i915_component_master_match(struct device *dev, void *data)
+static int i915_component_master_match(struct device *dev, int subcomponent,
+				       void *data)
 {
-	return !strcmp(dev->driver->name, "i915");
+	return !strcmp(dev->driver->name, "i915") &&
+	       subcomponent == I915_COMPONENT_AUDIO;
 }
 
 /* check whether intel graphics is present */
-- 
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] 121+ messages in thread

* [PATCH v10 03/40] drm/i915: Gathering the HDCP1.4 routines together
  2019-01-31  6:59 [PATCH v10 00/40] drm/i915: Implement HDCP2.2 Ramalingam C
  2019-01-31  6:59 ` [PATCH v10 01/40] components: multiple components for a device Ramalingam C
  2019-01-31  6:59 ` [PATCH v10 02/40] i915/snd_hdac: I915 subcomponent for the snd_hdac Ramalingam C
@ 2019-01-31  6:59 ` Ramalingam C
  2019-02-04 13:11   ` Shankar, Uma
  2019-01-31  6:59 ` [PATCH v10 04/40] drm: header for i915 - MEI_HDCP interface Ramalingam C
                   ` (39 subsequent siblings)
  42 siblings, 1 reply; 121+ messages in thread
From: Ramalingam C @ 2019-01-31  6:59 UTC (permalink / raw)
  To: intel-gfx, dri-devel, 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>
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 ce7ba3a9c000..8cb85b07cfde 100644
--- a/drivers/gpu/drm/i915/intel_hdcp.c
+++ b/drivers/gpu/drm/i915/intel_hdcp.c
@@ -730,6 +730,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),
@@ -866,62 +925,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

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

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

* [PATCH v10 04/40] drm: header for i915 - MEI_HDCP interface
  2019-01-31  6:59 [PATCH v10 00/40] drm/i915: Implement HDCP2.2 Ramalingam C
                   ` (2 preceding siblings ...)
  2019-01-31  6:59 ` [PATCH v10 03/40] drm/i915: Gathering the HDCP1.4 routines together Ramalingam C
@ 2019-01-31  6:59 ` Ramalingam C
  2019-02-04 13:24   ` Shankar, Uma
  2019-01-31  6:59 ` [PATCH v10 05/40] drm/i915: Initialize HDCP2.2 Ramalingam C
                   ` (38 subsequent siblings)
  42 siblings, 1 reply; 121+ messages in thread
From: Ramalingam C @ 2019-01-31  6:59 UTC (permalink / raw)
  To: intel-gfx, dri-devel, daniel.vetter, tomas.winkler, uma.shankar

Header defines the interface for the I915 and MEI_HDCP drivers.
This interface is specific to the usage of mei_hdcp from gen9+
platforms for ME FW based HDCP2.2 services.

And Generic HDCP2.2 protocol specific definitions
are added at drm/drm_hdcp.h.

v2: Commit msg is enhanced [Daniel]

v3: i915_hdcp_comp_master is defined.

Signed-off-by: Ramalingam C <ramalingam.c@intel.com>
Reviewed-by: Daniel Vetter <daniel.vetter@ffwll.ch>
---
 include/drm/i915_mei_hdcp_interface.h | 148 ++++++++++++++++++++++++++++++++++
 1 file changed, 148 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..bc5b0c71ed3c
--- /dev/null
+++ b/include/drm/i915_mei_hdcp_interface.h
@@ -0,0 +1,148 @@
+/* SPDX-License-Identifier: (GPL-2.0+) */
+/*
+ * 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 <linux/device.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);
+};
+
+/**
+ * struct i915_hdcp_component_master - Used for communication between i915
+ * and mei_hdcp drivers for the HDCP2.2 services
+ * @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_hdcp_comp_master {
+	struct device *mei_dev;
+	const struct i915_hdcp_component_ops *ops;
+
+	/* To protect the above members. */
+	struct mutex mutex;
+};
+
+#endif /* _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 related	[flat|nested] 121+ messages in thread

* [PATCH v10 05/40] drm/i915: Initialize HDCP2.2
  2019-01-31  6:59 [PATCH v10 00/40] drm/i915: Implement HDCP2.2 Ramalingam C
                   ` (3 preceding siblings ...)
  2019-01-31  6:59 ` [PATCH v10 04/40] drm: header for i915 - MEI_HDCP interface Ramalingam C
@ 2019-01-31  6:59 ` Ramalingam C
  2019-02-04 13:29   ` Shankar, Uma
  2019-01-31  6:59 ` [PATCH v10 06/40] drm/i915: MEI interface definition Ramalingam C
                   ` (37 subsequent siblings)
  42 siblings, 1 reply; 121+ messages in thread
From: Ramalingam C @ 2019-01-31  6:59 UTC (permalink / raw)
  To: intel-gfx, dri-devel, 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.
v10:
  bool is used in struct to make coding simpler. [Daniel]
  hdmi hdcp init is placed correctly after encoder attachment.

Signed-off-by: Ramalingam C <ramalingam.c@intel.com>
Reviewed-by: Daniel Vetter <daniel.vetter@ffwll.ch>
---
 drivers/gpu/drm/i915/intel_dp.c   |  3 ++-
 drivers/gpu/drm/i915/intel_drv.h  | 15 ++++++++++++++-
 drivers/gpu/drm/i915/intel_hdcp.c | 33 ++++++++++++++++++++++++++++++---
 drivers/gpu/drm/i915/intel_hdmi.c |  8 ++++----
 4 files changed, 50 insertions(+), 9 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
index 681e88405ada..815ee68efa2f 100644
--- a/drivers/gpu/drm/i915/intel_dp.c
+++ b/drivers/gpu/drm/i915/intel_dp.c
@@ -6950,7 +6950,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 90ba5436370e..0ac870feb5e9 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -394,6 +394,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. */
+	bool 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 {
@@ -2053,12 +2064,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 8cb85b07cfde..1a85dc46692d 100644
--- a/drivers/gpu/drm/i915/intel_hdcp.c
+++ b/drivers/gpu/drm/i915/intel_hdcp.c
@@ -832,14 +832,37 @@ 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)
+{
+	if (!IS_ENABLED(CONFIG_INTEL_MEI_HDCP))
+		return false;
+
+	return (INTEL_GEN(dev_priv) >= 10 || IS_GEMINILAKE(dev_priv) ||
+		IS_KABYLAKE(dev_priv));
+}
+
+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 = true;
+}
+
 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;
 
@@ -847,6 +870,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 97a98e1bea56..ab376a31cdab 100644
--- a/drivers/gpu/drm/i915/intel_hdmi.c
+++ b/drivers/gpu/drm/i915/intel_hdmi.c
@@ -2427,16 +2427,16 @@ void intel_hdmi_init_connector(struct intel_digital_port *intel_dig_port,
 
 	intel_hdmi_add_properties(intel_hdmi, connector);
 
+	intel_connector_attach_encoder(intel_connector, intel_encoder);
+	intel_hdmi->attached_connector = intel_connector;
+
 	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");
 	}
 
-	intel_connector_attach_encoder(intel_connector, intel_encoder);
-	intel_hdmi->attached_connector = intel_connector;
-
 	/* For G4X desktop chip, PEG_BAND_GAP_DATA 3:0 must first be written
 	 * 0xd.  Failure to do so will result in spurious interrupts being
 	 * generated on the port when a cable is not attached.
-- 
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] 121+ messages in thread

* [PATCH v10 06/40] drm/i915: MEI interface definition
  2019-01-31  6:59 [PATCH v10 00/40] drm/i915: Implement HDCP2.2 Ramalingam C
                   ` (4 preceding siblings ...)
  2019-01-31  6:59 ` [PATCH v10 05/40] drm/i915: Initialize HDCP2.2 Ramalingam C
@ 2019-01-31  6:59 ` Ramalingam C
  2019-01-31  8:17   ` Daniel Vetter
  2019-01-31  6:59 ` [PATCH v10 07/40] drm/i915: hdcp1.4 CP_IRQ handling and SW encryption tracking Ramalingam C
                   ` (36 subsequent siblings)
  42 siblings, 1 reply; 121+ messages in thread
From: Ramalingam C @ 2019-01-31  6:59 UTC (permalink / raw)
  To: intel-gfx, dri-devel, 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]
v4:
  port initialization is done only at hdcp2_init only [Danvet]
v5:
  I915 registers a subcomponent to be matched with mei_hdcp [Daniel]

Signed-off-by: Ramalingam C <ramalingam.c@intel.com>
Reviewed-by: Daniel Vetter <daniel.vetter@ffwll.ch>
---
 drivers/gpu/drm/i915/i915_drv.c   |   1 +
 drivers/gpu/drm/i915/i915_drv.h   |   7 +
 drivers/gpu/drm/i915/intel_drv.h  |   5 +
 drivers/gpu/drm/i915/intel_hdcp.c | 378 +++++++++++++++++++++++++++++++++++++-
 include/drm/i915_component.h      |   3 +
 5 files changed, 393 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c
index a7aaa1ac4c99..75aff907ba69 100644
--- a/drivers/gpu/drm/i915/i915_drv.c
+++ b/drivers/gpu/drm/i915/i915_drv.c
@@ -904,6 +904,7 @@ static int i915_driver_init_early(struct drm_i915_private *dev_priv)
 	mutex_init(&dev_priv->av_mutex);
 	mutex_init(&dev_priv->wm.wm_mutex);
 	mutex_init(&dev_priv->pps_mutex);
+	mutex_init(&dev_priv->hdcp_comp_mutex);
 
 	i915_memcpy_init_early(dev_priv);
 	intel_runtime_pm_init_early(dev_priv);
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index 22da9df1f0a7..d9a0771af4d1 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -55,6 +55,7 @@
 #include <drm/drm_util.h>
 #include <drm/drm_dsc.h>
 #include <drm/drm_connector.h>
+#include <drm/i915_mei_hdcp_interface.h>
 
 #include "i915_fixed.h"
 #include "i915_params.h"
@@ -2043,6 +2044,12 @@ struct drm_i915_private {
 
 	struct i915_pmu pmu;
 
+	struct i915_hdcp_comp_master *hdcp_master;
+	bool hdcp_comp_added;
+
+	/* Mutex to protect the above hdcp component related values. */
+	struct mutex hdcp_comp_mutex;
+
 	/*
 	 * 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/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index 0ac870feb5e9..63e009286d5f 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -41,6 +41,7 @@
 #include <drm/drm_rect.h>
 #include <drm/drm_vblank.h>
 #include <drm/drm_atomic.h>
+#include <drm/i915_mei_hdcp_interface.h>
 #include <media/cec-notifier.h>
 
 struct drm_printer;
@@ -385,6 +386,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 {
@@ -405,6 +409,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 1a85dc46692d..e0bb5f32ba90 100644
--- a/drivers/gpu/drm/i915/intel_hdcp.c
+++ b/drivers/gpu/drm/i915/intel_hdcp.c
@@ -7,8 +7,10 @@
  */
 
 #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"
@@ -832,6 +834,348 @@ 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_hdcp_comp_master *comp;
+	int ret;
+
+	mutex_lock(&dev_priv->hdcp_comp_mutex);
+	comp = dev_priv->hdcp_master;
+
+	if (!comp || !comp->ops) {
+		mutex_unlock(&dev_priv->hdcp_comp_mutex);
+		return -EINVAL;
+	}
+
+	ret = comp->ops->initiate_hdcp2_session(comp->mei_dev, data, ake_data);
+	if (ret)
+		DRM_DEBUG_KMS("Prepare_ake_init failed. %d\n", ret);
+	mutex_unlock(&dev_priv->hdcp_comp_mutex);
+
+	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_hdcp_comp_master *comp;
+	int ret;
+
+	mutex_lock(&dev_priv->hdcp_comp_mutex);
+	comp = dev_priv->hdcp_master;
+
+	if (!comp || !comp->ops) {
+		mutex_unlock(&dev_priv->hdcp_comp_mutex);
+		return -EINVAL;
+	}
+
+	ret = comp->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);
+	mutex_unlock(&dev_priv->hdcp_comp_mutex);
+
+	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_hdcp_comp_master *comp;
+	int ret;
+
+	mutex_lock(&dev_priv->hdcp_comp_mutex);
+	comp = dev_priv->hdcp_master;
+
+	if (!comp || !comp->ops) {
+		mutex_unlock(&dev_priv->hdcp_comp_mutex);
+		return -EINVAL;
+	}
+
+	ret = comp->ops->verify_hprime(comp->mei_dev, data, rx_hprime);
+	if (ret < 0)
+		DRM_DEBUG_KMS("Verify hprime failed. %d\n", ret);
+	mutex_unlock(&dev_priv->hdcp_comp_mutex);
+
+	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_hdcp_comp_master *comp;
+	int ret;
+
+	mutex_lock(&dev_priv->hdcp_comp_mutex);
+	comp = dev_priv->hdcp_master;
+
+	if (!comp || !comp->ops) {
+		mutex_unlock(&dev_priv->hdcp_comp_mutex);
+		return -EINVAL;
+	}
+
+	ret = comp->ops->store_pairing_info(comp->mei_dev, data, pairing_info);
+	if (ret < 0)
+		DRM_DEBUG_KMS("Store pairing info failed. %d\n", ret);
+	mutex_unlock(&dev_priv->hdcp_comp_mutex);
+
+	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_hdcp_comp_master *comp;
+	int ret;
+
+	mutex_lock(&dev_priv->hdcp_comp_mutex);
+	comp = dev_priv->hdcp_master;
+
+	if (!comp || !comp->ops) {
+		mutex_unlock(&dev_priv->hdcp_comp_mutex);
+		return -EINVAL;
+	}
+
+	ret = comp->ops->initiate_locality_check(comp->mei_dev, data, lc_init);
+	if (ret < 0)
+		DRM_DEBUG_KMS("Prepare lc_init failed. %d\n", ret);
+	mutex_unlock(&dev_priv->hdcp_comp_mutex);
+
+	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_hdcp_comp_master *comp;
+	int ret;
+
+	mutex_lock(&dev_priv->hdcp_comp_mutex);
+	comp = dev_priv->hdcp_master;
+
+	if (!comp || !comp->ops) {
+		mutex_unlock(&dev_priv->hdcp_comp_mutex);
+		return -EINVAL;
+	}
+
+	ret = comp->ops->verify_lprime(comp->mei_dev, data, rx_lprime);
+	if (ret < 0)
+		DRM_DEBUG_KMS("Verify L_Prime failed. %d\n", ret);
+	mutex_unlock(&dev_priv->hdcp_comp_mutex);
+
+	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_hdcp_comp_master *comp;
+	int ret;
+
+	mutex_lock(&dev_priv->hdcp_comp_mutex);
+	comp = dev_priv->hdcp_master;
+
+	if (!comp || !comp->ops) {
+		mutex_unlock(&dev_priv->hdcp_comp_mutex);
+		return -EINVAL;
+	}
+
+	ret = comp->ops->get_session_key(comp->mei_dev, data, ske_data);
+	if (ret < 0)
+		DRM_DEBUG_KMS("Get session key failed. %d\n", ret);
+	mutex_unlock(&dev_priv->hdcp_comp_mutex);
+
+	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_hdcp_comp_master *comp;
+	int ret;
+
+	mutex_lock(&dev_priv->hdcp_comp_mutex);
+	comp = dev_priv->hdcp_master;
+
+	if (!comp || !comp->ops) {
+		mutex_unlock(&dev_priv->hdcp_comp_mutex);
+		return -EINVAL;
+	}
+
+	ret = comp->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);
+	mutex_unlock(&dev_priv->hdcp_comp_mutex);
+
+	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_hdcp_comp_master *comp;
+	int ret;
+
+	mutex_lock(&dev_priv->hdcp_comp_mutex);
+	comp = dev_priv->hdcp_master;
+
+	if (!comp || !comp->ops) {
+		mutex_unlock(&dev_priv->hdcp_comp_mutex);
+		return -EINVAL;
+	}
+
+	ret = comp->ops->verify_mprime(comp->mei_dev, data, stream_ready);
+	if (ret < 0)
+		DRM_DEBUG_KMS("Verify mprime failed. %d\n", ret);
+	mutex_unlock(&dev_priv->hdcp_comp_mutex);
+
+	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_hdcp_comp_master *comp;
+	int ret;
+
+	mutex_lock(&dev_priv->hdcp_comp_mutex);
+	comp = dev_priv->hdcp_master;
+
+	if (!comp || !comp->ops) {
+		mutex_unlock(&dev_priv->hdcp_comp_mutex);
+		return -EINVAL;
+	}
+
+	ret = comp->ops->enable_hdcp_authentication(comp->mei_dev, data);
+	if (ret < 0)
+		DRM_DEBUG_KMS("Enable hdcp auth failed. %d\n", ret);
+	mutex_unlock(&dev_priv->hdcp_comp_mutex);
+
+	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_hdcp_comp_master *comp;
+	int ret;
+
+	mutex_lock(&dev_priv->hdcp_comp_mutex);
+	comp = dev_priv->hdcp_master;
+
+	if (!comp || !comp->ops) {
+		mutex_unlock(&dev_priv->hdcp_comp_mutex);
+		return -EINVAL;
+	}
+
+	ret = comp->ops->close_hdcp_session(comp->mei_dev,
+					     &connector->hdcp.port_data);
+	mutex_unlock(&dev_priv->hdcp_comp_mutex);
+
+	return ret;
+}
+
+static __attribute__((unused))
+int hdcp2_deauthenticate_port(struct intel_connector *connector)
+{
+	return hdcp2_close_mei_session(connector);
+}
+
+static int i915_hdcp_component_bind(struct device *i915_kdev,
+				    struct device *mei_kdev, void *data)
+{
+	struct drm_i915_private *dev_priv = kdev_to_i915(i915_kdev);
+
+	DRM_DEBUG("I915 HDCP comp bind\n");
+	mutex_lock(&dev_priv->hdcp_comp_mutex);
+	dev_priv->hdcp_master = (struct i915_hdcp_comp_master *)data;
+	dev_priv->hdcp_master->mei_dev = mei_kdev;
+	mutex_unlock(&dev_priv->hdcp_comp_mutex);
+
+	return 0;
+}
+
+static void i915_hdcp_component_unbind(struct device *i915_kdev,
+				       struct device *mei_kdev, void *data)
+{
+	struct drm_i915_private *dev_priv = kdev_to_i915(i915_kdev);
+
+	DRM_DEBUG("I915 HDCP comp unbind\n");
+	mutex_lock(&dev_priv->hdcp_comp_mutex);
+	dev_priv->hdcp_master->mei_dev = NULL;
+	dev_priv->hdcp_master = NULL;
+	mutex_unlock(&dev_priv->hdcp_comp_mutex);
+}
+
+static const struct component_ops i915_hdcp_component_ops = {
+	.bind   = i915_hdcp_component_bind,
+	.unbind = i915_hdcp_component_unbind,
+};
+
+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 = 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)
 {
 	if (!IS_ENABLED(CONFIG_INTEL_MEI_HDCP))
@@ -845,10 +1189,42 @@ 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;
+	bool add_component = false;
+	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;
+	}
+
+	mutex_lock(&dev_priv->hdcp_comp_mutex);
+	/*
+	 * Component for mei is common across the connector.
+	 * Adding the component once is sufficient.
+	 */
+	if (!dev_priv->hdcp_comp_added) {
+		dev_priv->hdcp_comp_added = true;
+		add_component = true;
+	}
+	mutex_unlock(&dev_priv->hdcp_comp_mutex);
+
+	if (add_component) {
+		ret = component_add_typed(dev_priv->drm.dev,
+					  &i915_hdcp_component_ops,
+					  I915_COMPONENT_HDCP);
+		if (ret < 0) {
+			DRM_DEBUG_KMS("Failed at component add(%d)\n", ret);
+			mutex_lock(&dev_priv->hdcp_comp_mutex);
+			dev_priv->hdcp_comp_added = false;
+			mutex_unlock(&dev_priv->hdcp_comp_mutex);
+			kfree(hdcp->port_data.streams);
+			return;
+		}
+	}
+
 	hdcp->hdcp2_supported = true;
 }
 
diff --git a/include/drm/i915_component.h b/include/drm/i915_component.h
index 72fbb037f9b3..f3851ba3e4c3 100644
--- a/include/drm/i915_component.h
+++ b/include/drm/i915_component.h
@@ -24,10 +24,13 @@
 #ifndef _I915_COMPONENT_H_
 #define _I915_COMPONENT_H_
 
+#include <linux/device.h>
+
 #include "drm_audio_component.h"
 
 enum i915_component_type {
 	I915_COMPONENT_AUDIO = 1,
+	I915_COMPONENT_HDCP,
 };
 
 /* MAX_PORT is the number of port
-- 
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] 121+ messages in thread

* [PATCH v10 07/40] drm/i915: hdcp1.4 CP_IRQ handling and SW encryption tracking
  2019-01-31  6:59 [PATCH v10 00/40] drm/i915: Implement HDCP2.2 Ramalingam C
                   ` (5 preceding siblings ...)
  2019-01-31  6:59 ` [PATCH v10 06/40] drm/i915: MEI interface definition Ramalingam C
@ 2019-01-31  6:59 ` Ramalingam C
  2019-01-31  7:56   ` Daniel Vetter
  2019-02-04 14:09   ` Shankar, Uma
  2019-01-31  6:59 ` [PATCH v10 08/40] drm/i915: Enable and Disable of HDCP2.2 Ramalingam C
                   ` (35 subsequent siblings)
  42 siblings, 2 replies; 121+ messages in thread
From: Ramalingam C @ 2019-01-31  6:59 UTC (permalink / raw)
  To: intel-gfx, dri-devel, 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.

v2:
  bool is used in struct for the cleaner coding. [Daniel]
  check_link work_fn is scheduled for cp_irq handling [Daniel]

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 | 73 ++++++++++++++++++++++++++++-----------
 3 files changed, 58 insertions(+), 22 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
index 815ee68efa2f..9ce05819fc11 100644
--- a/drivers/gpu/drm/i915/intel_dp.c
+++ b/drivers/gpu/drm/i915/intel_dp.c
@@ -4776,7 +4776,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 63e009286d5f..13a41e8cf4ff 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -399,6 +399,9 @@ struct intel_hdcp {
 	struct delayed_work check_work;
 	struct work_struct prop_work;
 
+	/* HDCP1.4 Encryption status */
+	bool hdcp_encrypted;
+
 	/* HDCP2.2 related definitions */
 	/* Flag indicates whether this connector supports HDCP2.2 or not. */
 	bool hdcp2_supported;
@@ -2073,10 +2076,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 e0bb5f32ba90..c1b057f1501b 100644
--- a/drivers/gpu/drm/i915/intel_hdcp.c
+++ b/drivers/gpu/drm/i915/intel_hdcp.c
@@ -74,6 +74,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)
 {
@@ -668,6 +678,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 = false;
 	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)) {
@@ -713,8 +724,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 = true;
 			return 0;
+		}
 
 		DRM_DEBUG_KMS("HDCP Auth failure (%d)\n", ret);
 
@@ -741,16 +754,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;
@@ -791,18 +805,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,
@@ -1120,6 +1122,18 @@ int hdcp2_deauthenticate_port(struct intel_connector *connector)
 	return hdcp2_close_mei_session(connector);
 }
 
+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 int i915_hdcp_component_bind(struct device *i915_kdev,
 				    struct device *mei_kdev, void *data)
 {
@@ -1288,7 +1302,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);
@@ -1328,3 +1343,21 @@ 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;
+
+	/*
+	 * CP_IRQ could be triggered due to 1. HDCP2.2 auth msgs availability,
+	 * 2. link failure and 3. repeater reauth request. At present we dont
+	 * handle the CP_IRQ for the HDCP2.2 auth msg availability for read.
+	 * To handle other two causes for CP_IRQ we have the work_fn which is
+	 * scheduled here.
+	 */
+	schedule_delayed_work(&hdcp->check_work, 0);
+}
-- 
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] 121+ messages in thread

* [PATCH v10 08/40] drm/i915: Enable and Disable of HDCP2.2
  2019-01-31  6:59 [PATCH v10 00/40] drm/i915: Implement HDCP2.2 Ramalingam C
                   ` (6 preceding siblings ...)
  2019-01-31  6:59 ` [PATCH v10 07/40] drm/i915: hdcp1.4 CP_IRQ handling and SW encryption tracking Ramalingam C
@ 2019-01-31  6:59 ` Ramalingam C
  2019-02-04 14:17   ` Shankar, Uma
  2019-01-31  6:59 ` [PATCH v10 09/40] drm/i915: Implement HDCP2.2 receiver authentication Ramalingam C
                   ` (34 subsequent siblings)
  42 siblings, 1 reply; 121+ messages in thread
From: Ramalingam C @ 2019-01-31  6:59 UTC (permalink / raw)
  To: intel-gfx, dri-devel, 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
v9:
  bool is used in struct intel_hdcp. [Daniel]

Signed-off-by: Ramalingam C <ramalingam.c@intel.com>
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 13a41e8cf4ff..31c7a4577ca9 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -389,6 +389,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 {
@@ -406,6 +410,9 @@ struct intel_hdcp {
 	/* Flag indicates whether this connector supports HDCP2.2 or not. */
 	bool hdcp2_supported;
 
+	/* HDCP2.2 Encryption status */
+	bool 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 c1b057f1501b..fbf8b7893bfa 100644
--- a/drivers/gpu/drm/i915/intel_hdcp.c
+++ b/drivers/gpu/drm/i915/intel_hdcp.c
@@ -74,6 +74,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);
@@ -1094,8 +1111,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_hdcp_comp_master *comp;
@@ -1116,12 +1132,157 @@ int hdcp2_close_mei_session(struct intel_connector *connector)
 	return ret;
 }
 
-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 = true;
+	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 = false;
+
+	return ret;
+}
+
 static void intel_hdcp_check_work(struct work_struct *work)
 {
 	struct intel_hdcp *hdcp = container_of(to_delayed_work(work),
@@ -1270,22 +1431,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;
 }
@@ -1302,7 +1474,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] 121+ messages in thread

* [PATCH v10 09/40] drm/i915: Implement HDCP2.2 receiver authentication
  2019-01-31  6:59 [PATCH v10 00/40] drm/i915: Implement HDCP2.2 Ramalingam C
                   ` (7 preceding siblings ...)
  2019-01-31  6:59 ` [PATCH v10 08/40] drm/i915: Enable and Disable of HDCP2.2 Ramalingam C
@ 2019-01-31  6:59 ` Ramalingam C
  2019-02-04 14:20   ` Shankar, Uma
  2019-01-31  6:59 ` [PATCH v10 10/40] drm: helper functions for hdcp2 seq_num to from u32 Ramalingam C
                   ` (33 subsequent siblings)
  42 siblings, 1 reply; 121+ messages in thread
From: Ramalingam C @ 2019-01-31  6:59 UTC (permalink / raw)
  To: intel-gfx, dri-devel, 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.
v9:
  bool is used in struct intel_hdcp [Daniel]
  config_stream_type is redesigned [Daniel]

Signed-off-by: Ramalingam C <ramalingam.c@intel.com>
Reviewed-by: Daniel Vetter <daniel.vetter@ffwll.ch>
---
 drivers/gpu/drm/i915/intel_drv.h  |  34 +++++++
 drivers/gpu/drm/i915/intel_hdcp.c | 197 +++++++++++++++++++++++++++++++++++---
 2 files changed, 216 insertions(+), 15 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index 31c7a4577ca9..e6792304520a 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -393,6 +393,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,
+				  bool is_repeater, u8 type);
 };
 
 struct intel_hdcp {
@@ -420,6 +436,24 @@ struct intel_hdcp {
 	 */
 	u8 content_type;
 	struct hdcp_port_data port_data;
+
+	bool is_paired;
+	bool 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 fbf8b7893bfa..1c81e17dc6c4 100644
--- a/drivers/gpu/drm/i915/intel_hdcp.c
+++ b/drivers/gpu/drm/i915/intel_hdcp.c
@@ -17,6 +17,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)
@@ -853,7 +854,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)
 {
@@ -878,7 +879,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,
@@ -908,9 +909,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);
@@ -933,7 +933,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)
 {
@@ -958,7 +958,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)
 {
@@ -983,7 +983,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)
 {
@@ -1008,9 +1008,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);
@@ -1087,8 +1086,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);
@@ -1137,11 +1135,180 @@ 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;
+
+	/* 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]);
+
+	/*
+	 * 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,
+					      &hdcp->is_paired,
+					      &msgs.no_stored_km, &size);
+	if (ret < 0)
+		return ret;
+
+	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 = 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;
+	}
+
+	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;
+	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 (shim->config_stream_type) {
+		ret = shim->config_stream_type(intel_dig_port,
+					       hdcp->is_repeater,
+					       hdcp->content_type);
+		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

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

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

* [PATCH v10 10/40] drm: helper functions for hdcp2 seq_num to from u32
  2019-01-31  6:59 [PATCH v10 00/40] drm/i915: Implement HDCP2.2 Ramalingam C
                   ` (8 preceding siblings ...)
  2019-01-31  6:59 ` [PATCH v10 09/40] drm/i915: Implement HDCP2.2 receiver authentication Ramalingam C
@ 2019-01-31  6:59 ` Ramalingam C
  2019-02-04 14:20   ` Shankar, Uma
  2019-01-31  6:59 ` [PATCH v10 11/40] drm/i915: Implement HDCP2.2 repeater authentication Ramalingam C
                   ` (32 subsequent siblings)
  42 siblings, 1 reply; 121+ messages in thread
From: Ramalingam C @ 2019-01-31  6:59 UTC (permalink / raw)
  To: intel-gfx, dri-devel, 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.

v2:
  Comment is updated. [Daniel]

Signed-off-by: Ramalingam C <ramalingam.c@intel.com>
Reviewed-by: Daniel Vetter <daniel.vetter@ffwll.ch>
---
 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 d6dfef8cff6a..7260b31af276 100644
--- a/include/drm/drm_hdcp.h
+++ b/include/drm/drm_hdcp.h
@@ -252,4 +252,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))
 
+/*
+ * Helper functions to convert 24bit big endian hdcp sequence number to
+ * host format and back
+ */
+static inline
+u32 drm_hdcp2_seq_num_to_u32(u8 seq_num[HDCP_2_2_SEQ_NUM_LEN])
+{
+	return (u32)(seq_num[2] | seq_num[1] << 8 | seq_num[0] << 16);
+}
+
+static inline
+void drm_hdcp2_u32_to_seq_num(u8 seq_num[HDCP_2_2_SEQ_NUM_LEN], u32 val)
+{
+	seq_num[0] = val >> 16;
+	seq_num[1] = val >> 8;
+	seq_num[2] = val;
+}
+
 #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] 121+ messages in thread

* [PATCH v10 11/40] drm/i915: Implement HDCP2.2 repeater authentication
  2019-01-31  6:59 [PATCH v10 00/40] drm/i915: Implement HDCP2.2 Ramalingam C
                   ` (9 preceding siblings ...)
  2019-01-31  6:59 ` [PATCH v10 10/40] drm: helper functions for hdcp2 seq_num to from u32 Ramalingam C
@ 2019-01-31  6:59 ` Ramalingam C
  2019-02-04 14:21   ` Shankar, Uma
  2019-01-31  6:59 ` [PATCH v10 12/40] drm: HDCP2.2 link check period Ramalingam C
                   ` (31 subsequent siblings)
  42 siblings, 1 reply; 121+ messages in thread
From: Ramalingam C @ 2019-01-31  6:59 UTC (permalink / raw)
  To: intel-gfx, dri-devel, 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]
v9:
  %s/__swab16/cpu_to_be16. [Tomas]

Signed-off-by: Ramalingam C <ramalingam.c@intel.com>
Reviewed-by: Daniel Vetter <daniel.vetter@ffwll.ch>
---
 drivers/gpu/drm/i915/intel_hdcp.c | 125 +++++++++++++++++++++++++++++++++++++-
 1 file changed, 123 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_hdcp.c b/drivers/gpu/drm/i915/intel_hdcp.c
index 1c81e17dc6c4..3b8d3a4b5e6e 100644
--- a/drivers/gpu/drm/i915/intel_hdcp.c
+++ b/drivers/gpu/drm/i915/intel_hdcp.c
@@ -1032,7 +1032,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,
@@ -1061,7 +1061,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)
 {
@@ -1270,6 +1270,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 = 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 */
+	seq_num_v = drm_hdcp2_seq_num_to_u32(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);
@@ -1303,6 +1416,14 @@ static int hdcp2_authenticate_sink(struct intel_connector *connector)
 			return ret;
 	}
 
+	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;
 	ret = hdcp2_authenticate_port(connector);
 	if (ret < 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] 121+ messages in thread

* [PATCH v10 12/40] drm: HDCP2.2 link check period
  2019-01-31  6:59 [PATCH v10 00/40] drm/i915: Implement HDCP2.2 Ramalingam C
                   ` (10 preceding siblings ...)
  2019-01-31  6:59 ` [PATCH v10 11/40] drm/i915: Implement HDCP2.2 repeater authentication Ramalingam C
@ 2019-01-31  6:59 ` Ramalingam C
  2019-02-04 14:24   ` Shankar, Uma
  2019-01-31  6:59 ` [PATCH v10 13/40] drm/i915: Implement HDCP2.2 link integrity check Ramalingam C
                   ` (30 subsequent siblings)
  42 siblings, 1 reply; 121+ messages in thread
From: Ramalingam C @ 2019-01-31  6:59 UTC (permalink / raw)
  To: intel-gfx, dri-devel, daniel.vetter, tomas.winkler, uma.shankar

Time period for HDCP2.2 link check.

Signed-off-by: Ramalingam C <ramalingam.c@intel.com>
Reviewed-by: Daniel Vetter <daniel.vetter@ffwll.ch>
---
 include/drm/drm_hdcp.h | 1 +
 1 file changed, 1 insertion(+)

diff --git a/include/drm/drm_hdcp.h b/include/drm/drm_hdcp.h
index 7260b31af276..d4e98b11b4aa 100644
--- a/include/drm/drm_hdcp.h
+++ b/include/drm/drm_hdcp.h
@@ -13,6 +13,7 @@
 
 /* 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
 
 /* 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 related	[flat|nested] 121+ messages in thread

* [PATCH v10 13/40] drm/i915: Implement HDCP2.2 link integrity check
  2019-01-31  6:59 [PATCH v10 00/40] drm/i915: Implement HDCP2.2 Ramalingam C
                   ` (11 preceding siblings ...)
  2019-01-31  6:59 ` [PATCH v10 12/40] drm: HDCP2.2 link check period Ramalingam C
@ 2019-01-31  6:59 ` Ramalingam C
  2019-02-04 14:28   ` Shankar, Uma
  2019-01-31  6:59 ` [PATCH v10 14/40] drm/i915: Handle HDCP2.2 downstream topology change Ramalingam C
                   ` (29 subsequent siblings)
  42 siblings, 1 reply; 121+ messages in thread
From: Ramalingam C @ 2019-01-31  6:59 UTC (permalink / raw)
  To: intel-gfx, dri-devel, 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]
v9:
  enum check_link_status is defined at intel_drv.h [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  | 10 +++++
 drivers/gpu/drm/i915/intel_hdcp.c | 88 ++++++++++++++++++++++++++++++++++++---
 2 files changed, 93 insertions(+), 5 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index e6792304520a..747fe7361287 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -314,6 +314,13 @@ struct intel_panel {
 
 struct intel_digital_port;
 
+enum check_link_response {
+	HDCP_LINK_PROTECTED	= 0,
+	HDCP_TOPOLOGY_CHANGE,
+	HDCP_LINK_INTEGRITY_FAILURE,
+	HDCP_REAUTH_REQUEST
+};
+
 /*
  * This structure serves as a translation layer between the generic HDCP code
  * and the bus-specific code. What that means is that HDCP over HDMI differs
@@ -409,6 +416,9 @@ struct intel_hdcp_shim {
 	 */
 	int (*config_stream_type)(struct intel_digital_port *intel_dig_port,
 				  bool is_repeater, u8 type);
+
+	/* 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 3b8d3a4b5e6e..3feff921a547 100644
--- a/drivers/gpu/drm/i915/intel_hdcp.c
+++ b/drivers/gpu/drm/i915/intel_hdcp.c
@@ -102,6 +102,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)
 {
@@ -1571,6 +1581,69 @@ 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 == 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 void intel_hdcp_check_work(struct work_struct *work)
 {
 	struct intel_hdcp *hdcp = container_of(to_delayed_work(work),
@@ -1578,7 +1651,10 @@ static void intel_hdcp_check_work(struct work_struct *work)
 					       check_work);
 	struct intel_connector *connector = intel_hdcp_to_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);
 }
@@ -1719,6 +1795,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)
@@ -1730,18 +1807,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);
 	}
-- 
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] 121+ messages in thread

* [PATCH v10 14/40] drm/i915: Handle HDCP2.2 downstream topology change
  2019-01-31  6:59 [PATCH v10 00/40] drm/i915: Implement HDCP2.2 Ramalingam C
                   ` (12 preceding siblings ...)
  2019-01-31  6:59 ` [PATCH v10 13/40] drm/i915: Implement HDCP2.2 link integrity check Ramalingam C
@ 2019-01-31  6:59 ` Ramalingam C
  2019-02-04 14:31   ` Shankar, Uma
  2019-01-31  6:59 ` [PATCH v10 15/40] drm: removing the DP Errata msg and its msg id Ramalingam C
                   ` (28 subsequent siblings)
  42 siblings, 1 reply; 121+ messages in thread
From: Ramalingam C @ 2019-01-31  6:59 UTC (permalink / raw)
  To: intel-gfx, dri-devel, 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 3feff921a547..7ff29fb0aa2f 100644
--- a/drivers/gpu/drm/i915/intel_hdcp.c
+++ b/drivers/gpu/drm/i915/intel_hdcp.c
@@ -1617,8 +1617,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 == 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

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

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

* [PATCH v10 15/40] drm: removing the DP Errata msg and its msg id
  2019-01-31  6:59 [PATCH v10 00/40] drm/i915: Implement HDCP2.2 Ramalingam C
                   ` (13 preceding siblings ...)
  2019-01-31  6:59 ` [PATCH v10 14/40] drm/i915: Handle HDCP2.2 downstream topology change Ramalingam C
@ 2019-01-31  6:59 ` Ramalingam C
  2019-01-31  8:02   ` Daniel Vetter
  2019-02-04 14:35   ` Shankar, Uma
  2019-01-31  6:59 ` [PATCH v10 16/40] drm/i915: Implement the HDCP2.2 support for DP Ramalingam C
                   ` (27 subsequent siblings)
  42 siblings, 2 replies; 121+ messages in thread
From: Ramalingam C @ 2019-01-31  6:59 UTC (permalink / raw)
  To: intel-gfx, dri-devel, daniel.vetter, tomas.winkler, uma.shankar

Since DP ERRATA message is not defined at spec, those structure
definition is removed from drm_hdcp.h

Signed-off-by: Ramalingam C <ramalingam.c@intel.com>
Suggested-by: Daniel Vetter <daniel.vetter@ffwll.ch>
---
 include/drm/drm_hdcp.h | 6 ------
 1 file changed, 6 deletions(-)

diff --git a/include/drm/drm_hdcp.h b/include/drm/drm_hdcp.h
index d4e98b11b4aa..f243408ecf26 100644
--- a/include/drm/drm_hdcp.h
+++ b/include/drm/drm_hdcp.h
@@ -69,7 +69,6 @@
 #define HDCP_2_2_REP_SEND_ACK			15
 #define HDCP_2_2_REP_STREAM_MANAGE		16
 #define HDCP_2_2_REP_STREAM_READY		17
-#define HDCP_2_2_ERRATA_DP_STREAM_TYPE		50
 
 #define HDCP_2_2_RTX_LEN			8
 #define HDCP_2_2_RRX_LEN			8
@@ -220,11 +219,6 @@ struct hdcp2_rep_stream_ready {
 	u8	m_prime[HDCP_2_2_MPRIME_LEN];
 } __packed;
 
-struct hdcp2_dp_errata_stream_type {
-	u8	msg_id;
-	u8	stream_type;
-} __packed;
-
 /* HDCP2.2 TIMEOUTs in mSec */
 #define HDCP_2_2_CERT_TIMEOUT_MS		100
 #define HDCP_2_2_HPRIME_NO_PAIRED_TIMEOUT_MS	1000
-- 
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] 121+ messages in thread

* [PATCH v10 16/40] drm/i915: Implement the HDCP2.2 support for DP
  2019-01-31  6:59 [PATCH v10 00/40] drm/i915: Implement HDCP2.2 Ramalingam C
                   ` (14 preceding siblings ...)
  2019-01-31  6:59 ` [PATCH v10 15/40] drm: removing the DP Errata msg and its msg id Ramalingam C
@ 2019-01-31  6:59 ` Ramalingam C
  2019-02-04 16:02   ` Shankar, Uma
  2019-01-31  6:59 ` [PATCH v10 17/40] drm/i915: Implement the HDCP2.2 support for HDMI Ramalingam C
                   ` (26 subsequent siblings)
  42 siblings, 1 reply; 121+ messages in thread
From: Ramalingam C @ 2019-01-31  6:59 UTC (permalink / raw)
  To: intel-gfx, dri-devel, 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]
v10:
  config_stream_type is redefined [Daniel]
  DP Errata specific defines are moved into intel_dp.c.

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 | 333 ++++++++++++++++++++++++++++++++++++++++
 1 file changed, 333 insertions(+)

diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
index 9ce05819fc11..b13c41220ce0 100644
--- a/drivers/gpu/drm/i915/intel_dp.c
+++ b/drivers/gpu/drm/i915/intel_dp.c
@@ -5843,6 +5843,333 @@ int intel_dp_hdcp_capable(struct intel_digital_port *intel_dig_port,
 	return 0;
 }
 
+struct hdcp2_dp_errata_stream_type {
+	u8	msg_id;
+	u8	stream_type;
+} __packed;
+
+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},
+/* local define to shovel this through the write_2_2 interface */
+#define HDCP_2_2_ERRATA_DP_STREAM_TYPE	50
+		{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,
+				      bool is_repeater, u8 content_type)
+{
+	struct hdcp2_dp_errata_stream_type stream_type_msg;
+
+	if (is_repeater)
+		return 0;
+
+	/*
+	 * 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 = content_type;
+
+	return intel_dp_hdcp2_write_msg(intel_dig_port, &stream_type_msg,
+					sizeof(stream_type_msg));
+}
+
+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 = HDCP_REAUTH_REQUEST;
+	else if (HDCP_2_2_DP_RXSTATUS_LINK_FAILED(rx_status))
+		ret = HDCP_LINK_INTEGRITY_FAILURE;
+	else if (HDCP_2_2_DP_RXSTATUS_READY(rx_status))
+		ret = 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,
@@ -5855,6 +6182,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] 121+ messages in thread

* [PATCH v10 17/40] drm/i915: Implement the HDCP2.2 support for HDMI
  2019-01-31  6:59 [PATCH v10 00/40] drm/i915: Implement HDCP2.2 Ramalingam C
                   ` (15 preceding siblings ...)
  2019-01-31  6:59 ` [PATCH v10 16/40] drm/i915: Implement the HDCP2.2 support for DP Ramalingam C
@ 2019-01-31  6:59 ` Ramalingam C
  2019-02-04 16:03   ` Shankar, Uma
  2019-01-31  6:59 ` [PATCH v10 18/40] drm/i915: CP_IRQ handling for DP HDCP2.2 msgs Ramalingam C
                   ` (25 subsequent siblings)
  42 siblings, 1 reply; 121+ messages in thread
From: Ramalingam C @ 2019-01-31  6:59 UTC (permalink / raw)
  To: intel-gfx, dri-devel, 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 ab376a31cdab..3b4fe7048af9 100644
--- a/drivers/gpu/drm/i915/intel_hdmi.c
+++ b/drivers/gpu/drm/i915/intel_hdmi.c
@@ -1129,6 +1129,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 = HDCP_REAUTH_REQUEST;
+	else if (HDCP_2_2_HDMI_RXSTATUS_READY(rx_status[1]))
+		ret = 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,
@@ -1140,6 +1324,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

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

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

* [PATCH v10 18/40] drm/i915: CP_IRQ handling for DP HDCP2.2 msgs
  2019-01-31  6:59 [PATCH v10 00/40] drm/i915: Implement HDCP2.2 Ramalingam C
                   ` (16 preceding siblings ...)
  2019-01-31  6:59 ` [PATCH v10 17/40] drm/i915: Implement the HDCP2.2 support for HDMI Ramalingam C
@ 2019-01-31  6:59 ` Ramalingam C
  2019-01-31  8:08   ` Daniel Vetter
  2019-01-31  6:59 ` [PATCH v10 19/40] drm/i915: Add HDCP2.2 support for DP connectors Ramalingam C
                   ` (24 subsequent siblings)
  42 siblings, 1 reply; 121+ messages in thread
From: Ramalingam C @ 2019-01-31  6:59 UTC (permalink / raw)
  To: intel-gfx, dri-devel, daniel.vetter, tomas.winkler, uma.shankar

Implements the
	Waitqueue is created to wait for CP_IRQ
	Signaling the CP_IRQ arrival through atomic variable.
	For applicable DP HDCP2.2 msgs read wait for CP_IRQ.

As per HDCP2.2 spec "HDCP Transmitters must process CP_IRQ interrupts
when they are received from HDCP Receivers"

Without CP_IRQ processing, DP HDCP2.2 H_Prime msg was getting corrupted
while reading it based on corresponding status bit. This creates the
random failures in reading the DP HDCP2.2 msgs.

Signed-off-by: Ramalingam C <ramalingam.c@intel.com>
---
 drivers/gpu/drm/i915/intel_dp.c   | 33 +++++++++++++++++++++++++--------
 drivers/gpu/drm/i915/intel_drv.h  |  7 +++++++
 drivers/gpu/drm/i915/intel_hdcp.c |  6 ++++++
 3 files changed, 38 insertions(+), 8 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
index b13c41220ce0..4e36df266ab3 100644
--- a/drivers/gpu/drm/i915/intel_dp.c
+++ b/drivers/gpu/drm/i915/intel_dp.c
@@ -5619,6 +5619,24 @@ void intel_dp_encoder_suspend(struct intel_encoder *intel_encoder)
 		edp_panel_vdd_off_sync(intel_dp);
 }
 
+static void intel_dp_hdcp_wait_for_cp_irq(struct intel_hdcp *hdcp,
+					  int timeout)
+{
+	long ret;
+
+	/* Reinit */
+	atomic_set(&hdcp->cp_irq_recved, 0);
+
+#define C (atomic_read(&hdcp->cp_irq_recved) > 0)
+	ret = wait_event_interruptible_timeout(hdcp->cp_irq_queue, C,
+					       msecs_to_jiffies(timeout));
+
+	if (ret > 0)
+		atomic_set(&hdcp->cp_irq_recved, 0);
+	else if (!ret)
+		DRM_DEBUG_KMS("Timedout at waiting for CP_IRQ\n");
+}
+
 static
 int intel_dp_hdcp_write_an_aksv(struct intel_digital_port *intel_dig_port,
 				u8 *an)
@@ -5963,14 +5981,13 @@ intel_dp_hdcp2_wait_for_msg(struct intel_digital_port *intel_dig_port,
 		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);
-
+		/*
+		 * Ignoring the return of the intel_dp_hdcp_wait_for_cp_irq,
+		 * Just to detect the msg availability before failing it.
+		 */
+		intel_dp_hdcp_wait_for_cp_irq(hdcp, timeout);
+		ret = hdcp2_detect_msg_availability(intel_dig_port,
+						    msg_id, &msg_ready);
 		if (!msg_ready)
 			ret = -ETIMEDOUT;
 	}
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index 747fe7361287..1901d12bacc4 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -464,6 +464,13 @@ struct intel_hdcp {
 	 * over re-Auth has to be triggered.
 	 */
 	u32 seq_num_m;
+
+	/*
+	 * Work queue to signal the CP_IRQ. Used for the waiters to read the
+	 * available information from HDCP DP sink.
+	 */
+	wait_queue_head_t cp_irq_queue;
+	atomic_t cp_irq_recved;
 };
 
 struct intel_connector {
diff --git a/drivers/gpu/drm/i915/intel_hdcp.c b/drivers/gpu/drm/i915/intel_hdcp.c
index 7ff29fb0aa2f..f38feeadb363 100644
--- a/drivers/gpu/drm/i915/intel_hdcp.c
+++ b/drivers/gpu/drm/i915/intel_hdcp.c
@@ -1805,6 +1805,9 @@ int intel_hdcp_init(struct intel_connector *connector,
 	if (hdcp2_supported)
 		intel_hdcp2_init(connector);
 
+	atomic_set(&hdcp->cp_irq_recved, 0);
+	init_waitqueue_head(&hdcp->cp_irq_queue);
+
 	return 0;
 }
 
@@ -1908,6 +1911,9 @@ void intel_hdcp_handle_cp_irq(struct intel_connector *connector)
 	if (!hdcp->shim)
 		return;
 
+	atomic_set(&connector->hdcp.cp_irq_recved, 1);
+	wake_up_all(&connector->hdcp.cp_irq_queue);
+
 	/*
 	 * CP_IRQ could be triggered due to 1. HDCP2.2 auth msgs availability,
 	 * 2. link failure and 3. repeater reauth request. At present we dont
-- 
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] 121+ messages in thread

* [PATCH v10 19/40] drm/i915: Add HDCP2.2 support for DP connectors
  2019-01-31  6:59 [PATCH v10 00/40] drm/i915: Implement HDCP2.2 Ramalingam C
                   ` (17 preceding siblings ...)
  2019-01-31  6:59 ` [PATCH v10 18/40] drm/i915: CP_IRQ handling for DP HDCP2.2 msgs Ramalingam C
@ 2019-01-31  6:59 ` Ramalingam C
  2019-02-04 16:08   ` Winkler, Tomas
  2019-01-31  6:59 ` [PATCH v10 20/40] drm/i915: Add HDCP2.2 support for HDMI connectors Ramalingam C
                   ` (23 subsequent siblings)
  42 siblings, 1 reply; 121+ messages in thread
From: Ramalingam C @ 2019-01-31  6:59 UTC (permalink / raw)
  To: intel-gfx, dri-devel, 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 4e36df266ab3..88c889770517 100644
--- a/drivers/gpu/drm/i915/intel_dp.c
+++ b/drivers/gpu/drm/i915/intel_dp.c
@@ -7301,7 +7301,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] 121+ messages in thread

* [PATCH v10 20/40] drm/i915: Add HDCP2.2 support for HDMI connectors
  2019-01-31  6:59 [PATCH v10 00/40] drm/i915: Implement HDCP2.2 Ramalingam C
                   ` (18 preceding siblings ...)
  2019-01-31  6:59 ` [PATCH v10 19/40] drm/i915: Add HDCP2.2 support for DP connectors Ramalingam C
@ 2019-01-31  6:59 ` Ramalingam C
  2019-02-04 16:04   ` Winkler, Tomas
  2019-01-31  6:59 ` [PATCH v10 21/40] mei: bus: whitelist hdcp client Ramalingam C
                   ` (22 subsequent siblings)
  42 siblings, 1 reply; 121+ messages in thread
From: Ramalingam C @ 2019-01-31  6:59 UTC (permalink / raw)
  To: intel-gfx, dri-devel, 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 3b4fe7048af9..2c4bf6d0c39f 100644
--- a/drivers/gpu/drm/i915/intel_hdmi.c
+++ b/drivers/gpu/drm/i915/intel_hdmi.c
@@ -2621,7 +2621,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] 121+ messages in thread

* [PATCH v10 21/40] mei: bus: whitelist hdcp client
  2019-01-31  6:59 [PATCH v10 00/40] drm/i915: Implement HDCP2.2 Ramalingam C
                   ` (19 preceding siblings ...)
  2019-01-31  6:59 ` [PATCH v10 20/40] drm/i915: Add HDCP2.2 support for HDMI connectors Ramalingam C
@ 2019-01-31  6:59 ` Ramalingam C
  2019-01-31  6:59 ` [PATCH v10 22/40] mei: bus: export to_mei_cl_device for mei client device drivers Ramalingam C
                   ` (21 subsequent siblings)
  42 siblings, 0 replies; 121+ messages in thread
From: Ramalingam C @ 2019-01-31  6:59 UTC (permalink / raw)
  To: intel-gfx, dri-devel, 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

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

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

* [PATCH v10 22/40] mei: bus: export to_mei_cl_device for mei client device drivers
  2019-01-31  6:59 [PATCH v10 00/40] drm/i915: Implement HDCP2.2 Ramalingam C
                   ` (20 preceding siblings ...)
  2019-01-31  6:59 ` [PATCH v10 21/40] mei: bus: whitelist hdcp client Ramalingam C
@ 2019-01-31  6:59 ` Ramalingam C
  2019-01-31  6:59 ` [PATCH v10 23/40] misc/mei/hdcp: Client driver for HDCP application Ramalingam C
                   ` (20 subsequent siblings)
  42 siblings, 0 replies; 121+ messages in thread
From: Ramalingam C @ 2019-01-31  6:59 UTC (permalink / raw)
  To: intel-gfx, dri-devel, 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

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

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

* [PATCH v10 23/40] misc/mei/hdcp: Client driver for HDCP application
  2019-01-31  6:59 [PATCH v10 00/40] drm/i915: Implement HDCP2.2 Ramalingam C
                   ` (21 preceding siblings ...)
  2019-01-31  6:59 ` [PATCH v10 22/40] mei: bus: export to_mei_cl_device for mei client device drivers Ramalingam C
@ 2019-01-31  6:59 ` Ramalingam C
  2019-02-05 12:33   ` Winkler, Tomas
  2019-01-31  6:59 ` [PATCH v10 24/40] misc/mei/hdcp: Define ME FW interface for HDCP2.2 Ramalingam C
                   ` (19 subsequent siblings)
  42 siblings, 1 reply; 121+ messages in thread
From: Ramalingam C @ 2019-01-31  6:59 UTC (permalink / raw)
  To: intel-gfx, dri-devel, 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 d9215fc4e499..8c2d9565a4cb 100644
--- a/drivers/misc/mei/Makefile
+++ b/drivers/misc/mei/Makefile
@@ -24,3 +24,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..b2de072aa0de
--- /dev/null
+++ b/drivers/misc/mei/hdcp/Makefile
@@ -0,0 +1,7 @@
+# SPDX-License-Identifier: GPL-2.0+
+#
+# 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..ca5010ad7dd7
--- /dev/null
+++ b/drivers/misc/mei/hdcp/mei_hdcp.c
@@ -0,0 +1,65 @@
+// SPDX-License-Identifier: (GPL-2.0+)
+/*
+ * 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("GPL");
+MODULE_DESCRIPTION("MEI HDCP");
-- 
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] 121+ messages in thread

* [PATCH v10 24/40] misc/mei/hdcp: Define ME FW interface for HDCP2.2
  2019-01-31  6:59 [PATCH v10 00/40] drm/i915: Implement HDCP2.2 Ramalingam C
                   ` (22 preceding siblings ...)
  2019-01-31  6:59 ` [PATCH v10 23/40] misc/mei/hdcp: Client driver for HDCP application Ramalingam C
@ 2019-01-31  6:59 ` Ramalingam C
  2019-02-04 16:07   ` Shankar, Uma
  2019-01-31  6:59 ` [PATCH v10 25/40] misc/mei/hdcp: Initiate Wired HDCP2.2 Tx Session Ramalingam C
                   ` (18 subsequent siblings)
  42 siblings, 1 reply; 121+ messages in thread
From: Ramalingam C @ 2019-01-31  6:59 UTC (permalink / raw)
  To: intel-gfx, dri-devel, 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..582a7e27ae29
--- /dev/null
+++ b/drivers/misc/mei/hdcp/mei_hdcp.h
@@ -0,0 +1,366 @@
+/* SPDX-License-Identifier: (GPL-2.0+) */
+/*
+ * 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

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

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

* [PATCH v10 25/40] misc/mei/hdcp: Initiate Wired HDCP2.2 Tx Session
  2019-01-31  6:59 [PATCH v10 00/40] drm/i915: Implement HDCP2.2 Ramalingam C
                   ` (23 preceding siblings ...)
  2019-01-31  6:59 ` [PATCH v10 24/40] misc/mei/hdcp: Define ME FW interface for HDCP2.2 Ramalingam C
@ 2019-01-31  6:59 ` Ramalingam C
  2019-02-04 16:09   ` Shankar, Uma
  2019-01-31  6:59 ` [PATCH v10 26/40] misc/mei/hdcp: Verify Receiver Cert and prepare km Ramalingam C
                   ` (17 subsequent siblings)
  42 siblings, 1 reply; 121+ messages in thread
From: Ramalingam C @ 2019-01-31  6:59 UTC (permalink / raw)
  To: intel-gfx, dri-devel, 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 | 82 ++++++++++++++++++++++++++++++++++++++++
 drivers/misc/mei/hdcp/mei_hdcp.h | 28 ++++++++++++++
 2 files changed, 110 insertions(+)

diff --git a/drivers/misc/mei/hdcp/mei_hdcp.c b/drivers/misc/mei/hdcp/mei_hdcp.c
index ca5010ad7dd7..534d29c8ee86 100644
--- a/drivers/misc/mei/hdcp/mei_hdcp.c
+++ b/drivers/misc/mei/hdcp/mei_hdcp.c
@@ -23,6 +23,88 @@
 #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 <drm/i915_mei_hdcp_interface.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 582a7e27ae29..f831db3cbd54 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] 121+ messages in thread

* [PATCH v10 26/40] misc/mei/hdcp: Verify Receiver Cert and prepare km
  2019-01-31  6:59 [PATCH v10 00/40] drm/i915: Implement HDCP2.2 Ramalingam C
                   ` (24 preceding siblings ...)
  2019-01-31  6:59 ` [PATCH v10 25/40] misc/mei/hdcp: Initiate Wired HDCP2.2 Tx Session Ramalingam C
@ 2019-01-31  6:59 ` Ramalingam C
  2019-02-04 16:10   ` Shankar, Uma
  2019-01-31  6:59 ` [PATCH v10 27/40] misc/mei/hdcp: Verify H_prime Ramalingam C
                   ` (16 subsequent siblings)
  42 siblings, 1 reply; 121+ messages in thread
From: Ramalingam C @ 2019-01-31  6:59 UTC (permalink / raw)
  To: intel-gfx, dri-devel, 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 534d29c8ee86..24665fff640d 100644
--- a/drivers/misc/mei/hdcp/mei_hdcp.c
+++ b/drivers/misc/mei/hdcp/mei_hdcp.c
@@ -90,11 +90,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

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

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

* [PATCH v10 27/40] misc/mei/hdcp: Verify H_prime
  2019-01-31  6:59 [PATCH v10 00/40] drm/i915: Implement HDCP2.2 Ramalingam C
                   ` (25 preceding siblings ...)
  2019-01-31  6:59 ` [PATCH v10 26/40] misc/mei/hdcp: Verify Receiver Cert and prepare km Ramalingam C
@ 2019-01-31  6:59 ` Ramalingam C
  2019-02-04 16:11   ` Shankar, Uma
  2019-01-31  6:59 ` [PATCH v10 28/40] misc/mei/hdcp: Store the HDCP Pairing info Ramalingam C
                   ` (15 subsequent siblings)
  42 siblings, 1 reply; 121+ messages in thread
From: Ramalingam C @ 2019-01-31  6:59 UTC (permalink / raw)
  To: intel-gfx, dri-devel, 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 24665fff640d..74219e1487d3 100644
--- a/drivers/misc/mei/hdcp/mei_hdcp.c
+++ b/drivers/misc/mei/hdcp/mei_hdcp.c
@@ -169,12 +169,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

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

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

* [PATCH v10 28/40] misc/mei/hdcp: Store the HDCP Pairing info
  2019-01-31  6:59 [PATCH v10 00/40] drm/i915: Implement HDCP2.2 Ramalingam C
                   ` (26 preceding siblings ...)
  2019-01-31  6:59 ` [PATCH v10 27/40] misc/mei/hdcp: Verify H_prime Ramalingam C
@ 2019-01-31  6:59 ` Ramalingam C
  2019-02-04 16:13   ` Shankar, Uma
  2019-01-31  6:59 ` [PATCH v10 29/40] misc/mei/hdcp: Initiate Locality check Ramalingam C
                   ` (14 subsequent siblings)
  42 siblings, 1 reply; 121+ messages in thread
From: Ramalingam C @ 2019-01-31  6:59 UTC (permalink / raw)
  To: intel-gfx, dri-devel, 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 74219e1487d3..e8396c723ab0 100644
--- a/drivers/misc/mei/hdcp/mei_hdcp.c
+++ b/drivers/misc/mei/hdcp/mei_hdcp.c
@@ -224,13 +224,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] 121+ messages in thread

* [PATCH v10 29/40] misc/mei/hdcp: Initiate Locality check
  2019-01-31  6:59 [PATCH v10 00/40] drm/i915: Implement HDCP2.2 Ramalingam C
                   ` (27 preceding siblings ...)
  2019-01-31  6:59 ` [PATCH v10 28/40] misc/mei/hdcp: Store the HDCP Pairing info Ramalingam C
@ 2019-01-31  6:59 ` Ramalingam C
  2019-02-04 16:16   ` Shankar, Uma
  2019-01-31  6:59 ` [PATCH v10 30/40] misc/mei/hdcp: Verify L_prime Ramalingam C
                   ` (13 subsequent siblings)
  42 siblings, 1 reply; 121+ messages in thread
From: Ramalingam C @ 2019-01-31  6:59 UTC (permalink / raw)
  To: intel-gfx, dri-devel, 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 e8396c723ab0..412a33e29d7d 100644
--- a/drivers/misc/mei/hdcp/mei_hdcp.c
+++ b/drivers/misc/mei/hdcp/mei_hdcp.c
@@ -282,6 +282,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,
@@ -289,7 +343,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

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

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

* [PATCH v10 30/40] misc/mei/hdcp: Verify L_prime
  2019-01-31  6:59 [PATCH v10 00/40] drm/i915: Implement HDCP2.2 Ramalingam C
                   ` (28 preceding siblings ...)
  2019-01-31  6:59 ` [PATCH v10 29/40] misc/mei/hdcp: Initiate Locality check Ramalingam C
@ 2019-01-31  6:59 ` Ramalingam C
  2019-02-04 16:16   ` Shankar, Uma
  2019-01-31  6:59 ` [PATCH v10 31/40] misc/mei/hdcp: Prepare Session Key Ramalingam C
                   ` (12 subsequent siblings)
  42 siblings, 1 reply; 121+ messages in thread
From: Ramalingam C @ 2019-01-31  6:59 UTC (permalink / raw)
  To: intel-gfx, dri-devel, 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 412a33e29d7d..3d7767d944dc 100644
--- a/drivers/misc/mei/hdcp/mei_hdcp.c
+++ b/drivers/misc/mei/hdcp/mei_hdcp.c
@@ -336,6 +336,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,
@@ -344,7 +401,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

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

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

* [PATCH v10 31/40] misc/mei/hdcp: Prepare Session Key
  2019-01-31  6:59 [PATCH v10 00/40] drm/i915: Implement HDCP2.2 Ramalingam C
                   ` (29 preceding siblings ...)
  2019-01-31  6:59 ` [PATCH v10 30/40] misc/mei/hdcp: Verify L_prime Ramalingam C
@ 2019-01-31  6:59 ` Ramalingam C
  2019-02-04 16:17   ` Shankar, Uma
  2019-01-31  6:59 ` [PATCH v10 32/40] misc/mei/hdcp: Repeater topology verification and ack Ramalingam C
                   ` (11 subsequent siblings)
  42 siblings, 1 reply; 121+ messages in thread
From: Ramalingam C @ 2019-01-31  6:59 UTC (permalink / raw)
  To: intel-gfx, dri-devel, 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 3d7767d944dc..2be7b6b949c2 100644
--- a/drivers/misc/mei/hdcp/mei_hdcp.c
+++ b/drivers/misc/mei/hdcp/mei_hdcp.c
@@ -393,6 +393,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,
@@ -402,7 +458,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

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

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

* [PATCH v10 32/40] misc/mei/hdcp: Repeater topology verification and ack
  2019-01-31  6:59 [PATCH v10 00/40] drm/i915: Implement HDCP2.2 Ramalingam C
                   ` (30 preceding siblings ...)
  2019-01-31  6:59 ` [PATCH v10 31/40] misc/mei/hdcp: Prepare Session Key Ramalingam C
@ 2019-01-31  6:59 ` Ramalingam C
  2019-02-04 16:17   ` Shankar, Uma
  2019-01-31  6:59 ` [PATCH v10 33/40] misc/mei/hdcp: Verify M_prime Ramalingam C
                   ` (10 subsequent siblings)
  42 siblings, 1 reply; 121+ messages in thread
From: Ramalingam C @ 2019-01-31  6:59 UTC (permalink / raw)
  To: intel-gfx, dri-devel, 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 2be7b6b949c2..c157c18371b4 100644
--- a/drivers/misc/mei/hdcp/mei_hdcp.c
+++ b/drivers/misc/mei/hdcp/mei_hdcp.c
@@ -449,6 +449,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,
@@ -459,7 +533,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] 121+ messages in thread

* [PATCH v10 33/40] misc/mei/hdcp: Verify M_prime
  2019-01-31  6:59 [PATCH v10 00/40] drm/i915: Implement HDCP2.2 Ramalingam C
                   ` (31 preceding siblings ...)
  2019-01-31  6:59 ` [PATCH v10 32/40] misc/mei/hdcp: Repeater topology verification and ack Ramalingam C
@ 2019-01-31  6:59 ` Ramalingam C
  2019-02-04 16:18   ` Shankar, Uma
  2019-01-31  6:59 ` [PATCH v10 34/40] misc/mei/hdcp: Enabling the HDCP authentication Ramalingam C
                   ` (9 subsequent siblings)
  42 siblings, 1 reply; 121+ messages in thread
From: Ramalingam C @ 2019-01-31  6:59 UTC (permalink / raw)
  To: intel-gfx, dri-devel, 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 c157c18371b4..91f7b08d1df1 100644
--- a/drivers/misc/mei/hdcp/mei_hdcp.c
+++ b/drivers/misc/mei/hdcp/mei_hdcp.c
@@ -523,6 +523,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,
@@ -534,7 +598,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

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

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

* [PATCH v10 34/40] misc/mei/hdcp: Enabling the HDCP authentication
  2019-01-31  6:59 [PATCH v10 00/40] drm/i915: Implement HDCP2.2 Ramalingam C
                   ` (32 preceding siblings ...)
  2019-01-31  6:59 ` [PATCH v10 33/40] misc/mei/hdcp: Verify M_prime Ramalingam C
@ 2019-01-31  6:59 ` Ramalingam C
  2019-02-04 16:19   ` Shankar, Uma
  2019-01-31  6:59 ` [PATCH v10 35/40] misc/mei/hdcp: Closing wired HDCP2.2 Tx Session Ramalingam C
                   ` (8 subsequent siblings)
  42 siblings, 1 reply; 121+ messages in thread
From: Ramalingam C @ 2019-01-31  6:59 UTC (permalink / raw)
  To: intel-gfx, dri-devel, 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 91f7b08d1df1..5303c729612b 100644
--- a/drivers/misc/mei/hdcp/mei_hdcp.c
+++ b/drivers/misc/mei/hdcp/mei_hdcp.c
@@ -587,6 +587,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,
@@ -599,7 +651,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

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

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

* [PATCH v10 35/40] misc/mei/hdcp: Closing wired HDCP2.2 Tx Session
  2019-01-31  6:59 [PATCH v10 00/40] drm/i915: Implement HDCP2.2 Ramalingam C
                   ` (33 preceding siblings ...)
  2019-01-31  6:59 ` [PATCH v10 34/40] misc/mei/hdcp: Enabling the HDCP authentication Ramalingam C
@ 2019-01-31  6:59 ` Ramalingam C
  2019-02-04 16:20   ` Shankar, Uma
  2019-01-31  6:59 ` [PATCH v10 36/40] misc/mei/hdcp: Component framework for I915 Interface Ramalingam C
                   ` (7 subsequent siblings)
  42 siblings, 1 reply; 121+ messages in thread
From: Ramalingam C @ 2019-01-31  6:59 UTC (permalink / raw)
  To: intel-gfx, dri-devel, 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 5303c729612b..edfc70fb0617 100644
--- a/drivers/misc/mei/hdcp/mei_hdcp.c
+++ b/drivers/misc/mei/hdcp/mei_hdcp.c
@@ -639,6 +639,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,
@@ -652,7 +705,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

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

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

* [PATCH v10 36/40] misc/mei/hdcp: Component framework for I915 Interface
  2019-01-31  6:59 [PATCH v10 00/40] drm/i915: Implement HDCP2.2 Ramalingam C
                   ` (34 preceding siblings ...)
  2019-01-31  6:59 ` [PATCH v10 35/40] misc/mei/hdcp: Closing wired HDCP2.2 Tx Session Ramalingam C
@ 2019-01-31  6:59 ` Ramalingam C
  2019-01-31  8:23   ` Daniel Vetter
  2019-02-04 16:27   ` Shankar, Uma
  2019-01-31  6:59 ` [PATCH v10 37/40] drm/i915: Commit CP without modeset Ramalingam C
                   ` (6 subsequent siblings)
  42 siblings, 2 replies; 121+ messages in thread
From: Ramalingam C @ 2019-01-31  6:59 UTC (permalink / raw)
  To: intel-gfx, dri-devel, 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.
v8:
  master comp is added to be matched with i915 subcomponent [daniel]

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

diff --git a/drivers/misc/mei/hdcp/mei_hdcp.c b/drivers/misc/mei/hdcp/mei_hdcp.c
index edfc70fb0617..be2ce12ca460 100644
--- a/drivers/misc/mei/hdcp/mei_hdcp.c
+++ b/drivers/misc/mei/hdcp/mei_hdcp.c
@@ -23,6 +23,7 @@
 #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 <drm/i915_mei_hdcp_interface.h>
@@ -692,8 +693,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,
@@ -708,20 +708,106 @@ struct i915_hdcp_component_ops mei_hdcp_ops = {
 	.close_hdcp_session = mei_close_hdcp_session,
 };
 
+static int mei_component_master_bind(struct device *dev)
+{
+	struct mei_cl_device *cldev = to_mei_cl_device(dev);
+	struct mei_hdcp_drv_data *drv_data = mei_cldev_get_drvdata(cldev);
+	int ret;
+
+	dev_info(dev, "%s\n", __func__);
+	drv_data->comp_master->ops = &mei_hdcp_ops;
+	drv_data->comp_master->mei_dev = dev;
+	ret = component_bind_all(dev, drv_data->comp_master);
+	if (ret < 0)
+		return ret;
+
+	return 0;
+}
+
+static void mei_component_master_unbind(struct device *dev)
+{
+	struct mei_cl_device *cldev = to_mei_cl_device(dev);
+	struct mei_hdcp_drv_data *drv_data = mei_cldev_get_drvdata(cldev);
+
+	dev_info(dev, "%s\n", __func__);
+	component_unbind_all(dev, drv_data->comp_master);
+}
+
+static const struct component_master_ops mei_component_master_ops = {
+	.bind = mei_component_master_bind,
+	.unbind = mei_component_master_unbind,
+};
+
+static int mei_hdcp_component_match(struct device *dev, int subcomponent,
+				    void *data)
+{
+	return !strcmp(dev->driver->name, "i915") &&
+	       subcomponent == I915_COMPONENT_HDCP;
+}
+
 static int mei_hdcp_probe(struct mei_cl_device *cldev,
 			  const struct mei_cl_device_id *id)
 {
+	struct mei_hdcp_drv_data *drv_data;
 	int ret;
 
 	ret = mei_cldev_enable(cldev);
 	if (ret < 0)
 		dev_err(&cldev->dev, "mei_cldev_enable Failed. %d\n", ret);
 
+	drv_data = kzalloc(sizeof(*drv_data), GFP_KERNEL);
+	if (!drv_data) {
+		ret = -ENOMEM;
+		goto drv_data_exit;
+	}
+
+	drv_data->comp_master = kzalloc(sizeof(*drv_data->comp_master),
+					GFP_KERNEL);
+	if (!drv_data->comp_master) {
+		ret = -ENOMEM;
+		goto comp_master_exit;
+	}
+
+	drv_data->master_match = NULL;
+	component_match_add_typed(&cldev->dev, &drv_data->master_match,
+				  mei_hdcp_component_match,
+				  drv_data->comp_master);
+	if (IS_ERR_OR_NULL(drv_data->master_match)) {
+		ret = -ENOMEM;
+		goto match_add_exit;
+	}
+
+	mei_cldev_set_drvdata(cldev, drv_data);
+	ret = component_master_add_with_match(&cldev->dev,
+					      &mei_component_master_ops,
+					      drv_data->master_match);
+	if (ret < 0) {
+		dev_err(&cldev->dev, "Master comp add failed %d\n", ret);
+		mei_cldev_set_drvdata(cldev, NULL);
+		goto match_add_exit;
+	}
+
+	return 0;
+
+match_add_exit:
+	kfree(drv_data->comp_master);
+comp_master_exit:
+	kfree(drv_data);
+drv_data_exit:
+	mei_cldev_disable(cldev);
+
 	return ret;
 }
 
 static int mei_hdcp_remove(struct mei_cl_device *cldev)
 {
+	struct mei_hdcp_drv_data *drv_data = mei_cldev_get_drvdata(cldev);
+
+	component_master_del(&cldev->dev, &mei_component_master_ops);
+	kfree(drv_data->comp_master);
+	kfree(drv_data);
+	mei_cldev_set_drvdata(cldev, NULL);
+
 	return mei_cldev_disable(cldev);
 }
 
diff --git a/drivers/misc/mei/hdcp/mei_hdcp.h b/drivers/misc/mei/hdcp/mei_hdcp.h
index f831db3cbd54..5c872a57ba11 100644
--- a/drivers/misc/mei/hdcp/mei_hdcp.h
+++ b/drivers/misc/mei/hdcp/mei_hdcp.h
@@ -363,6 +363,11 @@ struct wired_cmd_repeater_auth_stream_req_out {
 	struct hdcp_port_id	port;
 } __packed;
 
+struct mei_hdcp_drv_data {
+	struct i915_hdcp_comp_master *comp_master;
+	struct component_match *master_match;
+};
+
 enum mei_hdcp_ddi {
 	MEI_DDI_INVALID_PORT = 0x0,
 
-- 
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] 121+ messages in thread

* [PATCH v10 37/40] drm/i915: Commit CP without modeset
  2019-01-31  6:59 [PATCH v10 00/40] drm/i915: Implement HDCP2.2 Ramalingam C
                   ` (35 preceding siblings ...)
  2019-01-31  6:59 ` [PATCH v10 36/40] misc/mei/hdcp: Component framework for I915 Interface Ramalingam C
@ 2019-01-31  6:59 ` Ramalingam C
  2019-01-31  8:32   ` Daniel Vetter
  2019-01-31  6:59 ` [PATCH v10 38/40] drm/i915: Fix KBL HDCP2.2 encrypt status signalling Ramalingam C
                   ` (5 subsequent siblings)
  42 siblings, 1 reply; 121+ messages in thread
From: Ramalingam C @ 2019-01-31  6:59 UTC (permalink / raw)
  To: intel-gfx, dri-devel, 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 ca705546a0ab..9cb03c1b0abc 100644
--- a/drivers/gpu/drm/i915/intel_ddi.c
+++ b/drivers/gpu/drm/i915/intel_ddi.c
@@ -3495,11 +3495,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,
@@ -3542,8 +3537,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 a025efb1d7c6..9b964dabb57c 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -13034,6 +13034,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] = {};
@@ -13128,9 +13130,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 1901d12bacc4..e6b6e920ab01 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -2129,6 +2129,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 f38feeadb363..ef127dc7a241 100644
--- a/drivers/gpu/drm/i915/intel_hdcp.c
+++ b/drivers/gpu/drm/i915/intel_hdcp.c
@@ -1876,7 +1876,6 @@ void intel_hdcp_atomic_check(struct drm_connector *connector,
 {
 	u64 old_cp = old_state->content_protection;
 	u64 new_cp = new_state->content_protection;
-	struct drm_crtc_state *crtc_state;
 
 	if (!new_state->crtc) {
 		/*
@@ -1897,10 +1896,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

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

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

* [PATCH v10 38/40] drm/i915: Fix KBL HDCP2.2 encrypt status signalling
  2019-01-31  6:59 [PATCH v10 00/40] drm/i915: Implement HDCP2.2 Ramalingam C
                   ` (36 preceding siblings ...)
  2019-01-31  6:59 ` [PATCH v10 37/40] drm/i915: Commit CP without modeset Ramalingam C
@ 2019-01-31  6:59 ` Ramalingam C
  2019-02-04 15:32   ` C, Ramalingam
  2019-02-04 16:35   ` Shankar, Uma
  2019-01-31  6:59 ` [PATCH v10 39/40] FOR_TEST: i915/Kconfig: Select mei_hdcp by I915 Ramalingam C
                   ` (4 subsequent siblings)
  42 siblings, 2 replies; 121+ messages in thread
From: Ramalingam C @ 2019-01-31  6:59 UTC (permalink / raw)
  To: intel-gfx, dri-devel, 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.

v2:
  WA is moved into the toggle_signalling [Daniel]

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

diff --git a/drivers/gpu/drm/i915/intel_hdmi.c b/drivers/gpu/drm/i915/intel_hdmi.c
index 2c4bf6d0c39f..ae20288f7bbf 100644
--- a/drivers/gpu/drm/i915/intel_hdmi.c
+++ b/drivers/gpu/drm/i915/intel_hdmi.c
@@ -1083,10 +1083,44 @@ int intel_hdmi_hdcp_read_v_prime_part(struct intel_digital_port *intel_dig_port,
 	return ret;
 }
 
+static int 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 drm_crtc *crtc = connector->base.state->crtc;
+	struct intel_crtc *intel_crtc = container_of(crtc,
+						     struct intel_crtc, base);
+	u32 scanline;
+	int ret;
+
+	for (;;) {
+		scanline = I915_READ(PIPEDSL(intel_crtc->pipe));
+		if (scanline > 100 && scanline < 200)
+			break;
+		usleep_range(25, 50);
+	}
+
+	ret = intel_ddi_toggle_hdcp_signalling(&intel_dig_port->base, false);
+	if (ret) {
+		DRM_ERROR("Disable HDCP signalling failed (%d)\n", ret);
+		return ret;
+	}
+	ret = intel_ddi_toggle_hdcp_signalling(&intel_dig_port->base, true);
+	if (ret) {
+		DRM_ERROR("Enable HDCP signalling failed (%d)\n", ret);
+		return ret;
+	}
+
+	return 0;
+}
+
 static
 int intel_hdmi_hdcp_toggle_signalling(struct intel_digital_port *intel_dig_port,
 				      bool enable)
 {
+	struct intel_hdmi *hdmi = &intel_dig_port->hdmi;
+	struct intel_connector *connector = hdmi->attached_connector;
+	struct drm_i915_private *dev_priv = to_i915(connector->base.dev);
 	int ret;
 
 	if (!enable)
@@ -1098,6 +1132,14 @@ int intel_hdmi_hdcp_toggle_signalling(struct intel_digital_port *intel_dig_port,
 			  enable ? "Enable" : "Disable", ret);
 		return ret;
 	}
+
+	/*
+	 * WA: To fix incorrect positioning of the window of
+	 * opportunity and enc_en signalling in KABYLAKE.
+	 */
+	if (IS_KABYLAKE(dev_priv) && enable)
+		return kbl_repositioning_enc_en_signal(connector);
+
 	return 0;
 }
 
-- 
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] 121+ messages in thread

* [PATCH v10 39/40] FOR_TEST: i915/Kconfig: Select mei_hdcp by I915
  2019-01-31  6:59 [PATCH v10 00/40] drm/i915: Implement HDCP2.2 Ramalingam C
                   ` (37 preceding siblings ...)
  2019-01-31  6:59 ` [PATCH v10 38/40] drm/i915: Fix KBL HDCP2.2 encrypt status signalling Ramalingam C
@ 2019-01-31  6:59 ` Ramalingam C
  2019-01-31  6:59 ` [PATCH v10 40/40] FOR_TESTING_ONLY: debugfs: Excluding the LSPCon for HDCP1.4 Ramalingam C
                   ` (3 subsequent siblings)
  42 siblings, 0 replies; 121+ messages in thread
From: Ramalingam C @ 2019-01-31  6:59 UTC (permalink / raw)
  To: intel-gfx, dri-devel, 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

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

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

* [PATCH v10 40/40] FOR_TESTING_ONLY: debugfs: Excluding the LSPCon for HDCP1.4
  2019-01-31  6:59 [PATCH v10 00/40] drm/i915: Implement HDCP2.2 Ramalingam C
                   ` (38 preceding siblings ...)
  2019-01-31  6:59 ` [PATCH v10 39/40] FOR_TEST: i915/Kconfig: Select mei_hdcp by I915 Ramalingam C
@ 2019-01-31  6:59 ` Ramalingam C
  2019-01-31  7:38 ` ✗ Fi.CI.CHECKPATCH: warning for drm/i915: Implement HDCP2.2 (rev13) Patchwork
                   ` (2 subsequent siblings)
  42 siblings, 0 replies; 121+ messages in thread
From: Ramalingam C @ 2019-01-31  6:59 UTC (permalink / raw)
  To: intel-gfx, dri-devel, 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 fa2c226fc779..4935448891be 100644
--- a/drivers/gpu/drm/i915/i915_debugfs.c
+++ b/drivers/gpu/drm/i915/i915_debugfs.c
@@ -4794,6 +4794,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;
@@ -4804,8 +4807,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] 121+ messages in thread

* ✗ Fi.CI.CHECKPATCH: warning for drm/i915: Implement HDCP2.2 (rev13)
  2019-01-31  6:59 [PATCH v10 00/40] drm/i915: Implement HDCP2.2 Ramalingam C
                   ` (39 preceding siblings ...)
  2019-01-31  6:59 ` [PATCH v10 40/40] FOR_TESTING_ONLY: debugfs: Excluding the LSPCon for HDCP1.4 Ramalingam C
@ 2019-01-31  7:38 ` Patchwork
  2019-01-31  8:16 ` ✓ Fi.CI.BAT: success " Patchwork
  2019-01-31 18:42 ` ✓ Fi.CI.IGT: " Patchwork
  42 siblings, 0 replies; 121+ messages in thread
From: Patchwork @ 2019-01-31  7:38 UTC (permalink / raw)
  To: Ramalingam C; +Cc: intel-gfx

== Series Details ==

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

== Summary ==

$ dim checkpatch origin/drm-tip
7b8109241bdc components: multiple components for a device
-:33: WARNING:FUNCTION_ARGUMENTS: function definition argument 'struct device *' should also have an identifier name
#33: FILE: drivers/base/component.c:24:
+	int (*compare_typed)(struct device *, int, void *);

-:33: WARNING:FUNCTION_ARGUMENTS: function definition argument 'int' should also have an identifier name
#33: FILE: drivers/base/component.c:24:
+	int (*compare_typed)(struct device *, int, void *);

-:33: WARNING:FUNCTION_ARGUMENTS: function definition argument 'void *' should also have an identifier name
#33: FILE: drivers/base/component.c:24:
+	int (*compare_typed)(struct device *, int, void *);

-:89: CHECK:PARENTHESIS_ALIGNMENT: Alignment should match open parenthesis
#89: FILE: drivers/base/component.c:312:
+static void __component_match_add(struct device *master,
 	struct component_match **matchptr,

-:115: CHECK:PARENTHESIS_ALIGNMENT: Alignment should match open parenthesis
#115: FILE: drivers/base/component.c:361:
+void component_match_add_release(struct device *master,
+	struct component_match **matchptr,

-:125: CHECK:PARENTHESIS_ALIGNMENT: Alignment should match open parenthesis
#125: FILE: drivers/base/component.c:371:
+void component_match_add_typed(struct device *master,
+	struct component_match **matchptr,

-:142: CHECK:PARENTHESIS_ALIGNMENT: Alignment should match open parenthesis
#142: FILE: drivers/base/component.c:569:
+static int __component_add(struct device *dev, const struct component_ops *ops,
+	int subcomponent)

-:160: CHECK:PARENTHESIS_ALIGNMENT: Alignment should match open parenthesis
#160: FILE: drivers/base/component.c:601:
+int component_add_typed(struct device *dev, const struct component_ops *ops,
+	int subcomponent)

-:185: CHECK:PARENTHESIS_ALIGNMENT: Alignment should match open parenthesis
#185: FILE: include/linux/component.h:18:
+int component_add_typed(struct device *dev, const struct component_ops *ops,
+	int subcomponent);

-:194: CHECK:PARENTHESIS_ALIGNMENT: Alignment should match open parenthesis
#194: FILE: include/linux/component.h:43:
+void component_match_add_typed(struct device *master,
+	struct component_match **matchptr,

total: 0 errors, 3 warnings, 7 checks, 154 lines checked
832e0daaf69d i915/snd_hdac: I915 subcomponent for the snd_hdac
cda95c9995e5 drm/i915: Gathering the HDCP1.4 routines together
0276a10a370e drm: header for i915 - MEI_HDCP interface
-:21: WARNING:FILE_PATH_CHANGES: added, moved or deleted file(s), does MAINTAINERS need updating?
#21: 
new file mode 100644

total: 0 errors, 1 warnings, 0 checks, 148 lines checked
f68acca4814a drm/i915: Initialize HDCP2.2
1d83e3b3f115 drm/i915: MEI interface definition
3dcaa596dc3f drm/i915: hdcp1.4 CP_IRQ handling and SW encryption tracking
198298064188 drm/i915: Enable and Disable of HDCP2.2
1622698abd49 drm/i915: Implement HDCP2.2 receiver authentication
a01404e5fd53 drm: helper functions for hdcp2 seq_num to from u32
f1175ea9dea3 drm/i915: Implement HDCP2.2 repeater authentication
3700c3811a3d drm: HDCP2.2 link check period
9b8c35378374 drm/i915: Implement HDCP2.2 link integrity check
04637f66acf7 drm/i915: Handle HDCP2.2 downstream topology change
68446942e615 drm: removing the DP Errata msg and its msg id
f4213b614949 drm/i915: Implement the HDCP2.2 support for DP
68f4b0c5ea14 drm/i915: Implement the HDCP2.2 support for HDMI
f74253e7f7f5 drm/i915: CP_IRQ handling for DP HDCP2.2 msgs
b7bbad9a0563 drm/i915: Add HDCP2.2 support for DP connectors
4e1afee78bc2 drm/i915: Add HDCP2.2 support for HDMI connectors
fd5d1c5468a9 mei: bus: whitelist hdcp client
cf820bc07f0b mei: bus: export to_mei_cl_device for mei client device drivers
077f138ca1cb 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

total: 0 errors, 1 warnings, 0 checks, 87 lines checked
73e454e3d797 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
093b47b7bbab misc/mei/hdcp: Initiate Wired HDCP2.2 Tx Session
49f2740bf3d9 misc/mei/hdcp: Verify Receiver Cert and prepare km
8840f2444d47 misc/mei/hdcp: Verify H_prime
f5339e01b46b misc/mei/hdcp: Store the HDCP Pairing info
f5dfb3e88b97 misc/mei/hdcp: Initiate Locality check
29e66b92b706 misc/mei/hdcp: Verify L_prime
246f122adce2 misc/mei/hdcp: Prepare Session Key
dd653232a293 misc/mei/hdcp: Repeater topology verification and ack
ab8721db6d1f misc/mei/hdcp: Verify M_prime
b1d31913567b misc/mei/hdcp: Enabling the HDCP authentication
2e9ffa9f92af misc/mei/hdcp: Closing wired HDCP2.2 Tx Session
5b65f09a8fda misc/mei/hdcp: Component framework for I915 Interface
b5c51146e9ef drm/i915: Commit CP without modeset
0779352526b7 drm/i915: Fix KBL HDCP2.2 encrypt status signalling
2d1c89aaeb50 FOR_TEST: i915/Kconfig: Select mei_hdcp by I915
cd6cc61ebb7f 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] 121+ messages in thread

* Re: [PATCH v10 01/40] components: multiple components for a device
  2019-01-31  6:59 ` [PATCH v10 01/40] components: multiple components for a device Ramalingam C
@ 2019-01-31  7:50   ` Greg Kroah-Hartman
  2019-01-31  8:00     ` Daniel Vetter
  2019-01-31 14:46   ` [PATCH 1/2] component: Add documentation Daniel Vetter
  2019-02-06 16:45   ` [PATCH 1/3] " Daniel Vetter
  2 siblings, 1 reply; 121+ messages in thread
From: Greg Kroah-Hartman @ 2019-01-31  7:50 UTC (permalink / raw)
  To: Ramalingam C
  Cc: Rafael J . Wysocki, daniel.vetter, intel-gfx, Takashi Iwai,
	dri-devel, Jaroslav Kysela, Russell King, tomas.winkler

On Thu, Jan 31, 2019 at 12:29:17PM +0530, Ramalingam C wrote:
> +void component_match_add_typed(struct device *master,
> +	struct component_match **matchptr,
> +	int (*compare_typed)(struct device *, int, void *), void *compare_data)
> +{
> +	__component_match_add(master, matchptr, NULL, NULL, compare_typed,
> +			      compare_data);
> +}
> +EXPORT_SYMBOL(component_match_add_typed);

No comment at all as to what this new global function does?

> +int component_add_typed(struct device *dev, const struct component_ops *ops,
> +	int subcomponent)
> +{
> +	if (WARN_ON(subcomponent == 0))
> +		return -EINVAL;
> +
> +	return __component_add(dev, ops, subcomponent);
> +}
> +EXPORT_SYMBOL_GPL(component_add_typed);

Same here, no comments at all?

Please at the very least, document new things that you add, I thought I
asked for this the last time this patch was posted :(

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] 121+ messages in thread

* Re: [PATCH v10 07/40] drm/i915: hdcp1.4 CP_IRQ handling and SW encryption tracking
  2019-01-31  6:59 ` [PATCH v10 07/40] drm/i915: hdcp1.4 CP_IRQ handling and SW encryption tracking Ramalingam C
@ 2019-01-31  7:56   ` Daniel Vetter
  2019-01-31 13:41     ` C, Ramalingam
  2019-02-04 14:09   ` Shankar, Uma
  1 sibling, 1 reply; 121+ messages in thread
From: Daniel Vetter @ 2019-01-31  7:56 UTC (permalink / raw)
  To: Ramalingam C
  Cc: daniel.vetter, intel-gfx, uma.shankar, tomas.winkler, dri-devel

On Thu, Jan 31, 2019 at 12:29:23PM +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.
> 
> v2:
>   bool is used in struct for the cleaner coding. [Daniel]
>   check_link work_fn is scheduled for cp_irq handling [Daniel]

Just doing a delta-review, v2 addresses my comment about synchronization
with the worker, so

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

> 
> 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 | 73 ++++++++++++++++++++++++++++-----------
>  3 files changed, 58 insertions(+), 22 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
> index 815ee68efa2f..9ce05819fc11 100644
> --- a/drivers/gpu/drm/i915/intel_dp.c
> +++ b/drivers/gpu/drm/i915/intel_dp.c
> @@ -4776,7 +4776,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 63e009286d5f..13a41e8cf4ff 100644
> --- a/drivers/gpu/drm/i915/intel_drv.h
> +++ b/drivers/gpu/drm/i915/intel_drv.h
> @@ -399,6 +399,9 @@ struct intel_hdcp {
>  	struct delayed_work check_work;
>  	struct work_struct prop_work;
>  
> +	/* HDCP1.4 Encryption status */
> +	bool hdcp_encrypted;
> +
>  	/* HDCP2.2 related definitions */
>  	/* Flag indicates whether this connector supports HDCP2.2 or not. */
>  	bool hdcp2_supported;
> @@ -2073,10 +2076,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 e0bb5f32ba90..c1b057f1501b 100644
> --- a/drivers/gpu/drm/i915/intel_hdcp.c
> +++ b/drivers/gpu/drm/i915/intel_hdcp.c
> @@ -74,6 +74,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)
>  {
> @@ -668,6 +678,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 = false;
>  	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)) {
> @@ -713,8 +724,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 = true;
>  			return 0;
> +		}
>  
>  		DRM_DEBUG_KMS("HDCP Auth failure (%d)\n", ret);
>  
> @@ -741,16 +754,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;
> @@ -791,18 +805,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,
> @@ -1120,6 +1122,18 @@ int hdcp2_deauthenticate_port(struct intel_connector *connector)
>  	return hdcp2_close_mei_session(connector);
>  }
>  
> +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 int i915_hdcp_component_bind(struct device *i915_kdev,
>  				    struct device *mei_kdev, void *data)
>  {
> @@ -1288,7 +1302,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);
> @@ -1328,3 +1343,21 @@ 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;
> +
> +	/*
> +	 * CP_IRQ could be triggered due to 1. HDCP2.2 auth msgs availability,
> +	 * 2. link failure and 3. repeater reauth request. At present we dont
> +	 * handle the CP_IRQ for the HDCP2.2 auth msg availability for read.
> +	 * To handle other two causes for CP_IRQ we have the work_fn which is
> +	 * scheduled here.
> +	 */
> +	schedule_delayed_work(&hdcp->check_work, 0);
> +}
> -- 
> 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] 121+ messages in thread

* Re: [PATCH v10 01/40] components: multiple components for a device
  2019-01-31  7:50   ` Greg Kroah-Hartman
@ 2019-01-31  8:00     ` Daniel Vetter
  2019-01-31  8:12       ` Greg Kroah-Hartman
  0 siblings, 1 reply; 121+ messages in thread
From: Daniel Vetter @ 2019-01-31  8:00 UTC (permalink / raw)
  To: Greg Kroah-Hartman
  Cc: Rafael J . Wysocki, intel-gfx, Takashi Iwai, dri-devel,
	Jaroslav Kysela, daniel.vetter, Russell King, tomas.winkler

On Thu, Jan 31, 2019 at 08:50:20AM +0100, Greg Kroah-Hartman wrote:
> On Thu, Jan 31, 2019 at 12:29:17PM +0530, Ramalingam C wrote:
> > +void component_match_add_typed(struct device *master,
> > +	struct component_match **matchptr,
> > +	int (*compare_typed)(struct device *, int, void *), void *compare_data)
> > +{
> > +	__component_match_add(master, matchptr, NULL, NULL, compare_typed,
> > +			      compare_data);
> > +}
> > +EXPORT_SYMBOL(component_match_add_typed);
> 
> No comment at all as to what this new global function does?
> 
> > +int component_add_typed(struct device *dev, const struct component_ops *ops,
> > +	int subcomponent)
> > +{
> > +	if (WARN_ON(subcomponent == 0))
> > +		return -EINVAL;
> > +
> > +	return __component_add(dev, ops, subcomponent);
> > +}
> > +EXPORT_SYMBOL_GPL(component_add_typed);
> 
> Same here, no comments at all?
> 
> Please at the very least, document new things that you add, I thought I
> asked for this the last time this patch was posted :(

I replied and asked whether you insist on the docs for this or not, since
nothing has docs (and documenting these two alone is not going to explain
anything frankly). It's also defacto the drm component thing, other
subsystems didn't push their own solution into the core ...

There's also the bikeshed question for what exactly we should call these,
I'm not happy with the _typed suffix. Lockdep uses _class for this, but
kinda doesn't make, _subcomponent is a bit redundant and _sub also doesn't
convey much meaning.

Russell, any better ideas?

Thanks, Daniel
-- 
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] 121+ messages in thread

* Re: [PATCH v10 15/40] drm: removing the DP Errata msg and its msg id
  2019-01-31  6:59 ` [PATCH v10 15/40] drm: removing the DP Errata msg and its msg id Ramalingam C
@ 2019-01-31  8:02   ` Daniel Vetter
  2019-02-04 14:35   ` Shankar, Uma
  1 sibling, 0 replies; 121+ messages in thread
From: Daniel Vetter @ 2019-01-31  8:02 UTC (permalink / raw)
  To: Ramalingam C
  Cc: daniel.vetter, intel-gfx, uma.shankar, tomas.winkler, dri-devel

On Thu, Jan 31, 2019 at 12:29:31PM +0530, Ramalingam C wrote:
> Since DP ERRATA message is not defined at spec, those structure
> definition is removed from drm_hdcp.h
> 
> Signed-off-by: Ramalingam C <ramalingam.c@intel.com>
> Suggested-by: Daniel Vetter <daniel.vetter@ffwll.ch>

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

> ---
>  include/drm/drm_hdcp.h | 6 ------
>  1 file changed, 6 deletions(-)
> 
> diff --git a/include/drm/drm_hdcp.h b/include/drm/drm_hdcp.h
> index d4e98b11b4aa..f243408ecf26 100644
> --- a/include/drm/drm_hdcp.h
> +++ b/include/drm/drm_hdcp.h
> @@ -69,7 +69,6 @@
>  #define HDCP_2_2_REP_SEND_ACK			15
>  #define HDCP_2_2_REP_STREAM_MANAGE		16
>  #define HDCP_2_2_REP_STREAM_READY		17
> -#define HDCP_2_2_ERRATA_DP_STREAM_TYPE		50
>  
>  #define HDCP_2_2_RTX_LEN			8
>  #define HDCP_2_2_RRX_LEN			8
> @@ -220,11 +219,6 @@ struct hdcp2_rep_stream_ready {
>  	u8	m_prime[HDCP_2_2_MPRIME_LEN];
>  } __packed;
>  
> -struct hdcp2_dp_errata_stream_type {
> -	u8	msg_id;
> -	u8	stream_type;
> -} __packed;
> -
>  /* HDCP2.2 TIMEOUTs in mSec */
>  #define HDCP_2_2_CERT_TIMEOUT_MS		100
>  #define HDCP_2_2_HPRIME_NO_PAIRED_TIMEOUT_MS	1000
> -- 
> 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] 121+ messages in thread

* Re: [PATCH v10 18/40] drm/i915: CP_IRQ handling for DP HDCP2.2 msgs
  2019-01-31  6:59 ` [PATCH v10 18/40] drm/i915: CP_IRQ handling for DP HDCP2.2 msgs Ramalingam C
@ 2019-01-31  8:08   ` Daniel Vetter
  2019-01-31 12:50     ` Daniel Vetter
  0 siblings, 1 reply; 121+ messages in thread
From: Daniel Vetter @ 2019-01-31  8:08 UTC (permalink / raw)
  To: Ramalingam C
  Cc: daniel.vetter, intel-gfx, uma.shankar, tomas.winkler, dri-devel

On Thu, Jan 31, 2019 at 12:29:34PM +0530, Ramalingam C wrote:
> Implements the
> 	Waitqueue is created to wait for CP_IRQ
> 	Signaling the CP_IRQ arrival through atomic variable.
> 	For applicable DP HDCP2.2 msgs read wait for CP_IRQ.
> 
> As per HDCP2.2 spec "HDCP Transmitters must process CP_IRQ interrupts
> when they are received from HDCP Receivers"
> 
> Without CP_IRQ processing, DP HDCP2.2 H_Prime msg was getting corrupted
> while reading it based on corresponding status bit. This creates the
> random failures in reading the DP HDCP2.2 msgs.
> 
> Signed-off-by: Ramalingam C <ramalingam.c@intel.com>
> ---
>  drivers/gpu/drm/i915/intel_dp.c   | 33 +++++++++++++++++++++++++--------
>  drivers/gpu/drm/i915/intel_drv.h  |  7 +++++++
>  drivers/gpu/drm/i915/intel_hdcp.c |  6 ++++++
>  3 files changed, 38 insertions(+), 8 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
> index b13c41220ce0..4e36df266ab3 100644
> --- a/drivers/gpu/drm/i915/intel_dp.c
> +++ b/drivers/gpu/drm/i915/intel_dp.c
> @@ -5619,6 +5619,24 @@ void intel_dp_encoder_suspend(struct intel_encoder *intel_encoder)
>  		edp_panel_vdd_off_sync(intel_dp);
>  }
>  
> +static void intel_dp_hdcp_wait_for_cp_irq(struct intel_hdcp *hdcp,
> +					  int timeout)
> +{
> +	long ret;
> +
> +	/* Reinit */
> +	atomic_set(&hdcp->cp_irq_recved, 0);

This is still fundamentally racy. The way it's usually done is through a
counter, i.e. the wait function samples the atomic counter, and the wait
condition is then that the counter has increased.

The interrupt handler on the other hand just does an atomic_inc. That way
you never have the problem that the interrupt handler has set 1 before we
clear it to 0 here.

That still leaves the race that it has incremented _before_ we sampled in
this function here. There the counter sampling needs to be moved out
(probably before we send out the message to the sink), and passed into
this function as a parameter.

Finally there's the wrapping problem, so best to just have a condition
like sampled_counter != current_counter.

I assume this won't matter for correctness if we miss the interrupt, we
just time out and at that point the next message should be available. But
it's less confusing to have more correct code.

Cheers, Daniel

> +
> +#define C (atomic_read(&hdcp->cp_irq_recved) > 0)
> +	ret = wait_event_interruptible_timeout(hdcp->cp_irq_queue, C,
> +					       msecs_to_jiffies(timeout));
> +
> +	if (ret > 0)
> +		atomic_set(&hdcp->cp_irq_recved, 0);
> +	else if (!ret)
> +		DRM_DEBUG_KMS("Timedout at waiting for CP_IRQ\n");
> +}
> +
>  static
>  int intel_dp_hdcp_write_an_aksv(struct intel_digital_port *intel_dig_port,
>  				u8 *an)
> @@ -5963,14 +5981,13 @@ intel_dp_hdcp2_wait_for_msg(struct intel_digital_port *intel_dig_port,
>  		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);
> -
> +		/*
> +		 * Ignoring the return of the intel_dp_hdcp_wait_for_cp_irq,
> +		 * Just to detect the msg availability before failing it.
> +		 */
> +		intel_dp_hdcp_wait_for_cp_irq(hdcp, timeout);
> +		ret = hdcp2_detect_msg_availability(intel_dig_port,
> +						    msg_id, &msg_ready);
>  		if (!msg_ready)
>  			ret = -ETIMEDOUT;
>  	}
> diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
> index 747fe7361287..1901d12bacc4 100644
> --- a/drivers/gpu/drm/i915/intel_drv.h
> +++ b/drivers/gpu/drm/i915/intel_drv.h
> @@ -464,6 +464,13 @@ struct intel_hdcp {
>  	 * over re-Auth has to be triggered.
>  	 */
>  	u32 seq_num_m;
> +
> +	/*
> +	 * Work queue to signal the CP_IRQ. Used for the waiters to read the
> +	 * available information from HDCP DP sink.
> +	 */
> +	wait_queue_head_t cp_irq_queue;
> +	atomic_t cp_irq_recved;
>  };
>  
>  struct intel_connector {
> diff --git a/drivers/gpu/drm/i915/intel_hdcp.c b/drivers/gpu/drm/i915/intel_hdcp.c
> index 7ff29fb0aa2f..f38feeadb363 100644
> --- a/drivers/gpu/drm/i915/intel_hdcp.c
> +++ b/drivers/gpu/drm/i915/intel_hdcp.c
> @@ -1805,6 +1805,9 @@ int intel_hdcp_init(struct intel_connector *connector,
>  	if (hdcp2_supported)
>  		intel_hdcp2_init(connector);
>  
> +	atomic_set(&hdcp->cp_irq_recved, 0);
> +	init_waitqueue_head(&hdcp->cp_irq_queue);
> +
>  	return 0;
>  }
>  
> @@ -1908,6 +1911,9 @@ void intel_hdcp_handle_cp_irq(struct intel_connector *connector)
>  	if (!hdcp->shim)
>  		return;
>  
> +	atomic_set(&connector->hdcp.cp_irq_recved, 1);
> +	wake_up_all(&connector->hdcp.cp_irq_queue);
> +
>  	/*
>  	 * CP_IRQ could be triggered due to 1. HDCP2.2 auth msgs availability,
>  	 * 2. link failure and 3. repeater reauth request. At present we dont
> -- 
> 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] 121+ messages in thread

* Re: [PATCH v10 01/40] components: multiple components for a device
  2019-01-31  8:00     ` Daniel Vetter
@ 2019-01-31  8:12       ` Greg Kroah-Hartman
  2019-01-31  8:39         ` Daniel Vetter
  0 siblings, 1 reply; 121+ messages in thread
From: Greg Kroah-Hartman @ 2019-01-31  8:12 UTC (permalink / raw)
  To: Daniel Vetter
  Cc: Rafael J . Wysocki, intel-gfx, Rodrigo Vivi, Takashi Iwai,
	dri-devel, Jaroslav Kysela, uma.shankar, daniel.vetter,
	Russell King, tomas.winkler

On Thu, Jan 31, 2019 at 09:00:30AM +0100, Daniel Vetter wrote:
> On Thu, Jan 31, 2019 at 08:50:20AM +0100, Greg Kroah-Hartman wrote:
> > On Thu, Jan 31, 2019 at 12:29:17PM +0530, Ramalingam C wrote:
> > > +void component_match_add_typed(struct device *master,
> > > +	struct component_match **matchptr,
> > > +	int (*compare_typed)(struct device *, int, void *), void *compare_data)
> > > +{
> > > +	__component_match_add(master, matchptr, NULL, NULL, compare_typed,
> > > +			      compare_data);
> > > +}
> > > +EXPORT_SYMBOL(component_match_add_typed);
> > 
> > No comment at all as to what this new global function does?
> > 
> > > +int component_add_typed(struct device *dev, const struct component_ops *ops,
> > > +	int subcomponent)
> > > +{
> > > +	if (WARN_ON(subcomponent == 0))
> > > +		return -EINVAL;
> > > +
> > > +	return __component_add(dev, ops, subcomponent);
> > > +}
> > > +EXPORT_SYMBOL_GPL(component_add_typed);
> > 
> > Same here, no comments at all?
> > 
> > Please at the very least, document new things that you add, I thought I
> > asked for this the last time this patch was posted :(
> 
> I replied and asked whether you insist on the docs for this or not, since
> nothing has docs (and documenting these two alone is not going to explain
> anything frankly). It's also defacto the drm component thing, other
> subsystems didn't push their own solution into the core ...

I thought I responded that I would love to have something for the new
stuff at the very least.

And it's not nice to create new global functions without a single line
of comment for them as to what they are supposed to be used for.  So I'm
going to insist on that happening here at the very least.

thanks,

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

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

* ✓ Fi.CI.BAT: success for drm/i915: Implement HDCP2.2 (rev13)
  2019-01-31  6:59 [PATCH v10 00/40] drm/i915: Implement HDCP2.2 Ramalingam C
                   ` (40 preceding siblings ...)
  2019-01-31  7:38 ` ✗ Fi.CI.CHECKPATCH: warning for drm/i915: Implement HDCP2.2 (rev13) Patchwork
@ 2019-01-31  8:16 ` Patchwork
  2019-01-31 18:42 ` ✓ Fi.CI.IGT: " Patchwork
  42 siblings, 0 replies; 121+ messages in thread
From: Patchwork @ 2019-01-31  8:16 UTC (permalink / raw)
  To: Ramalingam C; +Cc: intel-gfx

== Series Details ==

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

== Summary ==

CI Bug Log - changes from CI_DRM_5517 -> Patchwork_12101
====================================================

Summary
-------

  **SUCCESS**

  No regressions found.

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

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

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

### IGT changes ###

#### Issues hit ####

  * igt@i915_selftest@live_hangcheck:
    - fi-skl-6260u:       PASS -> INCOMPLETE [fdo#108744]

  * igt@kms_chamelium@common-hpd-after-suspend:
    - fi-kbl-7567u:       PASS -> WARN [fdo#109380]

  * igt@kms_pipe_crc_basic@hang-read-crc-pipe-b:
    - fi-byt-clapper:     PASS -> FAIL [fdo#103191] / [fdo#107362] +1

  
#### Possible fixes ####

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

  * igt@kms_busy@basic-flip-a:
    - fi-gdg-551:         FAIL [fdo#103182] -> PASS

  * igt@kms_chamelium@hdmi-hpd-fast:
    - fi-kbl-7500u:       FAIL [fdo#109485] -> 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#104108]: https://bugs.freedesktop.org/show_bug.cgi?id=104108
  [fdo#107362]: https://bugs.freedesktop.org/show_bug.cgi?id=107362
  [fdo#107718]: https://bugs.freedesktop.org/show_bug.cgi?id=107718
  [fdo#108569]: https://bugs.freedesktop.org/show_bug.cgi?id=108569
  [fdo#108744]: https://bugs.freedesktop.org/show_bug.cgi?id=108744
  [fdo#108866]: https://bugs.freedesktop.org/show_bug.cgi?id=108866
  [fdo#109271]: https://bugs.freedesktop.org/show_bug.cgi?id=109271
  [fdo#109276]: https://bugs.freedesktop.org/show_bug.cgi?id=109276
  [fdo#109278]: https://bugs.freedesktop.org/show_bug.cgi?id=109278
  [fdo#109285]: https://bugs.freedesktop.org/show_bug.cgi?id=109285
  [fdo#109289]: https://bugs.freedesktop.org/show_bug.cgi?id=109289
  [fdo#109309]: https://bugs.freedesktop.org/show_bug.cgi?id=109309
  [fdo#109315]: https://bugs.freedesktop.org/show_bug.cgi?id=109315
  [fdo#109316]: https://bugs.freedesktop.org/show_bug.cgi?id=109316
  [fdo#109380]: https://bugs.freedesktop.org/show_bug.cgi?id=109380
  [fdo#109485]: https://bugs.freedesktop.org/show_bug.cgi?id=109485


Participating hosts (43 -> 41)
------------------------------

  Additional (2): fi-icl-u2 fi-skl-iommu 
  Missing    (4): fi-kbl-soraka fi-ilk-m540 fi-byt-squawks fi-bsw-cyan 


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

    * Linux: CI_DRM_5517 -> Patchwork_12101

  CI_DRM_5517: b2e346ffed409cd4a9b5f010d996b72ec9e7080f @ git://anongit.freedesktop.org/gfx-ci/linux
  IGT_4801: 6f6bacf12759fb319ade3ba37861ae711f8a5cd9 @ git://anongit.freedesktop.org/xorg/app/intel-gpu-tools
  Patchwork_12101: cd6cc61ebb7f4dea4ef6e8221bf168a7f51bf113 @ git://anongit.freedesktop.org/gfx-ci/linux


== Linux commits ==

cd6cc61ebb7f FOR_TESTING_ONLY: debugfs: Excluding the LSPCon for HDCP1.4
2d1c89aaeb50 FOR_TEST: i915/Kconfig: Select mei_hdcp by I915
0779352526b7 drm/i915: Fix KBL HDCP2.2 encrypt status signalling
b5c51146e9ef drm/i915: Commit CP without modeset
5b65f09a8fda misc/mei/hdcp: Component framework for I915 Interface
2e9ffa9f92af misc/mei/hdcp: Closing wired HDCP2.2 Tx Session
b1d31913567b misc/mei/hdcp: Enabling the HDCP authentication
ab8721db6d1f misc/mei/hdcp: Verify M_prime
dd653232a293 misc/mei/hdcp: Repeater topology verification and ack
246f122adce2 misc/mei/hdcp: Prepare Session Key
29e66b92b706 misc/mei/hdcp: Verify L_prime
f5dfb3e88b97 misc/mei/hdcp: Initiate Locality check
f5339e01b46b misc/mei/hdcp: Store the HDCP Pairing info
8840f2444d47 misc/mei/hdcp: Verify H_prime
49f2740bf3d9 misc/mei/hdcp: Verify Receiver Cert and prepare km
093b47b7bbab misc/mei/hdcp: Initiate Wired HDCP2.2 Tx Session
73e454e3d797 misc/mei/hdcp: Define ME FW interface for HDCP2.2
077f138ca1cb misc/mei/hdcp: Client driver for HDCP application
cf820bc07f0b mei: bus: export to_mei_cl_device for mei client device drivers
fd5d1c5468a9 mei: bus: whitelist hdcp client
4e1afee78bc2 drm/i915: Add HDCP2.2 support for HDMI connectors
b7bbad9a0563 drm/i915: Add HDCP2.2 support for DP connectors
f74253e7f7f5 drm/i915: CP_IRQ handling for DP HDCP2.2 msgs
68f4b0c5ea14 drm/i915: Implement the HDCP2.2 support for HDMI
f4213b614949 drm/i915: Implement the HDCP2.2 support for DP
68446942e615 drm: removing the DP Errata msg and its msg id
04637f66acf7 drm/i915: Handle HDCP2.2 downstream topology change
9b8c35378374 drm/i915: Implement HDCP2.2 link integrity check
3700c3811a3d drm: HDCP2.2 link check period
f1175ea9dea3 drm/i915: Implement HDCP2.2 repeater authentication
a01404e5fd53 drm: helper functions for hdcp2 seq_num to from u32
1622698abd49 drm/i915: Implement HDCP2.2 receiver authentication
198298064188 drm/i915: Enable and Disable of HDCP2.2
3dcaa596dc3f drm/i915: hdcp1.4 CP_IRQ handling and SW encryption tracking
1d83e3b3f115 drm/i915: MEI interface definition
f68acca4814a drm/i915: Initialize HDCP2.2
0276a10a370e drm: header for i915 - MEI_HDCP interface
cda95c9995e5 drm/i915: Gathering the HDCP1.4 routines together
832e0daaf69d i915/snd_hdac: I915 subcomponent for the snd_hdac
7b8109241bdc components: multiple components for a device

== Logs ==

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

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

* Re: [PATCH v10 06/40] drm/i915: MEI interface definition
  2019-01-31  6:59 ` [PATCH v10 06/40] drm/i915: MEI interface definition Ramalingam C
@ 2019-01-31  8:17   ` Daniel Vetter
  2019-01-31 13:39     ` C, Ramalingam
  0 siblings, 1 reply; 121+ messages in thread
From: Daniel Vetter @ 2019-01-31  8:17 UTC (permalink / raw)
  To: Ramalingam C
  Cc: daniel.vetter, intel-gfx, uma.shankar, tomas.winkler, dri-devel

On Thu, Jan 31, 2019 at 12:29:22PM +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]
> v4:
>   port initialization is done only at hdcp2_init only [Danvet]
> v5:
>   I915 registers a subcomponent to be matched with mei_hdcp [Daniel]
> 
> Signed-off-by: Ramalingam C <ramalingam.c@intel.com>
> Reviewed-by: Daniel Vetter <daniel.vetter@ffwll.ch>

When you make substantial changes to a patch (like here) and decide to
keep the r-b, then please indicate that it was for an earlier version. I
most definitely didn't review this one that re-adds all the locking :-)

What's missing here is the component_del. Not exactly sure why this
doesn't blow up. Luckily we don't need a component_del_typed because
component_del already takes the (dev, ops) pair, and that's unique.
-Daniel


> ---
>  drivers/gpu/drm/i915/i915_drv.c   |   1 +
>  drivers/gpu/drm/i915/i915_drv.h   |   7 +
>  drivers/gpu/drm/i915/intel_drv.h  |   5 +
>  drivers/gpu/drm/i915/intel_hdcp.c | 378 +++++++++++++++++++++++++++++++++++++-
>  include/drm/i915_component.h      |   3 +
>  5 files changed, 393 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c
> index a7aaa1ac4c99..75aff907ba69 100644
> --- a/drivers/gpu/drm/i915/i915_drv.c
> +++ b/drivers/gpu/drm/i915/i915_drv.c
> @@ -904,6 +904,7 @@ static int i915_driver_init_early(struct drm_i915_private *dev_priv)
>  	mutex_init(&dev_priv->av_mutex);
>  	mutex_init(&dev_priv->wm.wm_mutex);
>  	mutex_init(&dev_priv->pps_mutex);
> +	mutex_init(&dev_priv->hdcp_comp_mutex);
>  
>  	i915_memcpy_init_early(dev_priv);
>  	intel_runtime_pm_init_early(dev_priv);
> diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
> index 22da9df1f0a7..d9a0771af4d1 100644
> --- a/drivers/gpu/drm/i915/i915_drv.h
> +++ b/drivers/gpu/drm/i915/i915_drv.h
> @@ -55,6 +55,7 @@
>  #include <drm/drm_util.h>
>  #include <drm/drm_dsc.h>
>  #include <drm/drm_connector.h>
> +#include <drm/i915_mei_hdcp_interface.h>
>  
>  #include "i915_fixed.h"
>  #include "i915_params.h"
> @@ -2043,6 +2044,12 @@ struct drm_i915_private {
>  
>  	struct i915_pmu pmu;
>  
> +	struct i915_hdcp_comp_master *hdcp_master;
> +	bool hdcp_comp_added;
> +
> +	/* Mutex to protect the above hdcp component related values. */
> +	struct mutex hdcp_comp_mutex;
> +
>  	/*
>  	 * 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/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
> index 0ac870feb5e9..63e009286d5f 100644
> --- a/drivers/gpu/drm/i915/intel_drv.h
> +++ b/drivers/gpu/drm/i915/intel_drv.h
> @@ -41,6 +41,7 @@
>  #include <drm/drm_rect.h>
>  #include <drm/drm_vblank.h>
>  #include <drm/drm_atomic.h>
> +#include <drm/i915_mei_hdcp_interface.h>
>  #include <media/cec-notifier.h>
>  
>  struct drm_printer;
> @@ -385,6 +386,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 {
> @@ -405,6 +409,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 1a85dc46692d..e0bb5f32ba90 100644
> --- a/drivers/gpu/drm/i915/intel_hdcp.c
> +++ b/drivers/gpu/drm/i915/intel_hdcp.c
> @@ -7,8 +7,10 @@
>   */
>  
>  #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"
> @@ -832,6 +834,348 @@ 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_hdcp_comp_master *comp;
> +	int ret;
> +
> +	mutex_lock(&dev_priv->hdcp_comp_mutex);
> +	comp = dev_priv->hdcp_master;
> +
> +	if (!comp || !comp->ops) {
> +		mutex_unlock(&dev_priv->hdcp_comp_mutex);
> +		return -EINVAL;
> +	}
> +
> +	ret = comp->ops->initiate_hdcp2_session(comp->mei_dev, data, ake_data);
> +	if (ret)
> +		DRM_DEBUG_KMS("Prepare_ake_init failed. %d\n", ret);
> +	mutex_unlock(&dev_priv->hdcp_comp_mutex);
> +
> +	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_hdcp_comp_master *comp;
> +	int ret;
> +
> +	mutex_lock(&dev_priv->hdcp_comp_mutex);
> +	comp = dev_priv->hdcp_master;
> +
> +	if (!comp || !comp->ops) {
> +		mutex_unlock(&dev_priv->hdcp_comp_mutex);
> +		return -EINVAL;
> +	}
> +
> +	ret = comp->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);
> +	mutex_unlock(&dev_priv->hdcp_comp_mutex);
> +
> +	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_hdcp_comp_master *comp;
> +	int ret;
> +
> +	mutex_lock(&dev_priv->hdcp_comp_mutex);
> +	comp = dev_priv->hdcp_master;
> +
> +	if (!comp || !comp->ops) {
> +		mutex_unlock(&dev_priv->hdcp_comp_mutex);
> +		return -EINVAL;
> +	}
> +
> +	ret = comp->ops->verify_hprime(comp->mei_dev, data, rx_hprime);
> +	if (ret < 0)
> +		DRM_DEBUG_KMS("Verify hprime failed. %d\n", ret);
> +	mutex_unlock(&dev_priv->hdcp_comp_mutex);
> +
> +	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_hdcp_comp_master *comp;
> +	int ret;
> +
> +	mutex_lock(&dev_priv->hdcp_comp_mutex);
> +	comp = dev_priv->hdcp_master;
> +
> +	if (!comp || !comp->ops) {
> +		mutex_unlock(&dev_priv->hdcp_comp_mutex);
> +		return -EINVAL;
> +	}
> +
> +	ret = comp->ops->store_pairing_info(comp->mei_dev, data, pairing_info);
> +	if (ret < 0)
> +		DRM_DEBUG_KMS("Store pairing info failed. %d\n", ret);
> +	mutex_unlock(&dev_priv->hdcp_comp_mutex);
> +
> +	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_hdcp_comp_master *comp;
> +	int ret;
> +
> +	mutex_lock(&dev_priv->hdcp_comp_mutex);
> +	comp = dev_priv->hdcp_master;
> +
> +	if (!comp || !comp->ops) {
> +		mutex_unlock(&dev_priv->hdcp_comp_mutex);
> +		return -EINVAL;
> +	}
> +
> +	ret = comp->ops->initiate_locality_check(comp->mei_dev, data, lc_init);
> +	if (ret < 0)
> +		DRM_DEBUG_KMS("Prepare lc_init failed. %d\n", ret);
> +	mutex_unlock(&dev_priv->hdcp_comp_mutex);
> +
> +	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_hdcp_comp_master *comp;
> +	int ret;
> +
> +	mutex_lock(&dev_priv->hdcp_comp_mutex);
> +	comp = dev_priv->hdcp_master;
> +
> +	if (!comp || !comp->ops) {
> +		mutex_unlock(&dev_priv->hdcp_comp_mutex);
> +		return -EINVAL;
> +	}
> +
> +	ret = comp->ops->verify_lprime(comp->mei_dev, data, rx_lprime);
> +	if (ret < 0)
> +		DRM_DEBUG_KMS("Verify L_Prime failed. %d\n", ret);
> +	mutex_unlock(&dev_priv->hdcp_comp_mutex);
> +
> +	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_hdcp_comp_master *comp;
> +	int ret;
> +
> +	mutex_lock(&dev_priv->hdcp_comp_mutex);
> +	comp = dev_priv->hdcp_master;
> +
> +	if (!comp || !comp->ops) {
> +		mutex_unlock(&dev_priv->hdcp_comp_mutex);
> +		return -EINVAL;
> +	}
> +
> +	ret = comp->ops->get_session_key(comp->mei_dev, data, ske_data);
> +	if (ret < 0)
> +		DRM_DEBUG_KMS("Get session key failed. %d\n", ret);
> +	mutex_unlock(&dev_priv->hdcp_comp_mutex);
> +
> +	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_hdcp_comp_master *comp;
> +	int ret;
> +
> +	mutex_lock(&dev_priv->hdcp_comp_mutex);
> +	comp = dev_priv->hdcp_master;
> +
> +	if (!comp || !comp->ops) {
> +		mutex_unlock(&dev_priv->hdcp_comp_mutex);
> +		return -EINVAL;
> +	}
> +
> +	ret = comp->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);
> +	mutex_unlock(&dev_priv->hdcp_comp_mutex);
> +
> +	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_hdcp_comp_master *comp;
> +	int ret;
> +
> +	mutex_lock(&dev_priv->hdcp_comp_mutex);
> +	comp = dev_priv->hdcp_master;
> +
> +	if (!comp || !comp->ops) {
> +		mutex_unlock(&dev_priv->hdcp_comp_mutex);
> +		return -EINVAL;
> +	}
> +
> +	ret = comp->ops->verify_mprime(comp->mei_dev, data, stream_ready);
> +	if (ret < 0)
> +		DRM_DEBUG_KMS("Verify mprime failed. %d\n", ret);
> +	mutex_unlock(&dev_priv->hdcp_comp_mutex);
> +
> +	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_hdcp_comp_master *comp;
> +	int ret;
> +
> +	mutex_lock(&dev_priv->hdcp_comp_mutex);
> +	comp = dev_priv->hdcp_master;
> +
> +	if (!comp || !comp->ops) {
> +		mutex_unlock(&dev_priv->hdcp_comp_mutex);
> +		return -EINVAL;
> +	}
> +
> +	ret = comp->ops->enable_hdcp_authentication(comp->mei_dev, data);
> +	if (ret < 0)
> +		DRM_DEBUG_KMS("Enable hdcp auth failed. %d\n", ret);
> +	mutex_unlock(&dev_priv->hdcp_comp_mutex);
> +
> +	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_hdcp_comp_master *comp;
> +	int ret;
> +
> +	mutex_lock(&dev_priv->hdcp_comp_mutex);
> +	comp = dev_priv->hdcp_master;
> +
> +	if (!comp || !comp->ops) {
> +		mutex_unlock(&dev_priv->hdcp_comp_mutex);
> +		return -EINVAL;
> +	}
> +
> +	ret = comp->ops->close_hdcp_session(comp->mei_dev,
> +					     &connector->hdcp.port_data);
> +	mutex_unlock(&dev_priv->hdcp_comp_mutex);
> +
> +	return ret;
> +}
> +
> +static __attribute__((unused))
> +int hdcp2_deauthenticate_port(struct intel_connector *connector)
> +{
> +	return hdcp2_close_mei_session(connector);
> +}
> +
> +static int i915_hdcp_component_bind(struct device *i915_kdev,
> +				    struct device *mei_kdev, void *data)
> +{
> +	struct drm_i915_private *dev_priv = kdev_to_i915(i915_kdev);
> +
> +	DRM_DEBUG("I915 HDCP comp bind\n");
> +	mutex_lock(&dev_priv->hdcp_comp_mutex);
> +	dev_priv->hdcp_master = (struct i915_hdcp_comp_master *)data;
> +	dev_priv->hdcp_master->mei_dev = mei_kdev;
> +	mutex_unlock(&dev_priv->hdcp_comp_mutex);
> +
> +	return 0;
> +}
> +
> +static void i915_hdcp_component_unbind(struct device *i915_kdev,
> +				       struct device *mei_kdev, void *data)
> +{
> +	struct drm_i915_private *dev_priv = kdev_to_i915(i915_kdev);
> +
> +	DRM_DEBUG("I915 HDCP comp unbind\n");
> +	mutex_lock(&dev_priv->hdcp_comp_mutex);
> +	dev_priv->hdcp_master->mei_dev = NULL;
> +	dev_priv->hdcp_master = NULL;
> +	mutex_unlock(&dev_priv->hdcp_comp_mutex);
> +}
> +
> +static const struct component_ops i915_hdcp_component_ops = {
> +	.bind   = i915_hdcp_component_bind,
> +	.unbind = i915_hdcp_component_unbind,
> +};
> +
> +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 = 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)
>  {
>  	if (!IS_ENABLED(CONFIG_INTEL_MEI_HDCP))
> @@ -845,10 +1189,42 @@ 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;
> +	bool add_component = false;
> +	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;
> +	}
> +
> +	mutex_lock(&dev_priv->hdcp_comp_mutex);
> +	/*
> +	 * Component for mei is common across the connector.
> +	 * Adding the component once is sufficient.
> +	 */
> +	if (!dev_priv->hdcp_comp_added) {
> +		dev_priv->hdcp_comp_added = true;
> +		add_component = true;
> +	}
> +	mutex_unlock(&dev_priv->hdcp_comp_mutex);
> +
> +	if (add_component) {
> +		ret = component_add_typed(dev_priv->drm.dev,
> +					  &i915_hdcp_component_ops,
> +					  I915_COMPONENT_HDCP);
> +		if (ret < 0) {
> +			DRM_DEBUG_KMS("Failed at component add(%d)\n", ret);
> +			mutex_lock(&dev_priv->hdcp_comp_mutex);
> +			dev_priv->hdcp_comp_added = false;
> +			mutex_unlock(&dev_priv->hdcp_comp_mutex);
> +			kfree(hdcp->port_data.streams);
> +			return;
> +		}
> +	}
> +
>  	hdcp->hdcp2_supported = true;
>  }
>  
> diff --git a/include/drm/i915_component.h b/include/drm/i915_component.h
> index 72fbb037f9b3..f3851ba3e4c3 100644
> --- a/include/drm/i915_component.h
> +++ b/include/drm/i915_component.h
> @@ -24,10 +24,13 @@
>  #ifndef _I915_COMPONENT_H_
>  #define _I915_COMPONENT_H_
>  
> +#include <linux/device.h>
> +
>  #include "drm_audio_component.h"
>  
>  enum i915_component_type {
>  	I915_COMPONENT_AUDIO = 1,
> +	I915_COMPONENT_HDCP,
>  };
>  
>  /* MAX_PORT is the number of port
> -- 
> 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] 121+ messages in thread

* Re: [PATCH v10 36/40] misc/mei/hdcp: Component framework for I915 Interface
  2019-01-31  6:59 ` [PATCH v10 36/40] misc/mei/hdcp: Component framework for I915 Interface Ramalingam C
@ 2019-01-31  8:23   ` Daniel Vetter
  2019-02-04 16:27   ` Shankar, Uma
  1 sibling, 0 replies; 121+ messages in thread
From: Daniel Vetter @ 2019-01-31  8:23 UTC (permalink / raw)
  To: Ramalingam C; +Cc: daniel.vetter, intel-gfx, tomas.winkler, dri-devel

On Thu, Jan 31, 2019 at 12:29:52PM +0530, 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.
> v8:
>   master comp is added to be matched with i915 subcomponent [daniel]
> 
> Signed-off-by: Ramalingam C <ramalingam.c@intel.com>
> Reviewed-by: Uma Shankar <uma.shankar@intel.com>

Pretty sure v8 has nothing to do with what Uma originally reviewed. If you
keep an r-b with substantial changes pls add an indicator about which old
version this was for. But for completely rewritten patches like this one
here it's best to outright drop it.

> ---
>  drivers/misc/mei/hdcp/mei_hdcp.c | 90 +++++++++++++++++++++++++++++++++++++++-
>  drivers/misc/mei/hdcp/mei_hdcp.h |  5 +++
>  2 files changed, 93 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/misc/mei/hdcp/mei_hdcp.c b/drivers/misc/mei/hdcp/mei_hdcp.c
> index edfc70fb0617..be2ce12ca460 100644
> --- a/drivers/misc/mei/hdcp/mei_hdcp.c
> +++ b/drivers/misc/mei/hdcp/mei_hdcp.c
> @@ -23,6 +23,7 @@
>  #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 <drm/i915_mei_hdcp_interface.h>
> @@ -692,8 +693,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,
> @@ -708,20 +708,106 @@ struct i915_hdcp_component_ops mei_hdcp_ops = {
>  	.close_hdcp_session = mei_close_hdcp_session,
>  };
>  
> +static int mei_component_master_bind(struct device *dev)
> +{
> +	struct mei_cl_device *cldev = to_mei_cl_device(dev);
> +	struct mei_hdcp_drv_data *drv_data = mei_cldev_get_drvdata(cldev);
> +	int ret;
> +
> +	dev_info(dev, "%s\n", __func__);
> +	drv_data->comp_master->ops = &mei_hdcp_ops;
> +	drv_data->comp_master->mei_dev = dev;
> +	ret = component_bind_all(dev, drv_data->comp_master);

> +	if (ret < 0)
> +		return ret;
> +
> +	return 0;
> +}
> +
> +static void mei_component_master_unbind(struct device *dev)
> +{
> +	struct mei_cl_device *cldev = to_mei_cl_device(dev);
> +	struct mei_hdcp_drv_data *drv_data = mei_cldev_get_drvdata(cldev);
> +
> +	dev_info(dev, "%s\n", __func__);
> +	component_unbind_all(dev, drv_data->comp_master);
> +}
> +
> +static const struct component_master_ops mei_component_master_ops = {
> +	.bind = mei_component_master_bind,
> +	.unbind = mei_component_master_unbind,
> +};
> +
> +static int mei_hdcp_component_match(struct device *dev, int subcomponent,
> +				    void *data)
> +{
> +	return !strcmp(dev->driver->name, "i915") &&
> +	       subcomponent == I915_COMPONENT_HDCP;
> +}
> +
>  static int mei_hdcp_probe(struct mei_cl_device *cldev,
>  			  const struct mei_cl_device_id *id)
>  {
> +	struct mei_hdcp_drv_data *drv_data;
>  	int ret;
>  
>  	ret = mei_cldev_enable(cldev);
>  	if (ret < 0)
>  		dev_err(&cldev->dev, "mei_cldev_enable Failed. %d\n", ret);
>  
> +	drv_data = kzalloc(sizeof(*drv_data), GFP_KERNEL);
> +	if (!drv_data) {
> +		ret = -ENOMEM;
> +		goto drv_data_exit;
> +	}
> +
> +	drv_data->comp_master = kzalloc(sizeof(*drv_data->comp_master),
> +					GFP_KERNEL);
> +	if (!drv_data->comp_master) {
> +		ret = -ENOMEM;
> +		goto comp_master_exit;
> +	}
> +
> +	drv_data->master_match = NULL;
> +	component_match_add_typed(&cldev->dev, &drv_data->master_match,
> +				  mei_hdcp_component_match,
> +				  drv_data->comp_master);
> +	if (IS_ERR_OR_NULL(drv_data->master_match)) {
> +		ret = -ENOMEM;
> +		goto match_add_exit;
> +	}
> +
> +	mei_cldev_set_drvdata(cldev, drv_data);
> +	ret = component_master_add_with_match(&cldev->dev,
> +					      &mei_component_master_ops,
> +					      drv_data->master_match);
> +	if (ret < 0) {
> +		dev_err(&cldev->dev, "Master comp add failed %d\n", ret);
> +		mei_cldev_set_drvdata(cldev, NULL);
> +		goto match_add_exit;
> +	}
> +
> +	return 0;
> +
> +match_add_exit:
> +	kfree(drv_data->comp_master);
> +comp_master_exit:
> +	kfree(drv_data);
> +drv_data_exit:
> +	mei_cldev_disable(cldev);
> +
>  	return ret;
>  }
>  
>  static int mei_hdcp_remove(struct mei_cl_device *cldev)
>  {
> +	struct mei_hdcp_drv_data *drv_data = mei_cldev_get_drvdata(cldev);
> +
> +	component_master_del(&cldev->dev, &mei_component_master_ops);
> +	kfree(drv_data->comp_master);
> +	kfree(drv_data);
> +	mei_cldev_set_drvdata(cldev, NULL);
> +
>  	return mei_cldev_disable(cldev);
>  }
>  
> diff --git a/drivers/misc/mei/hdcp/mei_hdcp.h b/drivers/misc/mei/hdcp/mei_hdcp.h
> index f831db3cbd54..5c872a57ba11 100644
> --- a/drivers/misc/mei/hdcp/mei_hdcp.h
> +++ b/drivers/misc/mei/hdcp/mei_hdcp.h
> @@ -363,6 +363,11 @@ struct wired_cmd_repeater_auth_stream_req_out {
>  	struct hdcp_port_id	port;
>  } __packed;
>  
> +struct mei_hdcp_drv_data {
> +	struct i915_hdcp_comp_master *comp_master;
> +	struct component_match *master_match;

I think this can just be a local variable in mei_hdcp_probe, and you could
make the comp_master directly your drv_data structure. Memory is released
through the magic of devm_. With that:

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

> +};
> +
>  enum mei_hdcp_ddi {
>  	MEI_DDI_INVALID_PORT = 0x0,
>  
> -- 
> 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] 121+ messages in thread

* Re: [PATCH v10 37/40] drm/i915: Commit CP without modeset
  2019-01-31  6:59 ` [PATCH v10 37/40] drm/i915: Commit CP without modeset Ramalingam C
@ 2019-01-31  8:32   ` Daniel Vetter
  2019-02-04  8:39     ` C, Ramalingam
  0 siblings, 1 reply; 121+ messages in thread
From: Daniel Vetter @ 2019-01-31  8:32 UTC (permalink / raw)
  To: Ramalingam C; +Cc: daniel.vetter, intel-gfx, tomas.winkler, dri-devel

On Thu, Jan 31, 2019 at 12:29:53PM +0530, Ramalingam C wrote:
> 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 ca705546a0ab..9cb03c1b0abc 100644
> --- a/drivers/gpu/drm/i915/intel_ddi.c
> +++ b/drivers/gpu/drm/i915/intel_ddi.c
> @@ -3495,11 +3495,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,
> @@ -3542,8 +3537,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 a025efb1d7c6..9b964dabb57c 100644
> --- a/drivers/gpu/drm/i915/intel_display.c
> +++ b/drivers/gpu/drm/i915/intel_display.c
> @@ -13034,6 +13034,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] = {};
> @@ -13128,9 +13130,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);

So this is kinda awkward, having these one-use callbacks for hdcp.
"changing connector state without a full modeset" is a generic problem,
and Hans has added a new intel_encoder->update_pipe callback for this
stuff. The way to use it:

- Keep the enable/disable calls where they currently are, we still need
  them for full modesets.

- Add a new update_pipe callback, which is for the !needs_modeset case for
  both hdmi and dp, and adjust hdcp state there.

- Adjust compute_config to only flag update_pipe, not a full modeset in
  compute_config (in atomic_check).

This should fit a lot neater into the overall infrastructure for fastset
and all that stuff.

For validation the problem is that we're now adding two paths, so need to
make sure the content protection test copes. We need to make sure that
we're enabling content protection both with a modeset and without,
probably the simplest trick to get there is to add a new subtest which
does a dpms off->on once content protection is on, and checks that it
stays on.

Also we need CI results without this patch so I can start merging. Rough
merge plan:
- needs ack to merge component.c through drm-intel
- merge all the i915 patches
- topic branch for mei, shared with mei subsystem
- make sure that CI has mei enabled and that tests aren't on fire
- merge this one here

Cheers, Daniel

> +
>  	/* 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 1901d12bacc4..e6b6e920ab01 100644
> --- a/drivers/gpu/drm/i915/intel_drv.h
> +++ b/drivers/gpu/drm/i915/intel_drv.h
> @@ -2129,6 +2129,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 f38feeadb363..ef127dc7a241 100644
> --- a/drivers/gpu/drm/i915/intel_hdcp.c
> +++ b/drivers/gpu/drm/i915/intel_hdcp.c
> @@ -1876,7 +1876,6 @@ void intel_hdcp_atomic_check(struct drm_connector *connector,
>  {
>  	u64 old_cp = old_state->content_protection;
>  	u64 new_cp = new_state->content_protection;
> -	struct drm_crtc_state *crtc_state;
>  
>  	if (!new_state->crtc) {
>  		/*
> @@ -1897,10 +1896,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
> 

-- 
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] 121+ messages in thread

* Re: [PATCH v10 01/40] components: multiple components for a device
  2019-01-31  8:12       ` Greg Kroah-Hartman
@ 2019-01-31  8:39         ` Daniel Vetter
  0 siblings, 0 replies; 121+ messages in thread
From: Daniel Vetter @ 2019-01-31  8:39 UTC (permalink / raw)
  To: Greg Kroah-Hartman
  Cc: Rafael J . Wysocki, intel-gfx, Takashi Iwai, dri-devel,
	Jaroslav Kysela, daniel.vetter, Russell King, tomas.winkler

On Thu, Jan 31, 2019 at 09:12:45AM +0100, Greg Kroah-Hartman wrote:
> On Thu, Jan 31, 2019 at 09:00:30AM +0100, Daniel Vetter wrote:
> > On Thu, Jan 31, 2019 at 08:50:20AM +0100, Greg Kroah-Hartman wrote:
> > > On Thu, Jan 31, 2019 at 12:29:17PM +0530, Ramalingam C wrote:
> > > > +void component_match_add_typed(struct device *master,
> > > > +	struct component_match **matchptr,
> > > > +	int (*compare_typed)(struct device *, int, void *), void *compare_data)
> > > > +{
> > > > +	__component_match_add(master, matchptr, NULL, NULL, compare_typed,
> > > > +			      compare_data);
> > > > +}
> > > > +EXPORT_SYMBOL(component_match_add_typed);
> > > 
> > > No comment at all as to what this new global function does?
> > > 
> > > > +int component_add_typed(struct device *dev, const struct component_ops *ops,
> > > > +	int subcomponent)
> > > > +{
> > > > +	if (WARN_ON(subcomponent == 0))
> > > > +		return -EINVAL;
> > > > +
> > > > +	return __component_add(dev, ops, subcomponent);
> > > > +}
> > > > +EXPORT_SYMBOL_GPL(component_add_typed);
> > > 
> > > Same here, no comments at all?
> > > 
> > > Please at the very least, document new things that you add, I thought I
> > > asked for this the last time this patch was posted :(
> > 
> > I replied and asked whether you insist on the docs for this or not, since
> > nothing has docs (and documenting these two alone is not going to explain
> > anything frankly). It's also defacto the drm component thing, other
> > subsystems didn't push their own solution into the core ...
> 
> I thought I responded that I would love to have something for the new
> stuff at the very least.

Didn't see anything fly by ...

> And it's not nice to create new global functions without a single line
> of comment for them as to what they are supposed to be used for.  So I'm
> going to insist on that happening here at the very least.

I'll type the entire thing then. I get the "new stuff at least" drill to
fill gaps (use it plenty myself), but just doesn't make sense here at all
...

Cheers, Daniel
-- 
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] 121+ messages in thread

* Re: [PATCH v10 18/40] drm/i915: CP_IRQ handling for DP HDCP2.2 msgs
  2019-01-31  8:08   ` Daniel Vetter
@ 2019-01-31 12:50     ` Daniel Vetter
  0 siblings, 0 replies; 121+ messages in thread
From: Daniel Vetter @ 2019-01-31 12:50 UTC (permalink / raw)
  To: Ramalingam C
  Cc: daniel.vetter, intel-gfx, uma.shankar, tomas.winkler, dri-devel

On Thu, Jan 31, 2019 at 09:08:04AM +0100, Daniel Vetter wrote:
> On Thu, Jan 31, 2019 at 12:29:34PM +0530, Ramalingam C wrote:
> > Implements the
> > 	Waitqueue is created to wait for CP_IRQ
> > 	Signaling the CP_IRQ arrival through atomic variable.
> > 	For applicable DP HDCP2.2 msgs read wait for CP_IRQ.
> > 
> > As per HDCP2.2 spec "HDCP Transmitters must process CP_IRQ interrupts
> > when they are received from HDCP Receivers"
> > 
> > Without CP_IRQ processing, DP HDCP2.2 H_Prime msg was getting corrupted
> > while reading it based on corresponding status bit. This creates the
> > random failures in reading the DP HDCP2.2 msgs.
> > 
> > Signed-off-by: Ramalingam C <ramalingam.c@intel.com>
> > ---
> >  drivers/gpu/drm/i915/intel_dp.c   | 33 +++++++++++++++++++++++++--------
> >  drivers/gpu/drm/i915/intel_drv.h  |  7 +++++++
> >  drivers/gpu/drm/i915/intel_hdcp.c |  6 ++++++
> >  3 files changed, 38 insertions(+), 8 deletions(-)
> > 
> > diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
> > index b13c41220ce0..4e36df266ab3 100644
> > --- a/drivers/gpu/drm/i915/intel_dp.c
> > +++ b/drivers/gpu/drm/i915/intel_dp.c
> > @@ -5619,6 +5619,24 @@ void intel_dp_encoder_suspend(struct intel_encoder *intel_encoder)
> >  		edp_panel_vdd_off_sync(intel_dp);
> >  }
> >  
> > +static void intel_dp_hdcp_wait_for_cp_irq(struct intel_hdcp *hdcp,
> > +					  int timeout)
> > +{
> > +	long ret;
> > +
> > +	/* Reinit */
> > +	atomic_set(&hdcp->cp_irq_recved, 0);
> 
> This is still fundamentally racy. The way it's usually done is through a
> counter, i.e. the wait function samples the atomic counter, and the wait
> condition is then that the counter has increased.
> 
> The interrupt handler on the other hand just does an atomic_inc. That way
> you never have the problem that the interrupt handler has set 1 before we
> clear it to 0 here.
> 
> That still leaves the race that it has incremented _before_ we sampled in
> this function here. There the counter sampling needs to be moved out
> (probably before we send out the message to the sink), and passed into
> this function as a parameter.
> 
> Finally there's the wrapping problem, so best to just have a condition
> like sampled_counter != current_counter.
> 
> I assume this won't matter for correctness if we miss the interrupt, we
> just time out and at that point the next message should be available. But
> it's less confusing to have more correct code.

Another option would be to shrug the races off (add a comment explaining
why that's ok) and use struct completion instead of wait_queue. That one
is explicitly for one-shot stuff where the wake-up itself is all we need,
and there's no further condition to check.
-Daniel

> 
> Cheers, Daniel
> 
> > +
> > +#define C (atomic_read(&hdcp->cp_irq_recved) > 0)
> > +	ret = wait_event_interruptible_timeout(hdcp->cp_irq_queue, C,
> > +					       msecs_to_jiffies(timeout));
> > +
> > +	if (ret > 0)
> > +		atomic_set(&hdcp->cp_irq_recved, 0);
> > +	else if (!ret)
> > +		DRM_DEBUG_KMS("Timedout at waiting for CP_IRQ\n");
> > +}
> > +
> >  static
> >  int intel_dp_hdcp_write_an_aksv(struct intel_digital_port *intel_dig_port,
> >  				u8 *an)
> > @@ -5963,14 +5981,13 @@ intel_dp_hdcp2_wait_for_msg(struct intel_digital_port *intel_dig_port,
> >  		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);
> > -
> > +		/*
> > +		 * Ignoring the return of the intel_dp_hdcp_wait_for_cp_irq,
> > +		 * Just to detect the msg availability before failing it.
> > +		 */
> > +		intel_dp_hdcp_wait_for_cp_irq(hdcp, timeout);
> > +		ret = hdcp2_detect_msg_availability(intel_dig_port,
> > +						    msg_id, &msg_ready);
> >  		if (!msg_ready)
> >  			ret = -ETIMEDOUT;
> >  	}
> > diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
> > index 747fe7361287..1901d12bacc4 100644
> > --- a/drivers/gpu/drm/i915/intel_drv.h
> > +++ b/drivers/gpu/drm/i915/intel_drv.h
> > @@ -464,6 +464,13 @@ struct intel_hdcp {
> >  	 * over re-Auth has to be triggered.
> >  	 */
> >  	u32 seq_num_m;
> > +
> > +	/*
> > +	 * Work queue to signal the CP_IRQ. Used for the waiters to read the
> > +	 * available information from HDCP DP sink.
> > +	 */
> > +	wait_queue_head_t cp_irq_queue;
> > +	atomic_t cp_irq_recved;
> >  };
> >  
> >  struct intel_connector {
> > diff --git a/drivers/gpu/drm/i915/intel_hdcp.c b/drivers/gpu/drm/i915/intel_hdcp.c
> > index 7ff29fb0aa2f..f38feeadb363 100644
> > --- a/drivers/gpu/drm/i915/intel_hdcp.c
> > +++ b/drivers/gpu/drm/i915/intel_hdcp.c
> > @@ -1805,6 +1805,9 @@ int intel_hdcp_init(struct intel_connector *connector,
> >  	if (hdcp2_supported)
> >  		intel_hdcp2_init(connector);
> >  
> > +	atomic_set(&hdcp->cp_irq_recved, 0);
> > +	init_waitqueue_head(&hdcp->cp_irq_queue);
> > +
> >  	return 0;
> >  }
> >  
> > @@ -1908,6 +1911,9 @@ void intel_hdcp_handle_cp_irq(struct intel_connector *connector)
> >  	if (!hdcp->shim)
> >  		return;
> >  
> > +	atomic_set(&connector->hdcp.cp_irq_recved, 1);
> > +	wake_up_all(&connector->hdcp.cp_irq_queue);
> > +
> >  	/*
> >  	 * CP_IRQ could be triggered due to 1. HDCP2.2 auth msgs availability,
> >  	 * 2. link failure and 3. repeater reauth request. At present we dont
> > -- 
> > 2.7.4
> > 
> 
> -- 
> 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] 121+ messages in thread

* Re: [PATCH v10 06/40] drm/i915: MEI interface definition
  2019-01-31  8:17   ` Daniel Vetter
@ 2019-01-31 13:39     ` C, Ramalingam
  0 siblings, 0 replies; 121+ messages in thread
From: C, Ramalingam @ 2019-01-31 13:39 UTC (permalink / raw)
  To: Daniel Vetter; +Cc: daniel.vetter, intel-gfx, tomas.winkler, dri-devel



On 1/31/2019 1:47 PM, Daniel Vetter wrote:
> On Thu, Jan 31, 2019 at 12:29:22PM +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]
>> v4:
>>    port initialization is done only at hdcp2_init only [Danvet]
>> v5:
>>    I915 registers a subcomponent to be matched with mei_hdcp [Daniel]
>>
>> Signed-off-by: Ramalingam C <ramalingam.c@intel.com>
>> Reviewed-by: Daniel Vetter <daniel.vetter@ffwll.ch>
> When you make substantial changes to a patch (like here) and decide to
> keep the r-b, then please indicate that it was for an earlier version. I
> most definitely didn't review this one that re-adds all the locking :-)
sure :)
>
> What's missing here is the component_del. Not exactly sure why this
> doesn't blow up.
That is weird. But yes note the absence of _del. I will introduce the 
the call to hdcp_exit at unload and handle the component_del.
> Luckily we don't need a component_del_typed because
> component_del already takes the (dev, ops) pair, and that's unique.
yes true.

-Ram
> -Daniel
>
>
>> ---
>>   drivers/gpu/drm/i915/i915_drv.c   |   1 +
>>   drivers/gpu/drm/i915/i915_drv.h   |   7 +
>>   drivers/gpu/drm/i915/intel_drv.h  |   5 +
>>   drivers/gpu/drm/i915/intel_hdcp.c | 378 +++++++++++++++++++++++++++++++++++++-
>>   include/drm/i915_component.h      |   3 +
>>   5 files changed, 393 insertions(+), 1 deletion(-)
>>
>> diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c
>> index a7aaa1ac4c99..75aff907ba69 100644
>> --- a/drivers/gpu/drm/i915/i915_drv.c
>> +++ b/drivers/gpu/drm/i915/i915_drv.c
>> @@ -904,6 +904,7 @@ static int i915_driver_init_early(struct drm_i915_private *dev_priv)
>>   	mutex_init(&dev_priv->av_mutex);
>>   	mutex_init(&dev_priv->wm.wm_mutex);
>>   	mutex_init(&dev_priv->pps_mutex);
>> +	mutex_init(&dev_priv->hdcp_comp_mutex);
>>   
>>   	i915_memcpy_init_early(dev_priv);
>>   	intel_runtime_pm_init_early(dev_priv);
>> diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
>> index 22da9df1f0a7..d9a0771af4d1 100644
>> --- a/drivers/gpu/drm/i915/i915_drv.h
>> +++ b/drivers/gpu/drm/i915/i915_drv.h
>> @@ -55,6 +55,7 @@
>>   #include <drm/drm_util.h>
>>   #include <drm/drm_dsc.h>
>>   #include <drm/drm_connector.h>
>> +#include <drm/i915_mei_hdcp_interface.h>
>>   
>>   #include "i915_fixed.h"
>>   #include "i915_params.h"
>> @@ -2043,6 +2044,12 @@ struct drm_i915_private {
>>   
>>   	struct i915_pmu pmu;
>>   
>> +	struct i915_hdcp_comp_master *hdcp_master;
>> +	bool hdcp_comp_added;
>> +
>> +	/* Mutex to protect the above hdcp component related values. */
>> +	struct mutex hdcp_comp_mutex;
>> +
>>   	/*
>>   	 * 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/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
>> index 0ac870feb5e9..63e009286d5f 100644
>> --- a/drivers/gpu/drm/i915/intel_drv.h
>> +++ b/drivers/gpu/drm/i915/intel_drv.h
>> @@ -41,6 +41,7 @@
>>   #include <drm/drm_rect.h>
>>   #include <drm/drm_vblank.h>
>>   #include <drm/drm_atomic.h>
>> +#include <drm/i915_mei_hdcp_interface.h>
>>   #include <media/cec-notifier.h>
>>   
>>   struct drm_printer;
>> @@ -385,6 +386,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 {
>> @@ -405,6 +409,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 1a85dc46692d..e0bb5f32ba90 100644
>> --- a/drivers/gpu/drm/i915/intel_hdcp.c
>> +++ b/drivers/gpu/drm/i915/intel_hdcp.c
>> @@ -7,8 +7,10 @@
>>    */
>>   
>>   #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"
>> @@ -832,6 +834,348 @@ 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_hdcp_comp_master *comp;
>> +	int ret;
>> +
>> +	mutex_lock(&dev_priv->hdcp_comp_mutex);
>> +	comp = dev_priv->hdcp_master;
>> +
>> +	if (!comp || !comp->ops) {
>> +		mutex_unlock(&dev_priv->hdcp_comp_mutex);
>> +		return -EINVAL;
>> +	}
>> +
>> +	ret = comp->ops->initiate_hdcp2_session(comp->mei_dev, data, ake_data);
>> +	if (ret)
>> +		DRM_DEBUG_KMS("Prepare_ake_init failed. %d\n", ret);
>> +	mutex_unlock(&dev_priv->hdcp_comp_mutex);
>> +
>> +	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_hdcp_comp_master *comp;
>> +	int ret;
>> +
>> +	mutex_lock(&dev_priv->hdcp_comp_mutex);
>> +	comp = dev_priv->hdcp_master;
>> +
>> +	if (!comp || !comp->ops) {
>> +		mutex_unlock(&dev_priv->hdcp_comp_mutex);
>> +		return -EINVAL;
>> +	}
>> +
>> +	ret = comp->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);
>> +	mutex_unlock(&dev_priv->hdcp_comp_mutex);
>> +
>> +	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_hdcp_comp_master *comp;
>> +	int ret;
>> +
>> +	mutex_lock(&dev_priv->hdcp_comp_mutex);
>> +	comp = dev_priv->hdcp_master;
>> +
>> +	if (!comp || !comp->ops) {
>> +		mutex_unlock(&dev_priv->hdcp_comp_mutex);
>> +		return -EINVAL;
>> +	}
>> +
>> +	ret = comp->ops->verify_hprime(comp->mei_dev, data, rx_hprime);
>> +	if (ret < 0)
>> +		DRM_DEBUG_KMS("Verify hprime failed. %d\n", ret);
>> +	mutex_unlock(&dev_priv->hdcp_comp_mutex);
>> +
>> +	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_hdcp_comp_master *comp;
>> +	int ret;
>> +
>> +	mutex_lock(&dev_priv->hdcp_comp_mutex);
>> +	comp = dev_priv->hdcp_master;
>> +
>> +	if (!comp || !comp->ops) {
>> +		mutex_unlock(&dev_priv->hdcp_comp_mutex);
>> +		return -EINVAL;
>> +	}
>> +
>> +	ret = comp->ops->store_pairing_info(comp->mei_dev, data, pairing_info);
>> +	if (ret < 0)
>> +		DRM_DEBUG_KMS("Store pairing info failed. %d\n", ret);
>> +	mutex_unlock(&dev_priv->hdcp_comp_mutex);
>> +
>> +	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_hdcp_comp_master *comp;
>> +	int ret;
>> +
>> +	mutex_lock(&dev_priv->hdcp_comp_mutex);
>> +	comp = dev_priv->hdcp_master;
>> +
>> +	if (!comp || !comp->ops) {
>> +		mutex_unlock(&dev_priv->hdcp_comp_mutex);
>> +		return -EINVAL;
>> +	}
>> +
>> +	ret = comp->ops->initiate_locality_check(comp->mei_dev, data, lc_init);
>> +	if (ret < 0)
>> +		DRM_DEBUG_KMS("Prepare lc_init failed. %d\n", ret);
>> +	mutex_unlock(&dev_priv->hdcp_comp_mutex);
>> +
>> +	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_hdcp_comp_master *comp;
>> +	int ret;
>> +
>> +	mutex_lock(&dev_priv->hdcp_comp_mutex);
>> +	comp = dev_priv->hdcp_master;
>> +
>> +	if (!comp || !comp->ops) {
>> +		mutex_unlock(&dev_priv->hdcp_comp_mutex);
>> +		return -EINVAL;
>> +	}
>> +
>> +	ret = comp->ops->verify_lprime(comp->mei_dev, data, rx_lprime);
>> +	if (ret < 0)
>> +		DRM_DEBUG_KMS("Verify L_Prime failed. %d\n", ret);
>> +	mutex_unlock(&dev_priv->hdcp_comp_mutex);
>> +
>> +	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_hdcp_comp_master *comp;
>> +	int ret;
>> +
>> +	mutex_lock(&dev_priv->hdcp_comp_mutex);
>> +	comp = dev_priv->hdcp_master;
>> +
>> +	if (!comp || !comp->ops) {
>> +		mutex_unlock(&dev_priv->hdcp_comp_mutex);
>> +		return -EINVAL;
>> +	}
>> +
>> +	ret = comp->ops->get_session_key(comp->mei_dev, data, ske_data);
>> +	if (ret < 0)
>> +		DRM_DEBUG_KMS("Get session key failed. %d\n", ret);
>> +	mutex_unlock(&dev_priv->hdcp_comp_mutex);
>> +
>> +	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_hdcp_comp_master *comp;
>> +	int ret;
>> +
>> +	mutex_lock(&dev_priv->hdcp_comp_mutex);
>> +	comp = dev_priv->hdcp_master;
>> +
>> +	if (!comp || !comp->ops) {
>> +		mutex_unlock(&dev_priv->hdcp_comp_mutex);
>> +		return -EINVAL;
>> +	}
>> +
>> +	ret = comp->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);
>> +	mutex_unlock(&dev_priv->hdcp_comp_mutex);
>> +
>> +	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_hdcp_comp_master *comp;
>> +	int ret;
>> +
>> +	mutex_lock(&dev_priv->hdcp_comp_mutex);
>> +	comp = dev_priv->hdcp_master;
>> +
>> +	if (!comp || !comp->ops) {
>> +		mutex_unlock(&dev_priv->hdcp_comp_mutex);
>> +		return -EINVAL;
>> +	}
>> +
>> +	ret = comp->ops->verify_mprime(comp->mei_dev, data, stream_ready);
>> +	if (ret < 0)
>> +		DRM_DEBUG_KMS("Verify mprime failed. %d\n", ret);
>> +	mutex_unlock(&dev_priv->hdcp_comp_mutex);
>> +
>> +	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_hdcp_comp_master *comp;
>> +	int ret;
>> +
>> +	mutex_lock(&dev_priv->hdcp_comp_mutex);
>> +	comp = dev_priv->hdcp_master;
>> +
>> +	if (!comp || !comp->ops) {
>> +		mutex_unlock(&dev_priv->hdcp_comp_mutex);
>> +		return -EINVAL;
>> +	}
>> +
>> +	ret = comp->ops->enable_hdcp_authentication(comp->mei_dev, data);
>> +	if (ret < 0)
>> +		DRM_DEBUG_KMS("Enable hdcp auth failed. %d\n", ret);
>> +	mutex_unlock(&dev_priv->hdcp_comp_mutex);
>> +
>> +	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_hdcp_comp_master *comp;
>> +	int ret;
>> +
>> +	mutex_lock(&dev_priv->hdcp_comp_mutex);
>> +	comp = dev_priv->hdcp_master;
>> +
>> +	if (!comp || !comp->ops) {
>> +		mutex_unlock(&dev_priv->hdcp_comp_mutex);
>> +		return -EINVAL;
>> +	}
>> +
>> +	ret = comp->ops->close_hdcp_session(comp->mei_dev,
>> +					     &connector->hdcp.port_data);
>> +	mutex_unlock(&dev_priv->hdcp_comp_mutex);
>> +
>> +	return ret;
>> +}
>> +
>> +static __attribute__((unused))
>> +int hdcp2_deauthenticate_port(struct intel_connector *connector)
>> +{
>> +	return hdcp2_close_mei_session(connector);
>> +}
>> +
>> +static int i915_hdcp_component_bind(struct device *i915_kdev,
>> +				    struct device *mei_kdev, void *data)
>> +{
>> +	struct drm_i915_private *dev_priv = kdev_to_i915(i915_kdev);
>> +
>> +	DRM_DEBUG("I915 HDCP comp bind\n");
>> +	mutex_lock(&dev_priv->hdcp_comp_mutex);
>> +	dev_priv->hdcp_master = (struct i915_hdcp_comp_master *)data;
>> +	dev_priv->hdcp_master->mei_dev = mei_kdev;
>> +	mutex_unlock(&dev_priv->hdcp_comp_mutex);
>> +
>> +	return 0;
>> +}
>> +
>> +static void i915_hdcp_component_unbind(struct device *i915_kdev,
>> +				       struct device *mei_kdev, void *data)
>> +{
>> +	struct drm_i915_private *dev_priv = kdev_to_i915(i915_kdev);
>> +
>> +	DRM_DEBUG("I915 HDCP comp unbind\n");
>> +	mutex_lock(&dev_priv->hdcp_comp_mutex);
>> +	dev_priv->hdcp_master->mei_dev = NULL;
>> +	dev_priv->hdcp_master = NULL;
>> +	mutex_unlock(&dev_priv->hdcp_comp_mutex);
>> +}
>> +
>> +static const struct component_ops i915_hdcp_component_ops = {
>> +	.bind   = i915_hdcp_component_bind,
>> +	.unbind = i915_hdcp_component_unbind,
>> +};
>> +
>> +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 = 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)
>>   {
>>   	if (!IS_ENABLED(CONFIG_INTEL_MEI_HDCP))
>> @@ -845,10 +1189,42 @@ 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;
>> +	bool add_component = false;
>> +	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;
>> +	}
>> +
>> +	mutex_lock(&dev_priv->hdcp_comp_mutex);
>> +	/*
>> +	 * Component for mei is common across the connector.
>> +	 * Adding the component once is sufficient.
>> +	 */
>> +	if (!dev_priv->hdcp_comp_added) {
>> +		dev_priv->hdcp_comp_added = true;
>> +		add_component = true;
>> +	}
>> +	mutex_unlock(&dev_priv->hdcp_comp_mutex);
>> +
>> +	if (add_component) {
>> +		ret = component_add_typed(dev_priv->drm.dev,
>> +					  &i915_hdcp_component_ops,
>> +					  I915_COMPONENT_HDCP);
>> +		if (ret < 0) {
>> +			DRM_DEBUG_KMS("Failed at component add(%d)\n", ret);
>> +			mutex_lock(&dev_priv->hdcp_comp_mutex);
>> +			dev_priv->hdcp_comp_added = false;
>> +			mutex_unlock(&dev_priv->hdcp_comp_mutex);
>> +			kfree(hdcp->port_data.streams);
>> +			return;
>> +		}
>> +	}
>> +
>>   	hdcp->hdcp2_supported = true;
>>   }
>>   
>> diff --git a/include/drm/i915_component.h b/include/drm/i915_component.h
>> index 72fbb037f9b3..f3851ba3e4c3 100644
>> --- a/include/drm/i915_component.h
>> +++ b/include/drm/i915_component.h
>> @@ -24,10 +24,13 @@
>>   #ifndef _I915_COMPONENT_H_
>>   #define _I915_COMPONENT_H_
>>   
>> +#include <linux/device.h>
>> +
>>   #include "drm_audio_component.h"
>>   
>>   enum i915_component_type {
>>   	I915_COMPONENT_AUDIO = 1,
>> +	I915_COMPONENT_HDCP,
>>   };
>>   
>>   /* MAX_PORT is the number of 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] 121+ messages in thread

* Re: [PATCH v10 07/40] drm/i915: hdcp1.4 CP_IRQ handling and SW encryption tracking
  2019-01-31  7:56   ` Daniel Vetter
@ 2019-01-31 13:41     ` C, Ramalingam
  0 siblings, 0 replies; 121+ messages in thread
From: C, Ramalingam @ 2019-01-31 13:41 UTC (permalink / raw)
  To: Daniel Vetter; +Cc: daniel.vetter, intel-gfx, tomas.winkler, dri-devel



On 1/31/2019 1:26 PM, Daniel Vetter wrote:
> On Thu, Jan 31, 2019 at 12:29:23PM +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.
>>
>> v2:
>>    bool is used in struct for the cleaner coding. [Daniel]
>>    check_link work_fn is scheduled for cp_irq handling [Daniel]
> Just doing a delta-review, v2 addresses my comment about synchronization
> with the worker, so
>
> Reviewed-by: Daniel Vetter <daniel.vetter@ffwll.ch>
Thank you.

--Ram
>
>> 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 | 73 ++++++++++++++++++++++++++++-----------
>>   3 files changed, 58 insertions(+), 22 deletions(-)
>>
>> diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
>> index 815ee68efa2f..9ce05819fc11 100644
>> --- a/drivers/gpu/drm/i915/intel_dp.c
>> +++ b/drivers/gpu/drm/i915/intel_dp.c
>> @@ -4776,7 +4776,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 63e009286d5f..13a41e8cf4ff 100644
>> --- a/drivers/gpu/drm/i915/intel_drv.h
>> +++ b/drivers/gpu/drm/i915/intel_drv.h
>> @@ -399,6 +399,9 @@ struct intel_hdcp {
>>   	struct delayed_work check_work;
>>   	struct work_struct prop_work;
>>   
>> +	/* HDCP1.4 Encryption status */
>> +	bool hdcp_encrypted;
>> +
>>   	/* HDCP2.2 related definitions */
>>   	/* Flag indicates whether this connector supports HDCP2.2 or not. */
>>   	bool hdcp2_supported;
>> @@ -2073,10 +2076,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 e0bb5f32ba90..c1b057f1501b 100644
>> --- a/drivers/gpu/drm/i915/intel_hdcp.c
>> +++ b/drivers/gpu/drm/i915/intel_hdcp.c
>> @@ -74,6 +74,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)
>>   {
>> @@ -668,6 +678,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 = false;
>>   	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)) {
>> @@ -713,8 +724,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 = true;
>>   			return 0;
>> +		}
>>   
>>   		DRM_DEBUG_KMS("HDCP Auth failure (%d)\n", ret);
>>   
>> @@ -741,16 +754,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;
>> @@ -791,18 +805,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,
>> @@ -1120,6 +1122,18 @@ int hdcp2_deauthenticate_port(struct intel_connector *connector)
>>   	return hdcp2_close_mei_session(connector);
>>   }
>>   
>> +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 int i915_hdcp_component_bind(struct device *i915_kdev,
>>   				    struct device *mei_kdev, void *data)
>>   {
>> @@ -1288,7 +1302,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);
>> @@ -1328,3 +1343,21 @@ 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;
>> +
>> +	/*
>> +	 * CP_IRQ could be triggered due to 1. HDCP2.2 auth msgs availability,
>> +	 * 2. link failure and 3. repeater reauth request. At present we dont
>> +	 * handle the CP_IRQ for the HDCP2.2 auth msg availability for read.
>> +	 * To handle other two causes for CP_IRQ we have the work_fn which is
>> +	 * scheduled here.
>> +	 */
>> +	schedule_delayed_work(&hdcp->check_work, 0);
>> +}
>> -- 
>> 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] 121+ messages in thread

* [PATCH 1/2] component: Add documentation
  2019-01-31  6:59 ` [PATCH v10 01/40] components: multiple components for a device Ramalingam C
  2019-01-31  7:50   ` Greg Kroah-Hartman
@ 2019-01-31 14:46   ` Daniel Vetter
  2019-01-31 14:46     ` [PATCH 2/2] components: multiple components for a device Daniel Vetter
                       ` (2 more replies)
  2019-02-06 16:45   ` [PATCH 1/3] " Daniel Vetter
  2 siblings, 3 replies; 121+ messages in thread
From: Daniel Vetter @ 2019-01-31 14:46 UTC (permalink / raw)
  To: DRI Development
  Cc: LKML, Daniel Vetter, C, Ramalingam, Greg Kroah-Hartman,
	Russell King, Rafael J . Wysocki, Jaroslav Kysela, Takashi Iwai,
	Rodrigo Vivi, Jani Nikula, Daniel Vetter

Someone owes me a beer ...

While typing these I think doing an s/component_master/aggregate/
would be useful:
- it's shorter :-)
- I think component/aggregate is much more meaningful naming than
  component/puppetmaster or something like that. At least to my
  English ear "aggregate" emphasizes much more the "assemble a pile of
  things into something bigger" aspect, and there's not really much
  of a control hierarchy between aggregate and constituing components.

But that's way more than a quick doc typing exercise ...

Thanks to Ram for commenting on an initial draft of these docs.

Cc: "C, Ramalingam" <ramalingam.c@intel.com>
Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Cc: Russell King <rmk+kernel@arm.linux.org.uk>
Cc: Rafael J. Wysocki <rafael@kernel.org>
Cc: Jaroslav Kysela <perex@perex.cz>
Cc: Takashi Iwai <tiwai@suse.com>
Cc: Rodrigo Vivi <rodrigo.vivi@intel.com>
Cc: Jani Nikula <jani.nikula@linux.intel.com>
Signed-off-by: Daniel Vetter <daniel.vetter@intel.com>
---
 Documentation/driver-api/device_link.rst |   3 +
 Documentation/driver-api/index.rst       |   1 +
 drivers/base/component.c                 | 107 ++++++++++++++++++++++-
 include/linux/component.h                |  70 +++++++++++++++
 4 files changed, 178 insertions(+), 3 deletions(-)

diff --git a/Documentation/driver-api/device_link.rst b/Documentation/driver-api/device_link.rst
index d6763272e747..2d5919b2b337 100644
--- a/Documentation/driver-api/device_link.rst
+++ b/Documentation/driver-api/device_link.rst
@@ -1,6 +1,9 @@
 .. |struct dev_pm_domain| replace:: :c:type:`struct dev_pm_domain <dev_pm_domain>`
 .. |struct generic_pm_domain| replace:: :c:type:`struct generic_pm_domain <generic_pm_domain>`
 
+
+.. _device_link:
+
 ============
 Device links
 ============
diff --git a/Documentation/driver-api/index.rst b/Documentation/driver-api/index.rst
index ab38ced66a44..c0b600ed9961 100644
--- a/Documentation/driver-api/index.rst
+++ b/Documentation/driver-api/index.rst
@@ -22,6 +22,7 @@ available subsections can be seen below.
    device_connection
    dma-buf
    device_link
+   component
    message-based
    sound
    frame-buffer
diff --git a/drivers/base/component.c b/drivers/base/component.c
index ddcea8739c12..e5b04bce8544 100644
--- a/drivers/base/component.c
+++ b/drivers/base/component.c
@@ -16,6 +16,33 @@
 #include <linux/slab.h>
 #include <linux/debugfs.h>
 
+/**
+ * DOC: overview
+ *
+ * The component frameworks allows drivers to collect a pile of sub-devices,
+ * including their bound drivers, into an aggregate driver. Various subsystem
+ * already provide functions to get hold of such components, e.g.
+ * of_clk_get_by_name(). Anytime there's such a subsystem specific way to find a
+ * a device the component framework should not be used. The component framework
+ * fills the niche of aggregate drivers for specific hardware, where further
+ * standardization into a subsystem doesn't make sense. The common example is
+ * when a logical device (e.g. a DRM display driver) is spread around the SoC on
+ * various component (scanout engines, blending blocks, transcoders for various
+ * outputs and so on).
+ *
+ * The component framework also doesn't solve runtime dependencies, e.g. for
+ * system suspend and resume operations. See also :ref:`device
+ * links<device_link>`.
+ *
+ * Components are registered using component_add() and unregistered with
+ * component_del(), usually from the driver's probe and disconnect functions.
+ *
+ * Aggregate drivers first assemble a component match list of what they need
+ * using component_match_add(). This is then registered as an aggregate driver
+ * using component_master_add_with_match(), and unregistered using
+ * component_master_del().
+ */
+
 struct component;
 
 struct component_match_array {
@@ -301,10 +328,24 @@ static int component_match_realloc(struct device *dev,
 	return 0;
 }
 
-/*
- * Add a component to be matched, with a release function.
+/**
+ * component_match_add_release - add a compent match with release callback
+ * @master: device with the aggregate driver
+ * @matchptr: pointer to the list of component matches
+ * @release: release function for @compare_data
+ * @compare: compare function to match against all components
+ * @compare_data: opaque pointer passed to the @compare function
+ *
+ * This adds a new component match to the list stored in @matchptr, which the
+ * @master aggregate driver needs to function. @matchptr must be initialized to
+ * NULL before adding the first match.
+ *
+ * The allocated match list in @matchptr is automatically released using devm
+ * actions. At that point @release will be called, to free any references held
+ * by @compare_data, e.g. when @compare_data is a &device_node that must be
+ * released with of_node_put().
  *
- * The match array is first created or extended if necessary.
+ * See also component_match_add().
  */
 void component_match_add_release(struct device *master,
 	struct component_match **matchptr,
@@ -367,6 +408,18 @@ static void free_master(struct master *master)
 	kfree(master);
 }
 
+/**
+ * component_master_add_with_match - register an aggregate driver
+ * @dev: device with the aggregate driver
+ * @ops: callbacks for the aggregate driver
+ * @match: component match list for the aggregate driver
+ *
+ * Registers a new aggregate driver consisting of the components added to @match
+ * by calling one of the component_match_add() functions. Once all components in
+ * @match are available it will be assembled by calling
+ * &component_master_ops.bind from @ops. Must be unregistered by calling
+ * component_master_del().
+ */
 int component_master_add_with_match(struct device *dev,
 	const struct component_master_ops *ops,
 	struct component_match *match)
@@ -403,6 +456,15 @@ int component_master_add_with_match(struct device *dev,
 }
 EXPORT_SYMBOL_GPL(component_master_add_with_match);
 
+/**
+ * component_master_del - unregister an aggregate driver
+ * @dev: device with the aggregate driver
+ * @ops: callbacks for the aggregate driver
+ *
+ * Unregistered an aggregate driver registered with
+ * component_master_add_with_match(). If necessary the aggregate driver is first
+ * disassembled by calling &component_master_ops.unbind from @ops.
+ */
 void component_master_del(struct device *dev,
 	const struct component_master_ops *ops)
 {
@@ -430,6 +492,15 @@ static void component_unbind(struct component *component,
 	devres_release_group(component->dev, component);
 }
 
+/**
+ * component_unbind_all - unbind all component to an aggregate driver
+ * @master_dev: device with the aggregate driver
+ * @data: opaque pointer, passed to all components
+ *
+ * This unbinds all components to the aggregate @dev by passing @data to their
+ * &component_ops.unbind functions. Should be called from
+ * &component_master_ops.unbind.
+ */
 void component_unbind_all(struct device *master_dev, void *data)
 {
 	struct master *master;
@@ -503,6 +574,15 @@ static int component_bind(struct component *component, struct master *master,
 	return ret;
 }
 
+/**
+ * component_bind_all - bind all component to an aggregate driver
+ * @master_dev: device with the aggregate driver
+ * @data: opaque pointer, passed to all components
+ *
+ * This binds all components to the aggregate @dev by passing @data to their
+ * &component_ops.bind functions. Should be called from
+ * &component_master_ops.bind.
+ */
 int component_bind_all(struct device *master_dev, void *data)
 {
 	struct master *master;
@@ -537,6 +617,18 @@ int component_bind_all(struct device *master_dev, void *data)
 }
 EXPORT_SYMBOL_GPL(component_bind_all);
 
+/**
+ * component_add - register a component
+ * @dev: component device
+ * @ops: component callbacks
+ *
+ * Register a new component for @dev. Functions in @ops will be call when the
+ * aggregate driver is ready to bind the overall driver by calling
+ * component_bind_all(). See also &struct component_ops.
+ *
+ * The component needs to be unregistered again at driver unload/disconnect by
+ * calling component_del().
+ */
 int component_add(struct device *dev, const struct component_ops *ops)
 {
 	struct component *component;
@@ -568,6 +660,15 @@ int component_add(struct device *dev, const struct component_ops *ops)
 }
 EXPORT_SYMBOL_GPL(component_add);
 
+/**
+ * component_del - unregister a component
+ * @dev: component device
+ * @ops: component callbacks
+ *
+ * Unregister a component added with component_add(). If the component is bound
+ * into an aggregate driver this will force the entire aggrate driver, including
+ * all its components, to be unbound.
+ */
 void component_del(struct device *dev, const struct component_ops *ops)
 {
 	struct component *c, *component = NULL;
diff --git a/include/linux/component.h b/include/linux/component.h
index e71fbbbc74e2..67a899dd2e10 100644
--- a/include/linux/component.h
+++ b/include/linux/component.h
@@ -4,11 +4,31 @@
 
 #include <linux/stddef.h>
 
+
 struct device;
 
+/**
+ * struct component_ops - callbacks for component drivers
+ *
+ * Components are registered with component_add() and unregistered with
+ * component_del().
+ */
 struct component_ops {
+	/**
+	 * @bind:
+	 *
+	 * Called through component_bind_all() when the aggregate driver is
+	 * ready to bind the overall driver.
+	 */
 	int (*bind)(struct device *comp, struct device *master,
 		    void *master_data);
+	/**
+	 * @unbind:
+	 *
+	 * Called through component_unbind_all() when the aggregate driver is
+	 * ready to bind the overall driver, or when component_bind_all() fails
+	 * part-ways through and needs to unbind some already bound components.
+	 */
 	void (*unbind)(struct device *comp, struct device *master,
 		       void *master_data);
 };
@@ -21,8 +41,42 @@ void component_unbind_all(struct device *master, void *master_data);
 
 struct master;
 
+/**
+ * struct component_master_ops - callback for the aggregate driver
+ *
+ * Aggregate drivers are registered with component_master_add_with_match() and
+ * unregistered with component_master_del().
+ */
 struct component_master_ops {
+	/**
+	 * @bind:
+	 *
+	 * Called when all components or the aggregate driver, as specified in
+	 * the match list passed to component_master_add_with_match(), are
+	 * ready. Usually there are 3 steps to bind an aggregate driver:
+	 *
+	 * 1. Allocate a structure for the aggregate driver.
+	 *
+	 * 2. Bind all components to the aggregate driver by calling
+	 *    component_bind_all() with the aggregate driver structure as opaque
+	 *    pointer data.
+	 *
+	 * 3. Register the aggregate driver with the subsystem to publish its
+	 *    interfaces.
+	 *
+	 * Note that the lifetime of the aggregate driver does not align with
+	 * any of the underlying &struct device instances. Therefore devm cannot
+	 * be used and all resources acquired or allocated in this callback must
+	 * be expecitly released in the @unbind callback.
+	 */
 	int (*bind)(struct device *master);
+	/**
+	 * @unbind:
+	 *
+	 * Called when either the aggregate driver, using
+	 * component_master_del(), or one of its components, using
+	 * component_del(), is unregistered.
+	 */
 	void (*unbind)(struct device *master);
 };
 
@@ -38,6 +92,22 @@ void component_match_add_release(struct device *master,
 	void (*release)(struct device *, void *),
 	int (*compare)(struct device *, void *), void *compare_data);
 
+/**
+ * component_match_add - add a compent match
+ * @master: device with the aggregate driver
+ * @matchptr: pointer to the list of component matches
+ * @compare: compare function to match against all components
+ * @compare_data: opaque pointer passed to the @compare function
+ *
+ * This adds a new component match to the list stored in @matchptr, which the
+ * @master aggregate driver needs to function. @matchptr must be initialized to
+ * NULL before adding the first match.
+ *
+ * The allocated match list in @matchptr is automatically released using devm
+ * actions.
+ *
+ * See also component_match_add_release().
+ */
 static inline void component_match_add(struct device *master,
 	struct component_match **matchptr,
 	int (*compare)(struct device *, void *), void *compare_data)
-- 
2.20.1


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

* [PATCH 2/2] components: multiple components for a device
  2019-01-31 14:46   ` [PATCH 1/2] component: Add documentation Daniel Vetter
@ 2019-01-31 14:46     ` Daniel Vetter
  2019-02-04 16:00         ` Daniel Vetter
  2019-02-05 10:47     ` [PATCH 1/2] component: Add documentation Rafael J. Wysocki
  2019-02-05 16:21     ` [PATCH] " Daniel Vetter
  2 siblings, 1 reply; 121+ messages in thread
From: Daniel Vetter @ 2019-01-31 14:46 UTC (permalink / raw)
  To: DRI Development
  Cc: LKML, Daniel Vetter, Ramalingam C, Greg Kroah-Hartman,
	Russell King, Rafael J . Wysocki, Jaroslav Kysela, Takashi Iwai,
	Rodrigo Vivi, Jani Nikula

Component framework is extended to support multiple components for
a struct device. These will be matched with different masters based on
its sub component value.

We are introducing this, as I915 needs two different components
with different subcomponent value, which will be matched to two
different component masters(Audio and HDCP) based on the subcomponent
values.

v2: Add documenation.

Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch> (v1 code)
Signed-off-by: Ramalingam C <ramalingam.c@intel.com> (v1 commit message)
Cc: Ramalingam C <ramalingam.c@intel.com>
Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Cc: Russell King <rmk+kernel@arm.linux.org.uk>
Cc: Rafael J. Wysocki <rafael@kernel.org>
Cc: Jaroslav Kysela <perex@perex.cz>
Cc: Takashi Iwai <tiwai@suse.com>
Cc: Rodrigo Vivi <rodrigo.vivi@intel.com>
Cc: Jani Nikula <jani.nikula@linux.intel.com>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
---
 drivers/base/component.c  | 159 +++++++++++++++++++++++++++++---------
 include/linux/component.h |  10 ++-
 2 files changed, 130 insertions(+), 39 deletions(-)

diff --git a/drivers/base/component.c b/drivers/base/component.c
index e5b04bce8544..eb7915fc5278 100644
--- a/drivers/base/component.c
+++ b/drivers/base/component.c
@@ -48,6 +48,7 @@ struct component;
 struct component_match_array {
 	void *data;
 	int (*compare)(struct device *, void *);
+	int (*compare_typed)(struct device *, int, void *);
 	void (*release)(struct device *, void *);
 	struct component *component;
 	bool duplicate;
@@ -75,6 +76,7 @@ struct component {
 	bool bound;
 
 	const struct component_ops *ops;
+	int subcomponent;
 	struct device *dev;
 };
 
@@ -159,7 +161,7 @@ static struct master *__master_find(struct device *dev,
 }
 
 static struct component *find_component(struct master *master,
-	int (*compare)(struct device *, void *), void *compare_data)
+	struct component_match_array *mc)
 {
 	struct component *c;
 
@@ -167,8 +169,13 @@ static struct component *find_component(struct master *master,
 		if (c->master && c->master != master)
 			continue;
 
-		if (compare(c->dev, compare_data))
+		if (mc->compare_typed) {
+			if (mc->compare_typed(c->dev, c->subcomponent,
+					      mc->data))
+				return c;
+		} else if (mc->compare(c->dev, mc->data)) {
 			return c;
+		}
 	}
 
 	return NULL;
@@ -193,7 +200,7 @@ static int find_components(struct master *master)
 		if (match->compare[i].component)
 			continue;
 
-		c = find_component(master, mc->compare, mc->data);
+		c = find_component(master, mc);
 		if (!c) {
 			ret = -ENXIO;
 			break;
@@ -328,29 +335,12 @@ static int component_match_realloc(struct device *dev,
 	return 0;
 }
 
-/**
- * component_match_add_release - add a compent match with release callback
- * @master: device with the aggregate driver
- * @matchptr: pointer to the list of component matches
- * @release: release function for @compare_data
- * @compare: compare function to match against all components
- * @compare_data: opaque pointer passed to the @compare function
- *
- * This adds a new component match to the list stored in @matchptr, which the
- * @master aggregate driver needs to function. @matchptr must be initialized to
- * NULL before adding the first match.
- *
- * The allocated match list in @matchptr is automatically released using devm
- * actions. At that point @release will be called, to free any references held
- * by @compare_data, e.g. when @compare_data is a &device_node that must be
- * released with of_node_put().
- *
- * See also component_match_add().
- */
-void component_match_add_release(struct device *master,
+static void __component_match_add(struct device *master,
 	struct component_match **matchptr,
 	void (*release)(struct device *, void *),
-	int (*compare)(struct device *, void *), void *compare_data)
+	int (*compare)(struct device *, void *),
+	int (*compare_typed)(struct device *, int, void *),
+	void *compare_data)
 {
 	struct component_match *match = *matchptr;
 
@@ -382,13 +372,69 @@ void component_match_add_release(struct device *master,
 	}
 
 	match->compare[match->num].compare = compare;
+	match->compare[match->num].compare_typed = compare_typed;
 	match->compare[match->num].release = release;
 	match->compare[match->num].data = compare_data;
 	match->compare[match->num].component = NULL;
 	match->num++;
 }
+
+/**
+ * component_match_add_release - add a compent match with release callback
+ * @master: device with the aggregate driver
+ * @matchptr: pointer to the list of component matches
+ * @release: release function for @compare_data
+ * @compare: compare function to match against all components
+ * @compare_data: opaque pointer passed to the @compare function
+ *
+ * This adds a new component match to the list stored in @matchptr, which the
+ * @master aggregate driver needs to function. @matchptr must be initialized to
+ * NULL before adding the first match.
+ *
+ * The allocated match list in @matchptr is automatically released using devm
+ * actions. At that point @release will be called, to free any references held
+ * by @compare_data, e.g. when @compare_data is a &device_node that must be
+ * released with of_node_put(). This only matches against components
+ * added with component_add().
+ *
+ * See also component_match_add() and component_match_add_typed().
+ */
+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)
+{
+	__component_match_add(master, matchptr, release, compare, NULL,
+			      compare_data);
+}
 EXPORT_SYMBOL(component_match_add_release);
 
+/**
+ * component_match_add_typed - add a compent match for a typed component
+ * @master: device with the aggregate driver
+ * @matchptr: pointer to the list of component matches
+ * @compare_typed: compare function to match against all typed components
+ * @compare_data: opaque pointer passed to the @compare function
+ *
+ * This adds a new component match to the list stored in @matchptr, which the
+ * @master aggregate driver needs to function. @matchptr must be initialized to
+ * NULL before adding the first match. This only matches against components
+ * added with component_add_typed().
+ *
+ * The allocated match list in @matchptr is automatically released using devm
+ * actions.
+ *
+ * See also component_match_add_release() and component_match_add_typed().
+ */
+void component_match_add_typed(struct device *master,
+	struct component_match **matchptr,
+	int (*compare_typed)(struct device *, int, void *), void *compare_data)
+{
+	__component_match_add(master, matchptr, NULL, NULL, compare_typed,
+			      compare_data);
+}
+EXPORT_SYMBOL(component_match_add_typed);
+
 static void free_master(struct master *master)
 {
 	struct component_match *match = master->match;
@@ -617,19 +663,8 @@ int component_bind_all(struct device *master_dev, void *data)
 }
 EXPORT_SYMBOL_GPL(component_bind_all);
 
-/**
- * component_add - register a component
- * @dev: component device
- * @ops: component callbacks
- *
- * Register a new component for @dev. Functions in @ops will be call when the
- * aggregate driver is ready to bind the overall driver by calling
- * component_bind_all(). See also &struct component_ops.
- *
- * The component needs to be unregistered again at driver unload/disconnect by
- * calling component_del().
- */
-int component_add(struct device *dev, const struct component_ops *ops)
+static int __component_add(struct device *dev, const struct component_ops *ops,
+	int subcomponent)
 {
 	struct component *component;
 	int ret;
@@ -640,6 +675,7 @@ int component_add(struct device *dev, const struct component_ops *ops)
 
 	component->ops = ops;
 	component->dev = dev;
+	component->subcomponent = subcomponent;
 
 	dev_dbg(dev, "adding component (ops %ps)\n", ops);
 
@@ -658,6 +694,55 @@ int component_add(struct device *dev, const struct component_ops *ops)
 
 	return ret < 0 ? ret : 0;
 }
+
+/**
+ * component_add_typed - register a component
+ * @dev: component device
+ * @ops: component callbacks
+ * @subcomponent: nonzero identifier for subcomponents
+ *
+ * Register a new component for @dev. Functions in @ops will be call when the
+ * aggregate driver is ready to bind the overall driver by calling
+ * component_bind_all(). See also &struct component_ops.
+ *
+ * @subcomponent must be nonzero and is used to differentiate between multiple
+ * components registerd on the same device @dev. These components are match
+ * using component_match_add_typed().
+ *
+ * The component needs to be unregistered again at driver unload/disconnect by
+ * calling component_del().
+ *
+ * See also component_add().
+ */
+int component_add_typed(struct device *dev, const struct component_ops *ops,
+	int subcomponent)
+{
+	if (WARN_ON(subcomponent == 0))
+		return -EINVAL;
+
+	return __component_add(dev, ops, subcomponent);
+}
+EXPORT_SYMBOL_GPL(component_add_typed);
+
+/**
+ * component_add - register a component
+ * @dev: component device
+ * @ops: component callbacks
+ *
+ * Register a new component for @dev. Functions in @ops will be call when the
+ * aggregate driver is ready to bind the overall driver by calling
+ * component_bind_all(). See also &struct component_ops.
+ *
+ * The component needs to be unregistered again at driver unload/disconnect by
+ * calling component_del().
+ *
+ * See also component_add_typed() for a variant that allows multipled different
+ * components on the same device.
+ */
+int component_add(struct device *dev, const struct component_ops *ops)
+{
+	return __component_add(dev, ops, 0);
+}
 EXPORT_SYMBOL_GPL(component_add);
 
 /**
diff --git a/include/linux/component.h b/include/linux/component.h
index 67a899dd2e10..9e69e2117f0b 100644
--- a/include/linux/component.h
+++ b/include/linux/component.h
@@ -34,6 +34,8 @@ struct component_ops {
 };
 
 int component_add(struct device *, const struct component_ops *);
+int component_add_typed(struct device *dev, const struct component_ops *ops,
+	int subcomponent);
 void component_del(struct device *, const struct component_ops *);
 
 int component_bind_all(struct device *master, void *master_data);
@@ -91,6 +93,9 @@ 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_add_typed(struct device *master,
+	struct component_match **matchptr,
+	int (*compare_typed)(struct device *, int, void *), void *compare_data);
 
 /**
  * component_match_add - add a compent match
@@ -101,12 +106,13 @@ void component_match_add_release(struct device *master,
  *
  * This adds a new component match to the list stored in @matchptr, which the
  * @master aggregate driver needs to function. @matchptr must be initialized to
- * NULL before adding the first match.
+ * NULL before adding the first match. This only matches against components
+ * added with component_add().
  *
  * The allocated match list in @matchptr is automatically released using devm
  * actions.
  *
- * See also component_match_add_release().
+ * See also component_match_add_release() and component_match_add_typed().
  */
 static inline void component_match_add(struct device *master,
 	struct component_match **matchptr,
-- 
2.20.1


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

* ✓ Fi.CI.IGT: success for drm/i915: Implement HDCP2.2 (rev13)
  2019-01-31  6:59 [PATCH v10 00/40] drm/i915: Implement HDCP2.2 Ramalingam C
                   ` (41 preceding siblings ...)
  2019-01-31  8:16 ` ✓ Fi.CI.BAT: success " Patchwork
@ 2019-01-31 18:42 ` Patchwork
  42 siblings, 0 replies; 121+ messages in thread
From: Patchwork @ 2019-01-31 18:42 UTC (permalink / raw)
  To: C, Ramalingam; +Cc: intel-gfx

== Series Details ==

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

== Summary ==

CI Bug Log - changes from CI_DRM_5517_full -> Patchwork_12101_full
====================================================

Summary
-------

  **SUCCESS**

  No regressions found.

  

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

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

### IGT changes ###

#### Issues hit ####

  * igt@kms_busy@extended-modeset-hang-newfb-render-b:
    - shard-kbl:          NOTRUN -> DMESG-WARN [fdo#107956]

  * igt@kms_color@pipe-a-legacy-gamma:
    - shard-apl:          PASS -> FAIL [fdo#104782] / [fdo#108145]

  * igt@kms_cursor_crc@cursor-128x128-random:
    - shard-glk:          PASS -> FAIL [fdo#103232]

  * igt@kms_cursor_crc@cursor-256x256-suspend:
    - shard-hsw:          PASS -> INCOMPLETE [fdo#103540]

  * igt@kms_cursor_crc@cursor-256x85-random:
    - shard-apl:          PASS -> FAIL [fdo#103232] +1

  * igt@kms_plane_alpha_blend@pipe-a-alpha-opaque-fb:
    - shard-glk:          PASS -> FAIL [fdo#108145]

  
#### Possible fixes ####

  * igt@gem_eio@reset-stress:
    - shard-snb:          INCOMPLETE [fdo#105411] -> PASS

  * igt@kms_busy@extended-pageflip-hang-newfb-render-c:
    - shard-glk:          DMESG-WARN [fdo#107956] -> PASS

  * igt@kms_color@pipe-a-degamma:
    - shard-apl:          FAIL [fdo#104782] / [fdo#108145] -> PASS

  * igt@kms_color@pipe-b-ctm-max:
    - shard-apl:          FAIL [fdo#108147] -> PASS

  * igt@kms_cursor_crc@cursor-64x64-random:
    - shard-apl:          FAIL [fdo#103232] -> PASS

  * igt@kms_cursor_crc@cursor-64x64-sliding:
    - shard-glk:          FAIL [fdo#103232] -> PASS +1

  * igt@kms_plane@pixel-format-pipe-b-planes-source-clamping:
    - shard-glk:          FAIL [fdo#108948] -> PASS

  * igt@kms_plane@plane-position-covered-pipe-c-planes:
    - shard-glk:          FAIL [fdo#103166] -> PASS

  * igt@kms_plane_multiple@atomic-pipe-c-tiling-y:
    - shard-apl:          FAIL [fdo#103166] -> PASS

  * igt@kms_setmode@basic:
    - shard-apl:          FAIL [fdo#99912] -> PASS

  * igt@pm_rc6_residency@rc6-accuracy:
    - shard-snb:          {SKIP} [fdo#109271] -> PASS

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

  [fdo#103166]: https://bugs.freedesktop.org/show_bug.cgi?id=103166
  [fdo#103232]: https://bugs.freedesktop.org/show_bug.cgi?id=103232
  [fdo#103540]: https://bugs.freedesktop.org/show_bug.cgi?id=103540
  [fdo#104782]: https://bugs.freedesktop.org/show_bug.cgi?id=104782
  [fdo#105411]: https://bugs.freedesktop.org/show_bug.cgi?id=105411
  [fdo#107956]: https://bugs.freedesktop.org/show_bug.cgi?id=107956
  [fdo#108145]: https://bugs.freedesktop.org/show_bug.cgi?id=108145
  [fdo#108147]: https://bugs.freedesktop.org/show_bug.cgi?id=108147
  [fdo#108597]: https://bugs.freedesktop.org/show_bug.cgi?id=108597
  [fdo#108948]: https://bugs.freedesktop.org/show_bug.cgi?id=108948
  [fdo#109271]: https://bugs.freedesktop.org/show_bug.cgi?id=109271
  [fdo#109278]: https://bugs.freedesktop.org/show_bug.cgi?id=109278
  [fdo#99912]: https://bugs.freedesktop.org/show_bug.cgi?id=99912


Participating hosts (7 -> 5)
------------------------------

  Missing    (2): shard-skl shard-iclb 


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

    * Linux: CI_DRM_5517 -> Patchwork_12101

  CI_DRM_5517: b2e346ffed409cd4a9b5f010d996b72ec9e7080f @ git://anongit.freedesktop.org/gfx-ci/linux
  IGT_4801: 6f6bacf12759fb319ade3ba37861ae711f8a5cd9 @ git://anongit.freedesktop.org/xorg/app/intel-gpu-tools
  Patchwork_12101: cd6cc61ebb7f4dea4ef6e8221bf168a7f51bf113 @ git://anongit.freedesktop.org/gfx-ci/linux
  piglit_4509: fdc5a4ca11124ab8413c7988896eec4c97336694 @ git://anongit.freedesktop.org/piglit

== Logs ==

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

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

* Re: [PATCH v10 37/40] drm/i915: Commit CP without modeset
  2019-01-31  8:32   ` Daniel Vetter
@ 2019-02-04  8:39     ` C, Ramalingam
  0 siblings, 0 replies; 121+ messages in thread
From: C, Ramalingam @ 2019-02-04  8:39 UTC (permalink / raw)
  To: Daniel Vetter, tomas.winkler; +Cc: daniel.vetter, intel-gfx, dri-devel

Tomas,

On 1/31/2019 2:02 PM, Daniel Vetter wrote:
> Also we need CI results without this patch so I can start merging. Rough
> merge plan:
> - needs ack to merge component.c through drm-intel
> - merge all the i915 patches
> - topic branch for mei, shared with mei subsystem
Is this convenient to you? Or you have any other suggestion?

--Ram
> - make sure that CI has mei enabled and that tests aren't on fire
> - merge this one here
>
> Cheers, Daniel

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

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

* Re: [PATCH v10 03/40] drm/i915: Gathering the HDCP1.4 routines together
  2019-01-31  6:59 ` [PATCH v10 03/40] drm/i915: Gathering the HDCP1.4 routines together Ramalingam C
@ 2019-02-04 13:11   ` Shankar, Uma
  0 siblings, 0 replies; 121+ messages in thread
From: Shankar, Uma @ 2019-02-04 13:11 UTC (permalink / raw)
  To: C, Ramalingam, intel-gfx, dri-devel, daniel.vetter, Winkler, Tomas



>-----Original Message-----
>From: C, Ramalingam
>Sent: Thursday, January 31, 2019 12:29 PM
>To: intel-gfx@lists.freedesktop.org; dri-devel@lists.freedesktop.org;
>daniel.vetter@ffwll.ch; Winkler, Tomas <tomas.winkler@intel.com>; Shankar,
>Uma <uma.shankar@intel.com>
>Cc: C, Ramalingam <ramalingam.c@intel.com>
>Subject: [PATCH v10 03/40] drm/i915: Gathering the HDCP1.4 routines together
>
>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>
>Acked-by: Daniel Vetter <daniel.vetter@ffwll.ch>

Looks ok to me.
Reviewed-by: Uma Shankar <uma.shankar@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 ce7ba3a9c000..8cb85b07cfde 100644
>--- a/drivers/gpu/drm/i915/intel_hdcp.c
>+++ b/drivers/gpu/drm/i915/intel_hdcp.c
>@@ -730,6 +730,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),
>@@ -866,62 +925,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

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

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

* RE: [PATCH v10 04/40] drm: header for i915 - MEI_HDCP interface
  2019-01-31  6:59 ` [PATCH v10 04/40] drm: header for i915 - MEI_HDCP interface Ramalingam C
@ 2019-02-04 13:24   ` Shankar, Uma
  0 siblings, 0 replies; 121+ messages in thread
From: Shankar, Uma @ 2019-02-04 13:24 UTC (permalink / raw)
  To: C, Ramalingam, intel-gfx, dri-devel, daniel.vetter, Winkler, Tomas



>-----Original Message-----
>From: C, Ramalingam
>Sent: Thursday, January 31, 2019 12:29 PM
>To: intel-gfx@lists.freedesktop.org; dri-devel@lists.freedesktop.org;
>daniel.vetter@ffwll.ch; Winkler, Tomas <tomas.winkler@intel.com>; Shankar,
>Uma <uma.shankar@intel.com>
>Cc: C, Ramalingam <ramalingam.c@intel.com>
>Subject: [PATCH v10 04/40] drm: header for i915 - MEI_HDCP interface
>
>Header defines the interface for the I915 and MEI_HDCP drivers.
>This interface is specific to the usage of mei_hdcp from gen9+ platforms for ME
>FW based HDCP2.2 services.
>
>And Generic HDCP2.2 protocol specific definitions are added at drm/drm_hdcp.h.
>
>v2: Commit msg is enhanced [Daniel]
>
>v3: i915_hdcp_comp_master is defined.
>
>Signed-off-by: Ramalingam C <ramalingam.c@intel.com>
>Reviewed-by: Daniel Vetter <daniel.vetter@ffwll.ch>

Looks ok to me.
Reviewed-by: Uma Shankar <uma.shankar@intel.com>

>---
> include/drm/i915_mei_hdcp_interface.h | 148
>++++++++++++++++++++++++++++++++++
> 1 file changed, 148 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..bc5b0c71ed3c
>--- /dev/null
>+++ b/include/drm/i915_mei_hdcp_interface.h
>@@ -0,0 +1,148 @@
>+/* SPDX-License-Identifier: (GPL-2.0+) */
>+/*
>+ * 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 <linux/device.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);
>+};
>+
>+/**
>+ * struct i915_hdcp_component_master - Used for communication between
>+i915
>+ * and mei_hdcp drivers for the HDCP2.2 services
>+ * @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_hdcp_comp_master {
>+	struct device *mei_dev;
>+	const struct i915_hdcp_component_ops *ops;
>+
>+	/* To protect the above members. */
>+	struct mutex mutex;
>+};
>+
>+#endif /* _I915_MEI_HDCP_INTERFACE_H_ */
>--
>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] 121+ messages in thread

* RE: [PATCH v10 05/40] drm/i915: Initialize HDCP2.2
  2019-01-31  6:59 ` [PATCH v10 05/40] drm/i915: Initialize HDCP2.2 Ramalingam C
@ 2019-02-04 13:29   ` Shankar, Uma
  0 siblings, 0 replies; 121+ messages in thread
From: Shankar, Uma @ 2019-02-04 13:29 UTC (permalink / raw)
  To: C, Ramalingam, intel-gfx, dri-devel, daniel.vetter, Winkler, Tomas



>-----Original Message-----
>From: C, Ramalingam
>Sent: Thursday, January 31, 2019 12:29 PM
>To: intel-gfx@lists.freedesktop.org; dri-devel@lists.freedesktop.org;
>daniel.vetter@ffwll.ch; Winkler, Tomas <tomas.winkler@intel.com>; Shankar,
>Uma <uma.shankar@intel.com>
>Cc: C, Ramalingam <ramalingam.c@intel.com>
>Subject: [PATCH v10 05/40] drm/i915: Initialize HDCP2.2
>
>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.
>v10:
>  bool is used in struct to make coding simpler. [Daniel]
>  hdmi hdcp init is placed correctly after encoder attachment.
>
>Signed-off-by: Ramalingam C <ramalingam.c@intel.com>
>Reviewed-by: Daniel Vetter <daniel.vetter@ffwll.ch>

Looks ok to me.
Reviewed-by: Uma Shankar <uma.shankar@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 | 33 ++++++++++++++++++++++++++++++---
>drivers/gpu/drm/i915/intel_hdmi.c |  8 ++++----
> 4 files changed, 50 insertions(+), 9 deletions(-)
>
>diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
>index 681e88405ada..815ee68efa2f 100644
>--- a/drivers/gpu/drm/i915/intel_dp.c
>+++ b/drivers/gpu/drm/i915/intel_dp.c
>@@ -6950,7 +6950,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 90ba5436370e..0ac870feb5e9 100644
>--- a/drivers/gpu/drm/i915/intel_drv.h
>+++ b/drivers/gpu/drm/i915/intel_drv.h
>@@ -394,6 +394,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. */
>+	bool 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 {
>@@ -2053,12 +2064,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 8cb85b07cfde..1a85dc46692d 100644
>--- a/drivers/gpu/drm/i915/intel_hdcp.c
>+++ b/drivers/gpu/drm/i915/intel_hdcp.c
>@@ -832,14 +832,37 @@ 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) {
>+	if (!IS_ENABLED(CONFIG_INTEL_MEI_HDCP))
>+		return false;
>+
>+	return (INTEL_GEN(dev_priv) >= 10 || IS_GEMINILAKE(dev_priv) ||
>+		IS_KABYLAKE(dev_priv));
>+}
>+
>+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 = true;
>+}
>+
> 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;
>
>@@ -847,6 +870,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 97a98e1bea56..ab376a31cdab 100644
>--- a/drivers/gpu/drm/i915/intel_hdmi.c
>+++ b/drivers/gpu/drm/i915/intel_hdmi.c
>@@ -2427,16 +2427,16 @@ void intel_hdmi_init_connector(struct
>intel_digital_port *intel_dig_port,
>
> 	intel_hdmi_add_properties(intel_hdmi, connector);
>
>+	intel_connector_attach_encoder(intel_connector, intel_encoder);
>+	intel_hdmi->attached_connector = intel_connector;
>+
> 	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");
> 	}
>
>-	intel_connector_attach_encoder(intel_connector, intel_encoder);
>-	intel_hdmi->attached_connector = intel_connector;
>-
> 	/* For G4X desktop chip, PEG_BAND_GAP_DATA 3:0 must first be written
> 	 * 0xd.  Failure to do so will result in spurious interrupts being
> 	 * generated on the port when a cable is not attached.
>--
>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] 121+ messages in thread

* Re: [PATCH v10 07/40] drm/i915: hdcp1.4 CP_IRQ handling and SW encryption tracking
  2019-01-31  6:59 ` [PATCH v10 07/40] drm/i915: hdcp1.4 CP_IRQ handling and SW encryption tracking Ramalingam C
  2019-01-31  7:56   ` Daniel Vetter
@ 2019-02-04 14:09   ` Shankar, Uma
  2019-02-04 14:43     ` C, Ramalingam
  1 sibling, 1 reply; 121+ messages in thread
From: Shankar, Uma @ 2019-02-04 14:09 UTC (permalink / raw)
  To: C, Ramalingam, intel-gfx, dri-devel, daniel.vetter, Winkler, Tomas



>-----Original Message-----
>From: C, Ramalingam
>Sent: Thursday, January 31, 2019 12:29 PM
>To: intel-gfx@lists.freedesktop.org; dri-devel@lists.freedesktop.org;
>daniel.vetter@ffwll.ch; Winkler, Tomas <tomas.winkler@intel.com>; Shankar,
>Uma <uma.shankar@intel.com>
>Cc: C, Ramalingam <ramalingam.c@intel.com>
>Subject: [PATCH v10 07/40] drm/i915: hdcp1.4 CP_IRQ handling and SW
>encryption tracking
>
>"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.
>
>v2:
>  bool is used in struct for the cleaner coding. [Daniel]
>  check_link work_fn is scheduled for cp_irq handling [Daniel]
>
>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 |
>73 ++++++++++++++++++++++++++++-----------
> 3 files changed, 58 insertions(+), 22 deletions(-)
>
>diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
>index 815ee68efa2f..9ce05819fc11 100644
>--- a/drivers/gpu/drm/i915/intel_dp.c
>+++ b/drivers/gpu/drm/i915/intel_dp.c
>@@ -4776,7 +4776,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 63e009286d5f..13a41e8cf4ff 100644
>--- a/drivers/gpu/drm/i915/intel_drv.h
>+++ b/drivers/gpu/drm/i915/intel_drv.h
>@@ -399,6 +399,9 @@ struct intel_hdcp {
> 	struct delayed_work check_work;
> 	struct work_struct prop_work;
>
>+	/* HDCP1.4 Encryption status */
>+	bool hdcp_encrypted;
>+
> 	/* HDCP2.2 related definitions */
> 	/* Flag indicates whether this connector supports HDCP2.2 or not. */
> 	bool hdcp2_supported;
>@@ -2073,10 +2076,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 e0bb5f32ba90..c1b057f1501b 100644
>--- a/drivers/gpu/drm/i915/intel_hdcp.c
>+++ b/drivers/gpu/drm/i915/intel_hdcp.c
>@@ -74,6 +74,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)  { @@ -
>668,6 +678,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 = false;
> 	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)) {
>@@ -713,8 +724,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 = true;
> 			return 0;
>+		}
>
> 		DRM_DEBUG_KMS("HDCP Auth failure (%d)\n", ret);
>
>@@ -741,16 +754,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;
>@@ -791,18 +805,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, @@ -
>1120,6 +1122,18 @@ int hdcp2_deauthenticate_port(struct intel_connector
>*connector)
> 	return hdcp2_close_mei_session(connector);
> }
>
>+static void intel_hdcp_check_work(struct work_struct *work) {

Why this code movement for check_work. If not intentional no need for this change.
With proper justification or this fixed.

Reviewed-by: Uma Shankar <uma.shankar@intel.com>

>+	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 int i915_hdcp_component_bind(struct device *i915_kdev,
> 				    struct device *mei_kdev, void *data)  { @@ -
>1288,7 +1302,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);
>@@ -1328,3 +1343,21 @@ 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;
>+
>+	/*
>+	 * CP_IRQ could be triggered due to 1. HDCP2.2 auth msgs availability,
>+	 * 2. link failure and 3. repeater reauth request. At present we dont
>+	 * handle the CP_IRQ for the HDCP2.2 auth msg availability for read.
>+	 * To handle other two causes for CP_IRQ we have the work_fn which is
>+	 * scheduled here.
>+	 */
>+	schedule_delayed_work(&hdcp->check_work, 0); }
>--
>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] 121+ messages in thread

* Re: [PATCH v10 08/40] drm/i915: Enable and Disable of HDCP2.2
  2019-01-31  6:59 ` [PATCH v10 08/40] drm/i915: Enable and Disable of HDCP2.2 Ramalingam C
@ 2019-02-04 14:17   ` Shankar, Uma
  0 siblings, 0 replies; 121+ messages in thread
From: Shankar, Uma @ 2019-02-04 14:17 UTC (permalink / raw)
  To: C, Ramalingam, intel-gfx, dri-devel, daniel.vetter, Winkler, Tomas



>-----Original Message-----
>From: dri-devel [mailto:dri-devel-bounces@lists.freedesktop.org] On Behalf Of
>Ramalingam C
>Sent: Thursday, January 31, 2019 12:29 PM
>To: intel-gfx@lists.freedesktop.org; dri-devel@lists.freedesktop.org;
>daniel.vetter@ffwll.ch; Winkler, Tomas <tomas.winkler@intel.com>; Shankar,
>Uma <uma.shankar@intel.com>
>Subject: [PATCH v10 08/40] drm/i915: Enable and Disable of HDCP2.2
>
>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
>v9:
>  bool is used in struct intel_hdcp. [Daniel]
>
>Signed-off-by: Ramalingam C <ramalingam.c@intel.com>
>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 13a41e8cf4ff..31c7a4577ca9 100644
>--- a/drivers/gpu/drm/i915/intel_drv.h
>+++ b/drivers/gpu/drm/i915/intel_drv.h
>@@ -389,6 +389,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 */

Make Panel as Sink.

>+	int (*hdcp_2_2_capable)(struct intel_digital_port *intel_dig_port,
>+				bool *capable);
> };
>
> struct intel_hdcp {
>@@ -406,6 +410,9 @@ struct intel_hdcp {
> 	/* Flag indicates whether this connector supports HDCP2.2 or not. */
> 	bool hdcp2_supported;
>
>+	/* HDCP2.2 Encryption status */
>+	bool 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 c1b057f1501b..fbf8b7893bfa 100644
>--- a/drivers/gpu/drm/i915/intel_hdcp.c
>+++ b/drivers/gpu/drm/i915/intel_hdcp.c
>@@ -74,6 +74,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); @@
>-1094,8 +1111,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_hdcp_comp_master *comp;
>@@ -1116,12 +1132,157 @@ int hdcp2_close_mei_session(struct
>intel_connector *connector)
> 	return ret;
> }
>
>-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 = true;
>+	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 = false;
>+
>+	return ret;
>+}
>+
> static void intel_hdcp_check_work(struct work_struct *work)  {
> 	struct intel_hdcp *hdcp = container_of(to_delayed_work(work),
>@@ -1270,22 +1431,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);

Looks like check_work is not called for 2.2. Fix this.

With this fixed.
Reviewed-by: Uma Shankar <uma.shankar@intel.com>

>+	}
>
>-	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;
> }
>@@ -1302,7 +1474,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
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

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

* RE: [PATCH v10 09/40] drm/i915: Implement HDCP2.2 receiver authentication
  2019-01-31  6:59 ` [PATCH v10 09/40] drm/i915: Implement HDCP2.2 receiver authentication Ramalingam C
@ 2019-02-04 14:20   ` Shankar, Uma
  0 siblings, 0 replies; 121+ messages in thread
From: Shankar, Uma @ 2019-02-04 14:20 UTC (permalink / raw)
  To: C, Ramalingam, intel-gfx, dri-devel, daniel.vetter, Winkler, Tomas



>-----Original Message-----
>From: C, Ramalingam
>Sent: Thursday, January 31, 2019 12:29 PM
>To: intel-gfx@lists.freedesktop.org; dri-devel@lists.freedesktop.org;
>daniel.vetter@ffwll.ch; Winkler, Tomas <tomas.winkler@intel.com>; Shankar,
>Uma <uma.shankar@intel.com>
>Cc: C, Ramalingam <ramalingam.c@intel.com>
>Subject: [PATCH v10 09/40] drm/i915: Implement HDCP2.2 receiver
>authentication
>
>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.
>v9:
>  bool is used in struct intel_hdcp [Daniel]
>  config_stream_type is redesigned [Daniel]
>
>Signed-off-by: Ramalingam C <ramalingam.c@intel.com>
>Reviewed-by: Daniel Vetter <daniel.vetter@ffwll.ch>

Looks ok to me.
Reviewed-by: Uma Shankar <uma.shankar@intel.com>

>---
> drivers/gpu/drm/i915/intel_drv.h  |  34 +++++++
>drivers/gpu/drm/i915/intel_hdcp.c | 197
>+++++++++++++++++++++++++++++++++++---
> 2 files changed, 216 insertions(+), 15 deletions(-)
>
>diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
>index 31c7a4577ca9..e6792304520a 100644
>--- a/drivers/gpu/drm/i915/intel_drv.h
>+++ b/drivers/gpu/drm/i915/intel_drv.h
>@@ -393,6 +393,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,
>+				  bool is_repeater, u8 type);
> };
>
> struct intel_hdcp {
>@@ -420,6 +436,24 @@ struct intel_hdcp {
> 	 */
> 	u8 content_type;
> 	struct hdcp_port_data port_data;
>+
>+	bool is_paired;
>+	bool 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 fbf8b7893bfa..1c81e17dc6c4 100644
>--- a/drivers/gpu/drm/i915/intel_hdcp.c
>+++ b/drivers/gpu/drm/i915/intel_hdcp.c
>@@ -17,6 +17,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)
>@@ -853,7 +854,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)  { @@ -878,7 +879,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,
>@@ -908,9 +909,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); @@
>-933,7 +933,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)  {
>@@ -958,7 +958,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)
> {
>@@ -983,7 +983,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)  { @@ -1008,9
>+1008,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); @@
>-1087,8 +1086,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); @@
>-1137,11 +1135,180 @@ 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;
>+
>+	/* 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]);
>+
>+	/*
>+	 * 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,
>+					      &hdcp->is_paired,
>+					      &msgs.no_stored_km, &size);
>+	if (ret < 0)
>+		return ret;
>+
>+	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 = 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;
>+	}
>+
>+	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;
>+	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 (shim->config_stream_type) {
>+		ret = shim->config_stream_type(intel_dig_port,
>+					       hdcp->is_repeater,
>+					       hdcp->content_type);
>+		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	[flat|nested] 121+ messages in thread

* Re: [PATCH v10 10/40] drm: helper functions for hdcp2 seq_num to from u32
  2019-01-31  6:59 ` [PATCH v10 10/40] drm: helper functions for hdcp2 seq_num to from u32 Ramalingam C
@ 2019-02-04 14:20   ` Shankar, Uma
  0 siblings, 0 replies; 121+ messages in thread
From: Shankar, Uma @ 2019-02-04 14:20 UTC (permalink / raw)
  To: C, Ramalingam, intel-gfx, dri-devel, daniel.vetter, Winkler, Tomas



>-----Original Message-----
>From: C, Ramalingam
>Sent: Thursday, January 31, 2019 12:29 PM
>To: intel-gfx@lists.freedesktop.org; dri-devel@lists.freedesktop.org;
>daniel.vetter@ffwll.ch; Winkler, Tomas <tomas.winkler@intel.com>; Shankar,
>Uma <uma.shankar@intel.com>
>Cc: C, Ramalingam <ramalingam.c@intel.com>
>Subject: [PATCH v10 10/40] drm: helper functions for hdcp2 seq_num to from u32
>
>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.
>
>v2:
>  Comment is updated. [Daniel]
>
>Signed-off-by: Ramalingam C <ramalingam.c@intel.com>
>Reviewed-by: Daniel Vetter <daniel.vetter@ffwll.ch>

Looks ok to me.
Reviewed-by: Uma Shankar <uma.shankar@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
>d6dfef8cff6a..7260b31af276 100644
>--- a/include/drm/drm_hdcp.h
>+++ b/include/drm/drm_hdcp.h
>@@ -252,4 +252,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))
>
>+/*
>+ * Helper functions to convert 24bit big endian hdcp sequence number to
>+ * host format and back
>+ */
>+static inline
>+u32 drm_hdcp2_seq_num_to_u32(u8 seq_num[HDCP_2_2_SEQ_NUM_LEN]) {
>+	return (u32)(seq_num[2] | seq_num[1] << 8 | seq_num[0] << 16); }
>+
>+static inline
>+void drm_hdcp2_u32_to_seq_num(u8 seq_num[HDCP_2_2_SEQ_NUM_LEN],
>u32
>+val) {
>+	seq_num[0] = val >> 16;
>+	seq_num[1] = val >> 8;
>+	seq_num[2] = val;
>+}
>+
> #endif
>--
>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] 121+ messages in thread

* Re: [PATCH v10 11/40] drm/i915: Implement HDCP2.2 repeater authentication
  2019-01-31  6:59 ` [PATCH v10 11/40] drm/i915: Implement HDCP2.2 repeater authentication Ramalingam C
@ 2019-02-04 14:21   ` Shankar, Uma
  0 siblings, 0 replies; 121+ messages in thread
From: Shankar, Uma @ 2019-02-04 14:21 UTC (permalink / raw)
  To: C, Ramalingam, intel-gfx, dri-devel, daniel.vetter, Winkler, Tomas



>-----Original Message-----
>From: C, Ramalingam
>Sent: Thursday, January 31, 2019 12:29 PM
>To: intel-gfx@lists.freedesktop.org; dri-devel@lists.freedesktop.org;
>daniel.vetter@ffwll.ch; Winkler, Tomas <tomas.winkler@intel.com>; Shankar,
>Uma <uma.shankar@intel.com>
>Cc: C, Ramalingam <ramalingam.c@intel.com>
>Subject: [PATCH v10 11/40] drm/i915: Implement HDCP2.2 repeater
>authentication
>
>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]
>v9:
>  %s/__swab16/cpu_to_be16. [Tomas]
>
>Signed-off-by: Ramalingam C <ramalingam.c@intel.com>
>Reviewed-by: Daniel Vetter <daniel.vetter@ffwll.ch>

Looks ok to me.
Reviewed-by: Uma Shankar <uma.shankar@intel.com>

>---
> drivers/gpu/drm/i915/intel_hdcp.c | 125
>+++++++++++++++++++++++++++++++++++++-
> 1 file changed, 123 insertions(+), 2 deletions(-)
>
>diff --git a/drivers/gpu/drm/i915/intel_hdcp.c
>b/drivers/gpu/drm/i915/intel_hdcp.c
>index 1c81e17dc6c4..3b8d3a4b5e6e 100644
>--- a/drivers/gpu/drm/i915/intel_hdcp.c
>+++ b/drivers/gpu/drm/i915/intel_hdcp.c
>@@ -1032,7 +1032,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,
>@@ -1061,7 +1061,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)  { @@ -
>1270,6 +1270,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 = 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 */
>+	seq_num_v =
>drm_hdcp2_seq_num_to_u32(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);
>@@ -1303,6 +1416,14 @@ static int hdcp2_authenticate_sink(struct
>intel_connector *connector)
> 			return ret;
> 	}
>
>+	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;
> 	ret = hdcp2_authenticate_port(connector);
> 	if (ret < 0)
>--
>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] 121+ messages in thread

* Re: [PATCH v10 12/40] drm: HDCP2.2 link check period
  2019-01-31  6:59 ` [PATCH v10 12/40] drm: HDCP2.2 link check period Ramalingam C
@ 2019-02-04 14:24   ` Shankar, Uma
  2019-02-04 14:50     ` C, Ramalingam
  0 siblings, 1 reply; 121+ messages in thread
From: Shankar, Uma @ 2019-02-04 14:24 UTC (permalink / raw)
  To: C, Ramalingam, intel-gfx, dri-devel, daniel.vetter, Winkler, Tomas



>-----Original Message-----
>From: C, Ramalingam
>Sent: Thursday, January 31, 2019 12:29 PM
>To: intel-gfx@lists.freedesktop.org; dri-devel@lists.freedesktop.org;
>daniel.vetter@ffwll.ch; Winkler, Tomas <tomas.winkler@intel.com>; Shankar,
>Uma <uma.shankar@intel.com>
>Cc: C, Ramalingam <ramalingam.c@intel.com>
>Subject: [PATCH v10 12/40] drm: HDCP2.2 link check period
>
>Time period for HDCP2.2 link check.
>
>Signed-off-by: Ramalingam C <ramalingam.c@intel.com>
>Reviewed-by: Daniel Vetter <daniel.vetter@ffwll.ch>

Not sure if we need a separate patch for this. Could be merged where check_link is
introduced for hdcp2.2.

If there is a valid reasoning, no hard objection and it looks ok in general. So

Reviewed-by: Uma Shankar <uma.shankar@intel.com>

>---
> include/drm/drm_hdcp.h | 1 +
> 1 file changed, 1 insertion(+)
>
>diff --git a/include/drm/drm_hdcp.h b/include/drm/drm_hdcp.h index
>7260b31af276..d4e98b11b4aa 100644
>--- a/include/drm/drm_hdcp.h
>+++ b/include/drm/drm_hdcp.h
>@@ -13,6 +13,7 @@
>
> /* 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
>
> /* 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] 121+ messages in thread

* Re: [PATCH v10 13/40] drm/i915: Implement HDCP2.2 link integrity check
  2019-01-31  6:59 ` [PATCH v10 13/40] drm/i915: Implement HDCP2.2 link integrity check Ramalingam C
@ 2019-02-04 14:28   ` Shankar, Uma
  0 siblings, 0 replies; 121+ messages in thread
From: Shankar, Uma @ 2019-02-04 14:28 UTC (permalink / raw)
  To: C, Ramalingam, intel-gfx, dri-devel, daniel.vetter, Winkler, Tomas



>-----Original Message-----
>From: C, Ramalingam
>Sent: Thursday, January 31, 2019 12:29 PM
>To: intel-gfx@lists.freedesktop.org; dri-devel@lists.freedesktop.org;
>daniel.vetter@ffwll.ch; Winkler, Tomas <tomas.winkler@intel.com>; Shankar,
>Uma <uma.shankar@intel.com>
>Cc: C, Ramalingam <ramalingam.c@intel.com>
>Subject: [PATCH v10 13/40] drm/i915: Implement HDCP2.2 link integrity check
>
>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]
>v9:
>  enum check_link_status is defined at intel_drv.h [Daniel]
>
>Signed-off-by: Ramalingam C <ramalingam.c@intel.com>
>Reviewed-by: Uma Shankar <uma.shankar@intel.com>

The latest version also looks ok. You can keep my RB.

>---
> drivers/gpu/drm/i915/intel_drv.h  | 10 +++++  drivers/gpu/drm/i915/intel_hdcp.c
>| 88 ++++++++++++++++++++++++++++++++++++---
> 2 files changed, 93 insertions(+), 5 deletions(-)
>
>diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
>index e6792304520a..747fe7361287 100644
>--- a/drivers/gpu/drm/i915/intel_drv.h
>+++ b/drivers/gpu/drm/i915/intel_drv.h
>@@ -314,6 +314,13 @@ struct intel_panel {
>
> struct intel_digital_port;
>
>+enum check_link_response {
>+	HDCP_LINK_PROTECTED	= 0,
>+	HDCP_TOPOLOGY_CHANGE,
>+	HDCP_LINK_INTEGRITY_FAILURE,
>+	HDCP_REAUTH_REQUEST
>+};
>+
> /*
>  * This structure serves as a translation layer between the generic HDCP code
>  * and the bus-specific code. What that means is that HDCP over HDMI differs
>@@ -409,6 +416,9 @@ struct intel_hdcp_shim {
> 	 */
> 	int (*config_stream_type)(struct intel_digital_port *intel_dig_port,
> 				  bool is_repeater, u8 type);
>+
>+	/* 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 3b8d3a4b5e6e..3feff921a547 100644
>--- a/drivers/gpu/drm/i915/intel_hdcp.c
>+++ b/drivers/gpu/drm/i915/intel_hdcp.c
>@@ -102,6 +102,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)  { @@ -
>1571,6 +1581,69 @@ 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 == 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 void intel_hdcp_check_work(struct work_struct *work)  {
> 	struct intel_hdcp *hdcp = container_of(to_delayed_work(work),
>@@ -1578,7 +1651,10 @@ static void intel_hdcp_check_work(struct work_struct
>*work)
> 					       check_work);
> 	struct intel_connector *connector = intel_hdcp_to_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);
> }
>@@ -1719,6 +1795,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)
>@@ -1730,18 +1807,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);
> 	}
>--
>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] 121+ messages in thread

* Re: [PATCH v10 14/40] drm/i915: Handle HDCP2.2 downstream topology change
  2019-01-31  6:59 ` [PATCH v10 14/40] drm/i915: Handle HDCP2.2 downstream topology change Ramalingam C
@ 2019-02-04 14:31   ` Shankar, Uma
  0 siblings, 0 replies; 121+ messages in thread
From: Shankar, Uma @ 2019-02-04 14:31 UTC (permalink / raw)
  To: C, Ramalingam, intel-gfx, dri-devel, daniel.vetter, Winkler, Tomas



>-----Original Message-----
>From: C, Ramalingam
>Sent: Thursday, January 31, 2019 12:30 PM
>To: intel-gfx@lists.freedesktop.org; dri-devel@lists.freedesktop.org;
>daniel.vetter@ffwll.ch; Winkler, Tomas <tomas.winkler@intel.com>; Shankar,
>Uma <uma.shankar@intel.com>
>Cc: C, Ramalingam <ramalingam.c@intel.com>
>Subject: [PATCH v10 14/40] drm/i915: Handle HDCP2.2 downstream topology
>change
>
>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>

The latest version is ok. You can keep the RB.

>---
> 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 3feff921a547..7ff29fb0aa2f 100644
>--- a/drivers/gpu/drm/i915/intel_hdcp.c
>+++ b/drivers/gpu/drm/i915/intel_hdcp.c
>@@ -1617,8 +1617,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 == 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

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

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

* Re: [PATCH v10 15/40] drm: removing the DP Errata msg and its msg id
  2019-01-31  6:59 ` [PATCH v10 15/40] drm: removing the DP Errata msg and its msg id Ramalingam C
  2019-01-31  8:02   ` Daniel Vetter
@ 2019-02-04 14:35   ` Shankar, Uma
  1 sibling, 0 replies; 121+ messages in thread
From: Shankar, Uma @ 2019-02-04 14:35 UTC (permalink / raw)
  To: C, Ramalingam, intel-gfx, dri-devel, daniel.vetter, Winkler, Tomas



>-----Original Message-----
>From: C, Ramalingam
>Sent: Thursday, January 31, 2019 12:30 PM
>To: intel-gfx@lists.freedesktop.org; dri-devel@lists.freedesktop.org;
>daniel.vetter@ffwll.ch; Winkler, Tomas <tomas.winkler@intel.com>; Shankar,
>Uma <uma.shankar@intel.com>
>Cc: C, Ramalingam <ramalingam.c@intel.com>
>Subject: [PATCH v10 15/40] drm: removing the DP Errata msg and its msg id
>
>Since DP ERRATA message is not defined at spec, those structure definition is
>removed from drm_hdcp.h

I believe we still want to have it but inside the driver isn't it ?, would be good to
add a comment on that.

With that fixed.
Reviewed-by: Uma Shankar <uma.shankar@intel.com>
>
>Signed-off-by: Ramalingam C <ramalingam.c@intel.com>
>Suggested-by: Daniel Vetter <daniel.vetter@ffwll.ch>


>---
> include/drm/drm_hdcp.h | 6 ------
> 1 file changed, 6 deletions(-)
>
>diff --git a/include/drm/drm_hdcp.h b/include/drm/drm_hdcp.h index
>d4e98b11b4aa..f243408ecf26 100644
>--- a/include/drm/drm_hdcp.h
>+++ b/include/drm/drm_hdcp.h
>@@ -69,7 +69,6 @@
> #define HDCP_2_2_REP_SEND_ACK			15
> #define HDCP_2_2_REP_STREAM_MANAGE		16
> #define HDCP_2_2_REP_STREAM_READY		17
>-#define HDCP_2_2_ERRATA_DP_STREAM_TYPE		50
>
> #define HDCP_2_2_RTX_LEN			8
> #define HDCP_2_2_RRX_LEN			8
>@@ -220,11 +219,6 @@ struct hdcp2_rep_stream_ready {
> 	u8	m_prime[HDCP_2_2_MPRIME_LEN];
> } __packed;
>
>-struct hdcp2_dp_errata_stream_type {
>-	u8	msg_id;
>-	u8	stream_type;
>-} __packed;
>-
> /* HDCP2.2 TIMEOUTs in mSec */
> #define HDCP_2_2_CERT_TIMEOUT_MS		100
> #define HDCP_2_2_HPRIME_NO_PAIRED_TIMEOUT_MS	1000
>--
>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] 121+ messages in thread

* Re: [PATCH v10 07/40] drm/i915: hdcp1.4 CP_IRQ handling and SW encryption tracking
  2019-02-04 14:09   ` Shankar, Uma
@ 2019-02-04 14:43     ` C, Ramalingam
  0 siblings, 0 replies; 121+ messages in thread
From: C, Ramalingam @ 2019-02-04 14:43 UTC (permalink / raw)
  To: Shankar, Uma, intel-gfx, dri-devel, daniel.vetter, Winkler, Tomas



On 2/4/2019 7:39 PM, Shankar, Uma wrote:
>
>> -----Original Message-----
>> From: C, Ramalingam
>> Sent: Thursday, January 31, 2019 12:29 PM
>> To: intel-gfx@lists.freedesktop.org; dri-devel@lists.freedesktop.org;
>> daniel.vetter@ffwll.ch; Winkler, Tomas <tomas.winkler@intel.com>; Shankar,
>> Uma <uma.shankar@intel.com>
>> Cc: C, Ramalingam <ramalingam.c@intel.com>
>> Subject: [PATCH v10 07/40] drm/i915: hdcp1.4 CP_IRQ handling and SW
>> encryption tracking
>>
>> "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.
>>
>> v2:
>>   bool is used in struct for the cleaner coding. [Daniel]
>>   check_link work_fn is scheduled for cp_irq handling [Daniel]
>>
>> 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 |
>> 73 ++++++++++++++++++++++++++++-----------
>> 3 files changed, 58 insertions(+), 22 deletions(-)
>>
>> diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
>> index 815ee68efa2f..9ce05819fc11 100644
>> --- a/drivers/gpu/drm/i915/intel_dp.c
>> +++ b/drivers/gpu/drm/i915/intel_dp.c
>> @@ -4776,7 +4776,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 63e009286d5f..13a41e8cf4ff 100644
>> --- a/drivers/gpu/drm/i915/intel_drv.h
>> +++ b/drivers/gpu/drm/i915/intel_drv.h
>> @@ -399,6 +399,9 @@ struct intel_hdcp {
>> 	struct delayed_work check_work;
>> 	struct work_struct prop_work;
>>
>> +	/* HDCP1.4 Encryption status */
>> +	bool hdcp_encrypted;
>> +
>> 	/* HDCP2.2 related definitions */
>> 	/* Flag indicates whether this connector supports HDCP2.2 or not. */
>> 	bool hdcp2_supported;
>> @@ -2073,10 +2076,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 e0bb5f32ba90..c1b057f1501b 100644
>> --- a/drivers/gpu/drm/i915/intel_hdcp.c
>> +++ b/drivers/gpu/drm/i915/intel_hdcp.c
>> @@ -74,6 +74,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)  { @@ -
>> 668,6 +678,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 = false;
>> 	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)) {
>> @@ -713,8 +724,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 = true;
>> 			return 0;
>> +		}
>>
>> 		DRM_DEBUG_KMS("HDCP Auth failure (%d)\n", ret);
>>
>> @@ -741,16 +754,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;
>> @@ -791,18 +805,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, @@ -
>> 1120,6 +1122,18 @@ int hdcp2_deauthenticate_port(struct intel_connector
>> *connector)
>> 	return hdcp2_close_mei_session(connector);
>> }
>>
>> +static void intel_hdcp_check_work(struct work_struct *work) {
> Why this code movement for check_work. If not intentional no need for this change.
> With proper justification or this fixed.
All common(1.4 and 2.2) HDCP functions (enable, disable, check_work etc) 
are gathered together
Thanks for R-b.

--Ram
>
> Reviewed-by: Uma Shankar <uma.shankar@intel.com>
>
>> +	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 int i915_hdcp_component_bind(struct device *i915_kdev,
>> 				    struct device *mei_kdev, void *data)  { @@ -
>> 1288,7 +1302,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);
>> @@ -1328,3 +1343,21 @@ 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;
>> +
>> +	/*
>> +	 * CP_IRQ could be triggered due to 1. HDCP2.2 auth msgs availability,
>> +	 * 2. link failure and 3. repeater reauth request. At present we dont
>> +	 * handle the CP_IRQ for the HDCP2.2 auth msg availability for read.
>> +	 * To handle other two causes for CP_IRQ we have the work_fn which is
>> +	 * scheduled here.
>> +	 */
>> +	schedule_delayed_work(&hdcp->check_work, 0); }
>> --
>> 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] 121+ messages in thread

* Re: [PATCH v10 12/40] drm: HDCP2.2 link check period
  2019-02-04 14:24   ` Shankar, Uma
@ 2019-02-04 14:50     ` C, Ramalingam
  0 siblings, 0 replies; 121+ messages in thread
From: C, Ramalingam @ 2019-02-04 14:50 UTC (permalink / raw)
  To: Shankar, Uma, intel-gfx, dri-devel, daniel.vetter, Winkler, Tomas



On 2/4/2019 7:54 PM, Shankar, Uma wrote:
>
>> -----Original Message-----
>> From: C, Ramalingam
>> Sent: Thursday, January 31, 2019 12:29 PM
>> To: intel-gfx@lists.freedesktop.org; dri-devel@lists.freedesktop.org;
>> daniel.vetter@ffwll.ch; Winkler, Tomas <tomas.winkler@intel.com>; Shankar,
>> Uma <uma.shankar@intel.com>
>> Cc: C, Ramalingam <ramalingam.c@intel.com>
>> Subject: [PATCH v10 12/40] drm: HDCP2.2 link check period
>>
>> Time period for HDCP2.2 link check.
>>
>> Signed-off-by: Ramalingam C <ramalingam.c@intel.com>
>> Reviewed-by: Daniel Vetter <daniel.vetter@ffwll.ch>
> Not sure if we need a separate patch for this. Could be merged where check_link is
> introduced for hdcp2.2.
>
> If there is a valid reasoning, no hard objection and it looks ok in general. So
drm level change is convenient to have in separate patch to get approval 
from dri-devel.

--Ram
>
> Reviewed-by: Uma Shankar <uma.shankar@intel.com>
>
>> ---
>> include/drm/drm_hdcp.h | 1 +
>> 1 file changed, 1 insertion(+)
>>
>> diff --git a/include/drm/drm_hdcp.h b/include/drm/drm_hdcp.h index
>> 7260b31af276..d4e98b11b4aa 100644
>> --- a/include/drm/drm_hdcp.h
>> +++ b/include/drm/drm_hdcp.h
>> @@ -13,6 +13,7 @@
>>
>> /* 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
>>
>> /* 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	[flat|nested] 121+ messages in thread

* Re: [PATCH v10 02/40] i915/snd_hdac: I915 subcomponent for the snd_hdac
  2019-01-31  6:59 ` [PATCH v10 02/40] i915/snd_hdac: I915 subcomponent for the snd_hdac Ramalingam C
@ 2019-02-04 15:00   ` Daniel Vetter
  2019-02-04 15:09     ` Takashi Iwai
  0 siblings, 1 reply; 121+ messages in thread
From: Daniel Vetter @ 2019-02-04 15:00 UTC (permalink / raw)
  To: Ramalingam C
  Cc: Rafael J . Wysocki, daniel.vetter, intel-gfx, Rodrigo Vivi,
	Takashi Iwai, dri-devel, Jaroslav Kysela, uma.shankar,
	Greg Kroah-Hartman, Russell King, tomas.winkler

On Thu, Jan 31, 2019 at 12:29:18PM +0530, Ramalingam C wrote:
> From: Daniel Vetter <daniel.vetter@ffwll.ch>
> 
> Since we need multiple components for I915 for different purposes
> (Audio & Mei_hdcp), we adopt the subcomponents methodology introduced
> by the previous patch (mentioned below).
> 
> 	Author: Daniel Vetter <daniel.vetter@ffwll.ch>
> 	Date:   Mon Jan 28 17:08:20 2019 +0530
> 
> 	    components: multiple components for a device
> 
> Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
> Signed-off-by: Ramalingam C <ramalingam.c@intel.com>
> cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
> cc: Russell King <rmk+kernel@arm.linux.org.uk>
> cc: Rafael J. Wysocki <rafael@kernel.org>
> cc: Jaroslav Kysela <perex@perex.cz>
> cc: Takashi Iwai <tiwai@suse.com>
> cc: Rodrigo Vivi <rodrigo.vivi@intel.com>
> cc: Jani Nikula <jani.nikula@linux.intel.com>

Takashi, can you pls take a look and ack for merging through drm-intel? We
can also do a topic branch in case this conflicts with something on the
audio side.

Thanks, Daniel

> ---
>  drivers/gpu/drm/i915/intel_audio.c | 4 +++-
>  include/drm/i915_component.h       | 4 ++++
>  include/sound/hda_component.h      | 5 +++--
>  sound/hda/hdac_component.c         | 4 ++--
>  sound/hda/hdac_i915.c              | 6 ++++--
>  5 files changed, 16 insertions(+), 7 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/intel_audio.c b/drivers/gpu/drm/i915/intel_audio.c
> index de26cd0a5497..5104c6bbd66f 100644
> --- a/drivers/gpu/drm/i915/intel_audio.c
> +++ b/drivers/gpu/drm/i915/intel_audio.c
> @@ -984,7 +984,9 @@ void i915_audio_component_init(struct drm_i915_private *dev_priv)
>  {
>  	int ret;
>  
> -	ret = component_add(dev_priv->drm.dev, &i915_audio_component_bind_ops);
> +	ret = component_add_typed(dev_priv->drm.dev,
> +				  &i915_audio_component_bind_ops,
> +				  I915_COMPONENT_AUDIO);
>  	if (ret < 0) {
>  		DRM_ERROR("failed to add audio component (%d)\n", ret);
>  		/* continue with reduced functionality */
> diff --git a/include/drm/i915_component.h b/include/drm/i915_component.h
> index fca22d463e1b..72fbb037f9b3 100644
> --- a/include/drm/i915_component.h
> +++ b/include/drm/i915_component.h
> @@ -26,6 +26,10 @@
>  
>  #include "drm_audio_component.h"
>  
> +enum i915_component_type {
> +	I915_COMPONENT_AUDIO = 1,
> +};
> +
>  /* MAX_PORT is the number of port
>   * It must be sync with I915_MAX_PORTS defined i915_drv.h
>   */
> diff --git a/include/sound/hda_component.h b/include/sound/hda_component.h
> index 2ec31b358950..d4804c72d959 100644
> --- a/include/sound/hda_component.h
> +++ b/include/sound/hda_component.h
> @@ -20,7 +20,7 @@ int snd_hdac_acomp_get_eld(struct hdac_device *codec, hda_nid_t nid, int dev_id,
>  			   bool *audio_enabled, char *buffer, int max_bytes);
>  int snd_hdac_acomp_init(struct hdac_bus *bus,
>  			const struct drm_audio_component_audio_ops *aops,
> -			int (*match_master)(struct device *, void *),
> +			int (*match_master)(struct device *, int, void *),
>  			size_t extra_size);
>  int snd_hdac_acomp_exit(struct hdac_bus *bus);
>  int snd_hdac_acomp_register_notifier(struct hdac_bus *bus,
> @@ -47,7 +47,8 @@ static inline int snd_hdac_acomp_get_eld(struct hdac_device *codec, hda_nid_t ni
>  }
>  static inline int snd_hdac_acomp_init(struct hdac_bus *bus,
>  				      const struct drm_audio_component_audio_ops *aops,
> -				      int (*match_master)(struct device *, void *),
> +				      int (*match_master)(struct device *,
> +							  int, void *),
>  				      size_t extra_size)
>  {
>  	return -ENODEV;
> diff --git a/sound/hda/hdac_component.c b/sound/hda/hdac_component.c
> index a6d37b9d6413..5c95933e739a 100644
> --- a/sound/hda/hdac_component.c
> +++ b/sound/hda/hdac_component.c
> @@ -269,7 +269,7 @@ EXPORT_SYMBOL_GPL(snd_hdac_acomp_register_notifier);
>   */
>  int snd_hdac_acomp_init(struct hdac_bus *bus,
>  			const struct drm_audio_component_audio_ops *aops,
> -			int (*match_master)(struct device *, void *),
> +			int (*match_master)(struct device *, int, void *),
>  			size_t extra_size)
>  {
>  	struct component_match *match = NULL;
> @@ -288,7 +288,7 @@ int snd_hdac_acomp_init(struct hdac_bus *bus,
>  	bus->audio_component = acomp;
>  	devres_add(dev, acomp);
>  
> -	component_match_add(dev, &match, match_master, bus);
> +	component_match_add_typed(dev, &match, match_master, bus);
>  	ret = component_master_add_with_match(dev, &hdac_component_master_ops,
>  					      match);
>  	if (ret < 0)
> diff --git a/sound/hda/hdac_i915.c b/sound/hda/hdac_i915.c
> index 617ff1aa818f..7aee090e3d27 100644
> --- a/sound/hda/hdac_i915.c
> +++ b/sound/hda/hdac_i915.c
> @@ -82,9 +82,11 @@ void snd_hdac_i915_set_bclk(struct hdac_bus *bus)
>  }
>  EXPORT_SYMBOL_GPL(snd_hdac_i915_set_bclk);
>  
> -static int i915_component_master_match(struct device *dev, void *data)
> +static int i915_component_master_match(struct device *dev, int subcomponent,
> +				       void *data)
>  {
> -	return !strcmp(dev->driver->name, "i915");
> +	return !strcmp(dev->driver->name, "i915") &&
> +	       subcomponent == I915_COMPONENT_AUDIO;
>  }
>  
>  /* check whether intel graphics is present */
> -- 
> 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] 121+ messages in thread

* Re: [PATCH v10 02/40] i915/snd_hdac: I915 subcomponent for the snd_hdac
  2019-02-04 15:00   ` Daniel Vetter
@ 2019-02-04 15:09     ` Takashi Iwai
  0 siblings, 0 replies; 121+ messages in thread
From: Takashi Iwai @ 2019-02-04 15:09 UTC (permalink / raw)
  To: Daniel Vetter
  Cc: Rafael J . Wysocki, tiwai, daniel.vetter, intel-gfx,
	Greg Kroah-Hartman, Jaroslav Kysela, dri-devel, Russell King,
	tomas.winkler

On Mon, 04 Feb 2019 16:00:18 +0100,
Daniel Vetter wrote:
> 
> On Thu, Jan 31, 2019 at 12:29:18PM +0530, Ramalingam C wrote:
> > From: Daniel Vetter <daniel.vetter@ffwll.ch>
> > 
> > Since we need multiple components for I915 for different purposes
> > (Audio & Mei_hdcp), we adopt the subcomponents methodology introduced
> > by the previous patch (mentioned below).
> > 
> > 	Author: Daniel Vetter <daniel.vetter@ffwll.ch>
> > 	Date:   Mon Jan 28 17:08:20 2019 +0530
> > 
> > 	    components: multiple components for a device
> > 
> > Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
> > Signed-off-by: Ramalingam C <ramalingam.c@intel.com>
> > cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
> > cc: Russell King <rmk+kernel@arm.linux.org.uk>
> > cc: Rafael J. Wysocki <rafael@kernel.org>
> > cc: Jaroslav Kysela <perex@perex.cz>
> > cc: Takashi Iwai <tiwai@suse.com>
> > cc: Rodrigo Vivi <rodrigo.vivi@intel.com>
> > cc: Jani Nikula <jani.nikula@linux.intel.com>
> 
> Takashi, can you pls take a look and ack for merging through drm-intel? We
> can also do a topic branch in case this conflicts with something on the
> audio side.

I'm fine with the change as long as others agree with this API
extension.

Reviewed-by: Takashi Iwai <tiwai@suse.de>


thanks,

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

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

* Re: [PATCH v10 38/40] drm/i915: Fix KBL HDCP2.2 encrypt status signalling
  2019-01-31  6:59 ` [PATCH v10 38/40] drm/i915: Fix KBL HDCP2.2 encrypt status signalling Ramalingam C
@ 2019-02-04 15:32   ` C, Ramalingam
  2019-02-05  8:54     ` Daniel Vetter
  2019-02-04 16:35   ` Shankar, Uma
  1 sibling, 1 reply; 121+ messages in thread
From: C, Ramalingam @ 2019-02-04 15:32 UTC (permalink / raw)
  To: intel-gfx, dri-devel, daniel.vetter, tomas.winkler, uma.shankar

daniel,

Could you please review this patch too.? Already Updated this as per 
your previous review comment.

--Ram

On 1/31/2019 12:29 PM, Ramalingam C wrote:
> Implement the required WA sequence for KBL to fix the
> incorrect positioning of the window of oppurtunity and enc_en
> signalling.
>
> v2:
>    WA is moved into the toggle_signalling [Daniel]
>
> Signed-off-by: Ramalingam C <ramalingam.c@intel.com>
> ---
>   drivers/gpu/drm/i915/intel_hdmi.c | 42 +++++++++++++++++++++++++++++++++++++++
>   1 file changed, 42 insertions(+)
>
> diff --git a/drivers/gpu/drm/i915/intel_hdmi.c b/drivers/gpu/drm/i915/intel_hdmi.c
> index 2c4bf6d0c39f..ae20288f7bbf 100644
> --- a/drivers/gpu/drm/i915/intel_hdmi.c
> +++ b/drivers/gpu/drm/i915/intel_hdmi.c
> @@ -1083,10 +1083,44 @@ int intel_hdmi_hdcp_read_v_prime_part(struct intel_digital_port *intel_dig_port,
>   	return ret;
>   }
>   
> +static int 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 drm_crtc *crtc = connector->base.state->crtc;
> +	struct intel_crtc *intel_crtc = container_of(crtc,
> +						     struct intel_crtc, base);
> +	u32 scanline;
> +	int ret;
> +
> +	for (;;) {
> +		scanline = I915_READ(PIPEDSL(intel_crtc->pipe));
> +		if (scanline > 100 && scanline < 200)
> +			break;
> +		usleep_range(25, 50);
> +	}
> +
> +	ret = intel_ddi_toggle_hdcp_signalling(&intel_dig_port->base, false);
> +	if (ret) {
> +		DRM_ERROR("Disable HDCP signalling failed (%d)\n", ret);
> +		return ret;
> +	}
> +	ret = intel_ddi_toggle_hdcp_signalling(&intel_dig_port->base, true);
> +	if (ret) {
> +		DRM_ERROR("Enable HDCP signalling failed (%d)\n", ret);
> +		return ret;
> +	}
> +
> +	return 0;
> +}
> +
>   static
>   int intel_hdmi_hdcp_toggle_signalling(struct intel_digital_port *intel_dig_port,
>   				      bool enable)
>   {
> +	struct intel_hdmi *hdmi = &intel_dig_port->hdmi;
> +	struct intel_connector *connector = hdmi->attached_connector;
> +	struct drm_i915_private *dev_priv = to_i915(connector->base.dev);
>   	int ret;
>   
>   	if (!enable)
> @@ -1098,6 +1132,14 @@ int intel_hdmi_hdcp_toggle_signalling(struct intel_digital_port *intel_dig_port,
>   			  enable ? "Enable" : "Disable", ret);
>   		return ret;
>   	}
> +
> +	/*
> +	 * WA: To fix incorrect positioning of the window of
> +	 * opportunity and enc_en signalling in KABYLAKE.
> +	 */
> +	if (IS_KABYLAKE(dev_priv) && enable)
> +		return kbl_repositioning_enc_en_signal(connector);
> +
>   	return 0;
>   }
>   

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

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

* Re: [PATCH 2/2] components: multiple components for a device
  2019-01-31 14:46     ` [PATCH 2/2] components: multiple components for a device Daniel Vetter
@ 2019-02-04 16:00         ` Daniel Vetter
  0 siblings, 0 replies; 121+ messages in thread
From: Daniel Vetter @ 2019-02-04 16:00 UTC (permalink / raw)
  To: DRI Development
  Cc: LKML, Daniel Vetter, Ramalingam C, Greg Kroah-Hartman,
	Russell King, Rafael J . Wysocki, Jaroslav Kysela, Takashi Iwai,
	Rodrigo Vivi, Jani Nikula

On Thu, Jan 31, 2019 at 03:46:40PM +0100, Daniel Vetter wrote:
> Component framework is extended to support multiple components for
> a struct device. These will be matched with different masters based on
> its sub component value.
> 
> We are introducing this, as I915 needs two different components
> with different subcomponent value, which will be matched to two
> different component masters(Audio and HDCP) based on the subcomponent
> values.
> 
> v2: Add documenation.
> 
> Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch> (v1 code)
> Signed-off-by: Ramalingam C <ramalingam.c@intel.com> (v1 commit message)
> Cc: Ramalingam C <ramalingam.c@intel.com>
> Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
> Cc: Russell King <rmk+kernel@arm.linux.org.uk>
> Cc: Rafael J. Wysocki <rafael@kernel.org>
> Cc: Jaroslav Kysela <perex@perex.cz>
> Cc: Takashi Iwai <tiwai@suse.com>
> Cc: Rodrigo Vivi <rodrigo.vivi@intel.com>
> Cc: Jani Nikula <jani.nikula@linux.intel.com>
> Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>

Hi Greg&Russell,

Now that there's nice documentation on everything, any comments on these
two patches?

Thanks, Daniel

> ---
>  drivers/base/component.c  | 159 +++++++++++++++++++++++++++++---------
>  include/linux/component.h |  10 ++-
>  2 files changed, 130 insertions(+), 39 deletions(-)
> 
> diff --git a/drivers/base/component.c b/drivers/base/component.c
> index e5b04bce8544..eb7915fc5278 100644
> --- a/drivers/base/component.c
> +++ b/drivers/base/component.c
> @@ -48,6 +48,7 @@ struct component;
>  struct component_match_array {
>  	void *data;
>  	int (*compare)(struct device *, void *);
> +	int (*compare_typed)(struct device *, int, void *);
>  	void (*release)(struct device *, void *);
>  	struct component *component;
>  	bool duplicate;
> @@ -75,6 +76,7 @@ struct component {
>  	bool bound;
>  
>  	const struct component_ops *ops;
> +	int subcomponent;
>  	struct device *dev;
>  };
>  
> @@ -159,7 +161,7 @@ static struct master *__master_find(struct device *dev,
>  }
>  
>  static struct component *find_component(struct master *master,
> -	int (*compare)(struct device *, void *), void *compare_data)
> +	struct component_match_array *mc)
>  {
>  	struct component *c;
>  
> @@ -167,8 +169,13 @@ static struct component *find_component(struct master *master,
>  		if (c->master && c->master != master)
>  			continue;
>  
> -		if (compare(c->dev, compare_data))
> +		if (mc->compare_typed) {
> +			if (mc->compare_typed(c->dev, c->subcomponent,
> +					      mc->data))
> +				return c;
> +		} else if (mc->compare(c->dev, mc->data)) {
>  			return c;
> +		}
>  	}
>  
>  	return NULL;
> @@ -193,7 +200,7 @@ static int find_components(struct master *master)
>  		if (match->compare[i].component)
>  			continue;
>  
> -		c = find_component(master, mc->compare, mc->data);
> +		c = find_component(master, mc);
>  		if (!c) {
>  			ret = -ENXIO;
>  			break;
> @@ -328,29 +335,12 @@ static int component_match_realloc(struct device *dev,
>  	return 0;
>  }
>  
> -/**
> - * component_match_add_release - add a compent match with release callback
> - * @master: device with the aggregate driver
> - * @matchptr: pointer to the list of component matches
> - * @release: release function for @compare_data
> - * @compare: compare function to match against all components
> - * @compare_data: opaque pointer passed to the @compare function
> - *
> - * This adds a new component match to the list stored in @matchptr, which the
> - * @master aggregate driver needs to function. @matchptr must be initialized to
> - * NULL before adding the first match.
> - *
> - * The allocated match list in @matchptr is automatically released using devm
> - * actions. At that point @release will be called, to free any references held
> - * by @compare_data, e.g. when @compare_data is a &device_node that must be
> - * released with of_node_put().
> - *
> - * See also component_match_add().
> - */
> -void component_match_add_release(struct device *master,
> +static void __component_match_add(struct device *master,
>  	struct component_match **matchptr,
>  	void (*release)(struct device *, void *),
> -	int (*compare)(struct device *, void *), void *compare_data)
> +	int (*compare)(struct device *, void *),
> +	int (*compare_typed)(struct device *, int, void *),
> +	void *compare_data)
>  {
>  	struct component_match *match = *matchptr;
>  
> @@ -382,13 +372,69 @@ void component_match_add_release(struct device *master,
>  	}
>  
>  	match->compare[match->num].compare = compare;
> +	match->compare[match->num].compare_typed = compare_typed;
>  	match->compare[match->num].release = release;
>  	match->compare[match->num].data = compare_data;
>  	match->compare[match->num].component = NULL;
>  	match->num++;
>  }
> +
> +/**
> + * component_match_add_release - add a compent match with release callback
> + * @master: device with the aggregate driver
> + * @matchptr: pointer to the list of component matches
> + * @release: release function for @compare_data
> + * @compare: compare function to match against all components
> + * @compare_data: opaque pointer passed to the @compare function
> + *
> + * This adds a new component match to the list stored in @matchptr, which the
> + * @master aggregate driver needs to function. @matchptr must be initialized to
> + * NULL before adding the first match.
> + *
> + * The allocated match list in @matchptr is automatically released using devm
> + * actions. At that point @release will be called, to free any references held
> + * by @compare_data, e.g. when @compare_data is a &device_node that must be
> + * released with of_node_put(). This only matches against components
> + * added with component_add().
> + *
> + * See also component_match_add() and component_match_add_typed().
> + */
> +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)
> +{
> +	__component_match_add(master, matchptr, release, compare, NULL,
> +			      compare_data);
> +}
>  EXPORT_SYMBOL(component_match_add_release);
>  
> +/**
> + * component_match_add_typed - add a compent match for a typed component
> + * @master: device with the aggregate driver
> + * @matchptr: pointer to the list of component matches
> + * @compare_typed: compare function to match against all typed components
> + * @compare_data: opaque pointer passed to the @compare function
> + *
> + * This adds a new component match to the list stored in @matchptr, which the
> + * @master aggregate driver needs to function. @matchptr must be initialized to
> + * NULL before adding the first match. This only matches against components
> + * added with component_add_typed().
> + *
> + * The allocated match list in @matchptr is automatically released using devm
> + * actions.
> + *
> + * See also component_match_add_release() and component_match_add_typed().
> + */
> +void component_match_add_typed(struct device *master,
> +	struct component_match **matchptr,
> +	int (*compare_typed)(struct device *, int, void *), void *compare_data)
> +{
> +	__component_match_add(master, matchptr, NULL, NULL, compare_typed,
> +			      compare_data);
> +}
> +EXPORT_SYMBOL(component_match_add_typed);
> +
>  static void free_master(struct master *master)
>  {
>  	struct component_match *match = master->match;
> @@ -617,19 +663,8 @@ int component_bind_all(struct device *master_dev, void *data)
>  }
>  EXPORT_SYMBOL_GPL(component_bind_all);
>  
> -/**
> - * component_add - register a component
> - * @dev: component device
> - * @ops: component callbacks
> - *
> - * Register a new component for @dev. Functions in @ops will be call when the
> - * aggregate driver is ready to bind the overall driver by calling
> - * component_bind_all(). See also &struct component_ops.
> - *
> - * The component needs to be unregistered again at driver unload/disconnect by
> - * calling component_del().
> - */
> -int component_add(struct device *dev, const struct component_ops *ops)
> +static int __component_add(struct device *dev, const struct component_ops *ops,
> +	int subcomponent)
>  {
>  	struct component *component;
>  	int ret;
> @@ -640,6 +675,7 @@ int component_add(struct device *dev, const struct component_ops *ops)
>  
>  	component->ops = ops;
>  	component->dev = dev;
> +	component->subcomponent = subcomponent;
>  
>  	dev_dbg(dev, "adding component (ops %ps)\n", ops);
>  
> @@ -658,6 +694,55 @@ int component_add(struct device *dev, const struct component_ops *ops)
>  
>  	return ret < 0 ? ret : 0;
>  }
> +
> +/**
> + * component_add_typed - register a component
> + * @dev: component device
> + * @ops: component callbacks
> + * @subcomponent: nonzero identifier for subcomponents
> + *
> + * Register a new component for @dev. Functions in @ops will be call when the
> + * aggregate driver is ready to bind the overall driver by calling
> + * component_bind_all(). See also &struct component_ops.
> + *
> + * @subcomponent must be nonzero and is used to differentiate between multiple
> + * components registerd on the same device @dev. These components are match
> + * using component_match_add_typed().
> + *
> + * The component needs to be unregistered again at driver unload/disconnect by
> + * calling component_del().
> + *
> + * See also component_add().
> + */
> +int component_add_typed(struct device *dev, const struct component_ops *ops,
> +	int subcomponent)
> +{
> +	if (WARN_ON(subcomponent == 0))
> +		return -EINVAL;
> +
> +	return __component_add(dev, ops, subcomponent);
> +}
> +EXPORT_SYMBOL_GPL(component_add_typed);
> +
> +/**
> + * component_add - register a component
> + * @dev: component device
> + * @ops: component callbacks
> + *
> + * Register a new component for @dev. Functions in @ops will be call when the
> + * aggregate driver is ready to bind the overall driver by calling
> + * component_bind_all(). See also &struct component_ops.
> + *
> + * The component needs to be unregistered again at driver unload/disconnect by
> + * calling component_del().
> + *
> + * See also component_add_typed() for a variant that allows multipled different
> + * components on the same device.
> + */
> +int component_add(struct device *dev, const struct component_ops *ops)
> +{
> +	return __component_add(dev, ops, 0);
> +}
>  EXPORT_SYMBOL_GPL(component_add);
>  
>  /**
> diff --git a/include/linux/component.h b/include/linux/component.h
> index 67a899dd2e10..9e69e2117f0b 100644
> --- a/include/linux/component.h
> +++ b/include/linux/component.h
> @@ -34,6 +34,8 @@ struct component_ops {
>  };
>  
>  int component_add(struct device *, const struct component_ops *);
> +int component_add_typed(struct device *dev, const struct component_ops *ops,
> +	int subcomponent);
>  void component_del(struct device *, const struct component_ops *);
>  
>  int component_bind_all(struct device *master, void *master_data);
> @@ -91,6 +93,9 @@ 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_add_typed(struct device *master,
> +	struct component_match **matchptr,
> +	int (*compare_typed)(struct device *, int, void *), void *compare_data);
>  
>  /**
>   * component_match_add - add a compent match
> @@ -101,12 +106,13 @@ void component_match_add_release(struct device *master,
>   *
>   * This adds a new component match to the list stored in @matchptr, which the
>   * @master aggregate driver needs to function. @matchptr must be initialized to
> - * NULL before adding the first match.
> + * NULL before adding the first match. This only matches against components
> + * added with component_add().
>   *
>   * The allocated match list in @matchptr is automatically released using devm
>   * actions.
>   *
> - * See also component_match_add_release().
> + * See also component_match_add_release() and component_match_add_typed().
>   */
>  static inline void component_match_add(struct device *master,
>  	struct component_match **matchptr,
> -- 
> 2.20.1
> 

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

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

* Re: [PATCH 2/2] components: multiple components for a device
@ 2019-02-04 16:00         ` Daniel Vetter
  0 siblings, 0 replies; 121+ messages in thread
From: Daniel Vetter @ 2019-02-04 16:00 UTC (permalink / raw)
  To: DRI Development
  Cc: Rafael J . Wysocki, Daniel Vetter, Takashi Iwai, LKML,
	Jaroslav Kysela, Rodrigo Vivi, Greg Kroah-Hartman, Russell King

On Thu, Jan 31, 2019 at 03:46:40PM +0100, Daniel Vetter wrote:
> Component framework is extended to support multiple components for
> a struct device. These will be matched with different masters based on
> its sub component value.
> 
> We are introducing this, as I915 needs two different components
> with different subcomponent value, which will be matched to two
> different component masters(Audio and HDCP) based on the subcomponent
> values.
> 
> v2: Add documenation.
> 
> Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch> (v1 code)
> Signed-off-by: Ramalingam C <ramalingam.c@intel.com> (v1 commit message)
> Cc: Ramalingam C <ramalingam.c@intel.com>
> Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
> Cc: Russell King <rmk+kernel@arm.linux.org.uk>
> Cc: Rafael J. Wysocki <rafael@kernel.org>
> Cc: Jaroslav Kysela <perex@perex.cz>
> Cc: Takashi Iwai <tiwai@suse.com>
> Cc: Rodrigo Vivi <rodrigo.vivi@intel.com>
> Cc: Jani Nikula <jani.nikula@linux.intel.com>
> Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>

Hi Greg&Russell,

Now that there's nice documentation on everything, any comments on these
two patches?

Thanks, Daniel

> ---
>  drivers/base/component.c  | 159 +++++++++++++++++++++++++++++---------
>  include/linux/component.h |  10 ++-
>  2 files changed, 130 insertions(+), 39 deletions(-)
> 
> diff --git a/drivers/base/component.c b/drivers/base/component.c
> index e5b04bce8544..eb7915fc5278 100644
> --- a/drivers/base/component.c
> +++ b/drivers/base/component.c
> @@ -48,6 +48,7 @@ struct component;
>  struct component_match_array {
>  	void *data;
>  	int (*compare)(struct device *, void *);
> +	int (*compare_typed)(struct device *, int, void *);
>  	void (*release)(struct device *, void *);
>  	struct component *component;
>  	bool duplicate;
> @@ -75,6 +76,7 @@ struct component {
>  	bool bound;
>  
>  	const struct component_ops *ops;
> +	int subcomponent;
>  	struct device *dev;
>  };
>  
> @@ -159,7 +161,7 @@ static struct master *__master_find(struct device *dev,
>  }
>  
>  static struct component *find_component(struct master *master,
> -	int (*compare)(struct device *, void *), void *compare_data)
> +	struct component_match_array *mc)
>  {
>  	struct component *c;
>  
> @@ -167,8 +169,13 @@ static struct component *find_component(struct master *master,
>  		if (c->master && c->master != master)
>  			continue;
>  
> -		if (compare(c->dev, compare_data))
> +		if (mc->compare_typed) {
> +			if (mc->compare_typed(c->dev, c->subcomponent,
> +					      mc->data))
> +				return c;
> +		} else if (mc->compare(c->dev, mc->data)) {
>  			return c;
> +		}
>  	}
>  
>  	return NULL;
> @@ -193,7 +200,7 @@ static int find_components(struct master *master)
>  		if (match->compare[i].component)
>  			continue;
>  
> -		c = find_component(master, mc->compare, mc->data);
> +		c = find_component(master, mc);
>  		if (!c) {
>  			ret = -ENXIO;
>  			break;
> @@ -328,29 +335,12 @@ static int component_match_realloc(struct device *dev,
>  	return 0;
>  }
>  
> -/**
> - * component_match_add_release - add a compent match with release callback
> - * @master: device with the aggregate driver
> - * @matchptr: pointer to the list of component matches
> - * @release: release function for @compare_data
> - * @compare: compare function to match against all components
> - * @compare_data: opaque pointer passed to the @compare function
> - *
> - * This adds a new component match to the list stored in @matchptr, which the
> - * @master aggregate driver needs to function. @matchptr must be initialized to
> - * NULL before adding the first match.
> - *
> - * The allocated match list in @matchptr is automatically released using devm
> - * actions. At that point @release will be called, to free any references held
> - * by @compare_data, e.g. when @compare_data is a &device_node that must be
> - * released with of_node_put().
> - *
> - * See also component_match_add().
> - */
> -void component_match_add_release(struct device *master,
> +static void __component_match_add(struct device *master,
>  	struct component_match **matchptr,
>  	void (*release)(struct device *, void *),
> -	int (*compare)(struct device *, void *), void *compare_data)
> +	int (*compare)(struct device *, void *),
> +	int (*compare_typed)(struct device *, int, void *),
> +	void *compare_data)
>  {
>  	struct component_match *match = *matchptr;
>  
> @@ -382,13 +372,69 @@ void component_match_add_release(struct device *master,
>  	}
>  
>  	match->compare[match->num].compare = compare;
> +	match->compare[match->num].compare_typed = compare_typed;
>  	match->compare[match->num].release = release;
>  	match->compare[match->num].data = compare_data;
>  	match->compare[match->num].component = NULL;
>  	match->num++;
>  }
> +
> +/**
> + * component_match_add_release - add a compent match with release callback
> + * @master: device with the aggregate driver
> + * @matchptr: pointer to the list of component matches
> + * @release: release function for @compare_data
> + * @compare: compare function to match against all components
> + * @compare_data: opaque pointer passed to the @compare function
> + *
> + * This adds a new component match to the list stored in @matchptr, which the
> + * @master aggregate driver needs to function. @matchptr must be initialized to
> + * NULL before adding the first match.
> + *
> + * The allocated match list in @matchptr is automatically released using devm
> + * actions. At that point @release will be called, to free any references held
> + * by @compare_data, e.g. when @compare_data is a &device_node that must be
> + * released with of_node_put(). This only matches against components
> + * added with component_add().
> + *
> + * See also component_match_add() and component_match_add_typed().
> + */
> +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)
> +{
> +	__component_match_add(master, matchptr, release, compare, NULL,
> +			      compare_data);
> +}
>  EXPORT_SYMBOL(component_match_add_release);
>  
> +/**
> + * component_match_add_typed - add a compent match for a typed component
> + * @master: device with the aggregate driver
> + * @matchptr: pointer to the list of component matches
> + * @compare_typed: compare function to match against all typed components
> + * @compare_data: opaque pointer passed to the @compare function
> + *
> + * This adds a new component match to the list stored in @matchptr, which the
> + * @master aggregate driver needs to function. @matchptr must be initialized to
> + * NULL before adding the first match. This only matches against components
> + * added with component_add_typed().
> + *
> + * The allocated match list in @matchptr is automatically released using devm
> + * actions.
> + *
> + * See also component_match_add_release() and component_match_add_typed().
> + */
> +void component_match_add_typed(struct device *master,
> +	struct component_match **matchptr,
> +	int (*compare_typed)(struct device *, int, void *), void *compare_data)
> +{
> +	__component_match_add(master, matchptr, NULL, NULL, compare_typed,
> +			      compare_data);
> +}
> +EXPORT_SYMBOL(component_match_add_typed);
> +
>  static void free_master(struct master *master)
>  {
>  	struct component_match *match = master->match;
> @@ -617,19 +663,8 @@ int component_bind_all(struct device *master_dev, void *data)
>  }
>  EXPORT_SYMBOL_GPL(component_bind_all);
>  
> -/**
> - * component_add - register a component
> - * @dev: component device
> - * @ops: component callbacks
> - *
> - * Register a new component for @dev. Functions in @ops will be call when the
> - * aggregate driver is ready to bind the overall driver by calling
> - * component_bind_all(). See also &struct component_ops.
> - *
> - * The component needs to be unregistered again at driver unload/disconnect by
> - * calling component_del().
> - */
> -int component_add(struct device *dev, const struct component_ops *ops)
> +static int __component_add(struct device *dev, const struct component_ops *ops,
> +	int subcomponent)
>  {
>  	struct component *component;
>  	int ret;
> @@ -640,6 +675,7 @@ int component_add(struct device *dev, const struct component_ops *ops)
>  
>  	component->ops = ops;
>  	component->dev = dev;
> +	component->subcomponent = subcomponent;
>  
>  	dev_dbg(dev, "adding component (ops %ps)\n", ops);
>  
> @@ -658,6 +694,55 @@ int component_add(struct device *dev, const struct component_ops *ops)
>  
>  	return ret < 0 ? ret : 0;
>  }
> +
> +/**
> + * component_add_typed - register a component
> + * @dev: component device
> + * @ops: component callbacks
> + * @subcomponent: nonzero identifier for subcomponents
> + *
> + * Register a new component for @dev. Functions in @ops will be call when the
> + * aggregate driver is ready to bind the overall driver by calling
> + * component_bind_all(). See also &struct component_ops.
> + *
> + * @subcomponent must be nonzero and is used to differentiate between multiple
> + * components registerd on the same device @dev. These components are match
> + * using component_match_add_typed().
> + *
> + * The component needs to be unregistered again at driver unload/disconnect by
> + * calling component_del().
> + *
> + * See also component_add().
> + */
> +int component_add_typed(struct device *dev, const struct component_ops *ops,
> +	int subcomponent)
> +{
> +	if (WARN_ON(subcomponent == 0))
> +		return -EINVAL;
> +
> +	return __component_add(dev, ops, subcomponent);
> +}
> +EXPORT_SYMBOL_GPL(component_add_typed);
> +
> +/**
> + * component_add - register a component
> + * @dev: component device
> + * @ops: component callbacks
> + *
> + * Register a new component for @dev. Functions in @ops will be call when the
> + * aggregate driver is ready to bind the overall driver by calling
> + * component_bind_all(). See also &struct component_ops.
> + *
> + * The component needs to be unregistered again at driver unload/disconnect by
> + * calling component_del().
> + *
> + * See also component_add_typed() for a variant that allows multipled different
> + * components on the same device.
> + */
> +int component_add(struct device *dev, const struct component_ops *ops)
> +{
> +	return __component_add(dev, ops, 0);
> +}
>  EXPORT_SYMBOL_GPL(component_add);
>  
>  /**
> diff --git a/include/linux/component.h b/include/linux/component.h
> index 67a899dd2e10..9e69e2117f0b 100644
> --- a/include/linux/component.h
> +++ b/include/linux/component.h
> @@ -34,6 +34,8 @@ struct component_ops {
>  };
>  
>  int component_add(struct device *, const struct component_ops *);
> +int component_add_typed(struct device *dev, const struct component_ops *ops,
> +	int subcomponent);
>  void component_del(struct device *, const struct component_ops *);
>  
>  int component_bind_all(struct device *master, void *master_data);
> @@ -91,6 +93,9 @@ 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_add_typed(struct device *master,
> +	struct component_match **matchptr,
> +	int (*compare_typed)(struct device *, int, void *), void *compare_data);
>  
>  /**
>   * component_match_add - add a compent match
> @@ -101,12 +106,13 @@ void component_match_add_release(struct device *master,
>   *
>   * This adds a new component match to the list stored in @matchptr, which the
>   * @master aggregate driver needs to function. @matchptr must be initialized to
> - * NULL before adding the first match.
> + * NULL before adding the first match. This only matches against components
> + * added with component_add().
>   *
>   * The allocated match list in @matchptr is automatically released using devm
>   * actions.
>   *
> - * See also component_match_add_release().
> + * See also component_match_add_release() and component_match_add_typed().
>   */
>  static inline void component_match_add(struct device *master,
>  	struct component_match **matchptr,
> -- 
> 2.20.1
> 

-- 
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] 121+ messages in thread

* Re: [PATCH v10 16/40] drm/i915: Implement the HDCP2.2 support for DP
  2019-01-31  6:59 ` [PATCH v10 16/40] drm/i915: Implement the HDCP2.2 support for DP Ramalingam C
@ 2019-02-04 16:02   ` Shankar, Uma
  0 siblings, 0 replies; 121+ messages in thread
From: Shankar, Uma @ 2019-02-04 16:02 UTC (permalink / raw)
  To: C, Ramalingam, intel-gfx, dri-devel, daniel.vetter, Winkler, Tomas



>-----Original Message-----
>From: C, Ramalingam
>Sent: Thursday, January 31, 2019 12:30 PM
>To: intel-gfx@lists.freedesktop.org; dri-devel@lists.freedesktop.org;
>daniel.vetter@ffwll.ch; Winkler, Tomas <tomas.winkler@intel.com>; Shankar,
>Uma <uma.shankar@intel.com>
>Cc: C, Ramalingam <ramalingam.c@intel.com>
>Subject: [PATCH v10 16/40] drm/i915: Implement the HDCP2.2 support for DP
>
>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]
>v10:
>  config_stream_type is redefined [Daniel]
>  DP Errata specific defines are moved into intel_dp.c.
>
>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>

Latest set looks ok. You can keep my RB.

>---
> drivers/gpu/drm/i915/intel_dp.c | 333
>++++++++++++++++++++++++++++++++++++++++
> 1 file changed, 333 insertions(+)
>
>diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
>index 9ce05819fc11..b13c41220ce0 100644
>--- a/drivers/gpu/drm/i915/intel_dp.c
>+++ b/drivers/gpu/drm/i915/intel_dp.c
>@@ -5843,6 +5843,333 @@ int intel_dp_hdcp_capable(struct intel_digital_port
>*intel_dig_port,
> 	return 0;
> }
>
>+struct hdcp2_dp_errata_stream_type {
>+	u8	msg_id;
>+	u8	stream_type;
>+} __packed;
>+
>+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},
>+/* local define to shovel this through the write_2_2 interface */
>+#define HDCP_2_2_ERRATA_DP_STREAM_TYPE	50
>+		{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,
>+				      bool is_repeater, u8 content_type) {
>+	struct hdcp2_dp_errata_stream_type stream_type_msg;
>+
>+	if (is_repeater)
>+		return 0;
>+
>+	/*
>+	 * 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 = content_type;
>+
>+	return intel_dp_hdcp2_write_msg(intel_dig_port, &stream_type_msg,
>+					sizeof(stream_type_msg));
>+}
>+
>+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 = HDCP_REAUTH_REQUEST;
>+	else if (HDCP_2_2_DP_RXSTATUS_LINK_FAILED(rx_status))
>+		ret = HDCP_LINK_INTEGRITY_FAILURE;
>+	else if (HDCP_2_2_DP_RXSTATUS_READY(rx_status))
>+		ret = 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,
>@@ -5855,6 +6182,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

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

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

* Re: [PATCH v10 17/40] drm/i915: Implement the HDCP2.2 support for HDMI
  2019-01-31  6:59 ` [PATCH v10 17/40] drm/i915: Implement the HDCP2.2 support for HDMI Ramalingam C
@ 2019-02-04 16:03   ` Shankar, Uma
  0 siblings, 0 replies; 121+ messages in thread
From: Shankar, Uma @ 2019-02-04 16:03 UTC (permalink / raw)
  To: C, Ramalingam, intel-gfx, dri-devel, daniel.vetter, Winkler, Tomas



>-----Original Message-----
>From: C, Ramalingam
>Sent: Thursday, January 31, 2019 12:30 PM
>To: intel-gfx@lists.freedesktop.org; dri-devel@lists.freedesktop.org;
>daniel.vetter@ffwll.ch; Winkler, Tomas <tomas.winkler@intel.com>; Shankar,
>Uma <uma.shankar@intel.com>
>Cc: C, Ramalingam <ramalingam.c@intel.com>
>Subject: [PATCH v10 17/40] drm/i915: Implement the HDCP2.2 support for HDMI
>
>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>

Latest set looks ok. You can keep my RB.

>---
> 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 ab376a31cdab..3b4fe7048af9 100644
>--- a/drivers/gpu/drm/i915/intel_hdmi.c
>+++ b/drivers/gpu/drm/i915/intel_hdmi.c
>@@ -1129,6 +1129,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 = HDCP_REAUTH_REQUEST;
>+	else if (HDCP_2_2_HDMI_RXSTATUS_READY(rx_status[1]))
>+		ret = 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, @@ -1140,6 +1324,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

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

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

* Re: [PATCH v10 20/40] drm/i915: Add HDCP2.2 support for HDMI connectors
  2019-01-31  6:59 ` [PATCH v10 20/40] drm/i915: Add HDCP2.2 support for HDMI connectors Ramalingam C
@ 2019-02-04 16:04   ` Winkler, Tomas
  2019-02-04 16:11     ` C, Ramalingam
  0 siblings, 1 reply; 121+ messages in thread
From: Winkler, Tomas @ 2019-02-04 16:04 UTC (permalink / raw)
  To: C, Ramalingam, intel-gfx, dri-devel, daniel.vetter, Shankar, Uma

> 
> 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 3b4fe7048af9..2c4bf6d0c39f 100644
> --- a/drivers/gpu/drm/i915/intel_hdmi.c
> +++ b/drivers/gpu/drm/i915/intel_hdmi.c
> @@ -2621,7 +2621,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));

intel_hdcp_init is always called with is_hdcp2_supported() both for DP and HDMI, so you can just remove the argument it's redundant. 

if (is_hdcp2_supported())
     intel_hdcp2_init(connector);

They are both defied in intel_hdcp.c.

Thanks
Tomas

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

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

* Re: [PATCH v10 24/40] misc/mei/hdcp: Define ME FW interface for HDCP2.2
  2019-01-31  6:59 ` [PATCH v10 24/40] misc/mei/hdcp: Define ME FW interface for HDCP2.2 Ramalingam C
@ 2019-02-04 16:07   ` Shankar, Uma
  2019-02-05 13:01     ` Winkler, Tomas
  0 siblings, 1 reply; 121+ messages in thread
From: Shankar, Uma @ 2019-02-04 16:07 UTC (permalink / raw)
  To: C, Ramalingam, intel-gfx, dri-devel, daniel.vetter, Winkler, Tomas



>-----Original Message-----
>From: C, Ramalingam
>Sent: Thursday, January 31, 2019 12:30 PM
>To: intel-gfx@lists.freedesktop.org; dri-devel@lists.freedesktop.org;
>daniel.vetter@ffwll.ch; Winkler, Tomas <tomas.winkler@intel.com>; Shankar,
>Uma <uma.shankar@intel.com>
>Cc: C, Ramalingam <ramalingam.c@intel.com>
>Subject: [PATCH v10 24/40] misc/mei/hdcp: Define ME FW interface for HDCP2.2
>
>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>

Looks ok to me.
Reviewed-by: Uma Shankar <uma.shankar@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..582a7e27ae29
>--- /dev/null
>+++ b/drivers/misc/mei/hdcp/mei_hdcp.h
>@@ -0,0 +1,366 @@
>+/* SPDX-License-Identifier: (GPL-2.0+) */
>+/*
>+ * 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	[flat|nested] 121+ messages in thread

* Re: [PATCH v10 19/40] drm/i915: Add HDCP2.2 support for DP connectors
  2019-01-31  6:59 ` [PATCH v10 19/40] drm/i915: Add HDCP2.2 support for DP connectors Ramalingam C
@ 2019-02-04 16:08   ` Winkler, Tomas
  0 siblings, 0 replies; 121+ messages in thread
From: Winkler, Tomas @ 2019-02-04 16:08 UTC (permalink / raw)
  To: C, Ramalingam, intel-gfx, dri-devel, daniel.vetter, Shankar, Uma



> -----Original Message-----
> From: C, Ramalingam
> Sent: Thursday, January 31, 2019 09:00
> To: intel-gfx@lists.freedesktop.org; dri-devel@lists.freedesktop.org;
> daniel.vetter@ffwll.ch; Winkler, Tomas <tomas.winkler@intel.com>; Shankar,
> Uma <uma.shankar@intel.com>
> Cc: C, Ramalingam <ramalingam.c@intel.com>
> Subject: [PATCH v10 19/40] drm/i915: Add HDCP2.2 support for DP connectors
> 
> 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 4e36df266ab3..88c889770517 100644
> --- a/drivers/gpu/drm/i915/intel_dp.c
> +++ b/drivers/gpu/drm/i915/intel_dp.c
> @@ -7301,7 +7301,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));
intel_hdcp_init is always called with is_hdcp2_supported() both for DP and HDMI, so you can just remove the argument it's redundant. 


Thanks
Tomas

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

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

* Re: [PATCH v10 25/40] misc/mei/hdcp: Initiate Wired HDCP2.2 Tx Session
  2019-01-31  6:59 ` [PATCH v10 25/40] misc/mei/hdcp: Initiate Wired HDCP2.2 Tx Session Ramalingam C
@ 2019-02-04 16:09   ` Shankar, Uma
  2019-02-05 13:09     ` Winkler, Tomas
  0 siblings, 1 reply; 121+ messages in thread
From: Shankar, Uma @ 2019-02-04 16:09 UTC (permalink / raw)
  To: C, Ramalingam, intel-gfx, dri-devel, daniel.vetter, Winkler, Tomas



>-----Original Message-----
>From: C, Ramalingam
>Sent: Thursday, January 31, 2019 12:30 PM
>To: intel-gfx@lists.freedesktop.org; dri-devel@lists.freedesktop.org;
>daniel.vetter@ffwll.ch; Winkler, Tomas <tomas.winkler@intel.com>; Shankar,
>Uma <uma.shankar@intel.com>
>Cc: C, Ramalingam <ramalingam.c@intel.com>
>Subject: [PATCH v10 25/40] misc/mei/hdcp: Initiate Wired HDCP2.2 Tx Session
>
>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>

Latest set look ok. You can keep the RB.

>---
> drivers/misc/mei/hdcp/mei_hdcp.c | 82
>++++++++++++++++++++++++++++++++++++++++
> drivers/misc/mei/hdcp/mei_hdcp.h | 28 ++++++++++++++
> 2 files changed, 110 insertions(+)
>
>diff --git a/drivers/misc/mei/hdcp/mei_hdcp.c
>b/drivers/misc/mei/hdcp/mei_hdcp.c
>index ca5010ad7dd7..534d29c8ee86 100644
>--- a/drivers/misc/mei/hdcp/mei_hdcp.c
>+++ b/drivers/misc/mei/hdcp/mei_hdcp.c
>@@ -23,6 +23,88 @@
> #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 <drm/i915_mei_hdcp_interface.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 582a7e27ae29..f831db3cbd54 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	[flat|nested] 121+ messages in thread

* Re: [PATCH v10 26/40] misc/mei/hdcp: Verify Receiver Cert and prepare km
  2019-01-31  6:59 ` [PATCH v10 26/40] misc/mei/hdcp: Verify Receiver Cert and prepare km Ramalingam C
@ 2019-02-04 16:10   ` Shankar, Uma
  2019-02-06  8:28     ` Winkler, Tomas
  0 siblings, 1 reply; 121+ messages in thread
From: Shankar, Uma @ 2019-02-04 16:10 UTC (permalink / raw)
  To: C, Ramalingam, intel-gfx, dri-devel, daniel.vetter, Winkler, Tomas



>-----Original Message-----
>From: C, Ramalingam
>Sent: Thursday, January 31, 2019 12:30 PM
>To: intel-gfx@lists.freedesktop.org; dri-devel@lists.freedesktop.org;
>daniel.vetter@ffwll.ch; Winkler, Tomas <tomas.winkler@intel.com>; Shankar,
>Uma <uma.shankar@intel.com>
>Cc: C, Ramalingam <ramalingam.c@intel.com>
>Subject: [PATCH v10 26/40] misc/mei/hdcp: Verify Receiver Cert and prepare km
>
>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>

Latest set look ok. You can keep the RB.

>---
> 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 534d29c8ee86..24665fff640d 100644
>--- a/drivers/misc/mei/hdcp/mei_hdcp.c
>+++ b/drivers/misc/mei/hdcp/mei_hdcp.c
>@@ -90,11 +90,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	[flat|nested] 121+ messages in thread

* Re: [PATCH v10 20/40] drm/i915: Add HDCP2.2 support for HDMI connectors
  2019-02-04 16:04   ` Winkler, Tomas
@ 2019-02-04 16:11     ` C, Ramalingam
  0 siblings, 0 replies; 121+ messages in thread
From: C, Ramalingam @ 2019-02-04 16:11 UTC (permalink / raw)
  To: Winkler, Tomas, intel-gfx, dri-devel, daniel.vetter, Shankar, Uma



On 2/4/2019 9:34 PM, Winkler, Tomas wrote:
>> 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 3b4fe7048af9..2c4bf6d0c39f 100644
>> --- a/drivers/gpu/drm/i915/intel_hdmi.c
>> +++ b/drivers/gpu/drm/i915/intel_hdmi.c
>> @@ -2621,7 +2621,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));
> intel_hdcp_init is always called with is_hdcp2_supported() both for DP and HDMI, so you can just remove the argument it's redundant.
Thanks for the review Tomas.
Sure. That will reduce a parameter in hdcp_init.

--Ram

>
> if (is_hdcp2_supported())
>       intel_hdcp2_init(connector);
>
> They are both defied in intel_hdcp.c.
>
> Thanks
> Tomas
>

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

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

* Re: [PATCH v10 27/40] misc/mei/hdcp: Verify H_prime
  2019-01-31  6:59 ` [PATCH v10 27/40] misc/mei/hdcp: Verify H_prime Ramalingam C
@ 2019-02-04 16:11   ` Shankar, Uma
  0 siblings, 0 replies; 121+ messages in thread
From: Shankar, Uma @ 2019-02-04 16:11 UTC (permalink / raw)
  To: C, Ramalingam, intel-gfx, dri-devel, daniel.vetter, Winkler, Tomas



>-----Original Message-----
>From: C, Ramalingam
>Sent: Thursday, January 31, 2019 12:30 PM
>To: intel-gfx@lists.freedesktop.org; dri-devel@lists.freedesktop.org;
>daniel.vetter@ffwll.ch; Winkler, Tomas <tomas.winkler@intel.com>; Shankar,
>Uma <uma.shankar@intel.com>
>Cc: C, Ramalingam <ramalingam.c@intel.com>
>Subject: [PATCH v10 27/40] misc/mei/hdcp: Verify H_prime
>
>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>

Latest set look ok. You can keep the RB.

>---
> 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 24665fff640d..74219e1487d3 100644
>--- a/drivers/misc/mei/hdcp/mei_hdcp.c
>+++ b/drivers/misc/mei/hdcp/mei_hdcp.c
>@@ -169,12 +169,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

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

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

* Re: [PATCH v10 28/40] misc/mei/hdcp: Store the HDCP Pairing info
  2019-01-31  6:59 ` [PATCH v10 28/40] misc/mei/hdcp: Store the HDCP Pairing info Ramalingam C
@ 2019-02-04 16:13   ` Shankar, Uma
  0 siblings, 0 replies; 121+ messages in thread
From: Shankar, Uma @ 2019-02-04 16:13 UTC (permalink / raw)
  To: C, Ramalingam, intel-gfx, dri-devel, daniel.vetter, Winkler, Tomas



>-----Original Message-----
>From: dri-devel [mailto:dri-devel-bounces@lists.freedesktop.org] On Behalf Of
>Ramalingam C
>Sent: Thursday, January 31, 2019 12:30 PM
>To: intel-gfx@lists.freedesktop.org; dri-devel@lists.freedesktop.org;
>daniel.vetter@ffwll.ch; Winkler, Tomas <tomas.winkler@intel.com>; Shankar,
>Uma <uma.shankar@intel.com>
>Subject: [PATCH v10 28/40] misc/mei/hdcp: Store the HDCP Pairing info
>
>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>

Latest set looks ok. You can keep the RB.

>---
> 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 74219e1487d3..e8396c723ab0 100644
>--- a/drivers/misc/mei/hdcp/mei_hdcp.c
>+++ b/drivers/misc/mei/hdcp/mei_hdcp.c
>@@ -224,13 +224,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
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

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

* Re: [PATCH v10 29/40] misc/mei/hdcp: Initiate Locality check
  2019-01-31  6:59 ` [PATCH v10 29/40] misc/mei/hdcp: Initiate Locality check Ramalingam C
@ 2019-02-04 16:16   ` Shankar, Uma
  0 siblings, 0 replies; 121+ messages in thread
From: Shankar, Uma @ 2019-02-04 16:16 UTC (permalink / raw)
  To: C, Ramalingam, intel-gfx, dri-devel, daniel.vetter, Winkler, Tomas



>-----Original Message-----
>From: C, Ramalingam
>Sent: Thursday, January 31, 2019 12:30 PM
>To: intel-gfx@lists.freedesktop.org; dri-devel@lists.freedesktop.org;
>daniel.vetter@ffwll.ch; Winkler, Tomas <tomas.winkler@intel.com>; Shankar,
>Uma <uma.shankar@intel.com>
>Cc: C, Ramalingam <ramalingam.c@intel.com>
>Subject: [PATCH v10 29/40] misc/mei/hdcp: Initiate Locality check
>
>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>

Latest set looks ok. You can keep the RB.

>---
> 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 e8396c723ab0..412a33e29d7d 100644
>--- a/drivers/misc/mei/hdcp/mei_hdcp.c
>+++ b/drivers/misc/mei/hdcp/mei_hdcp.c
>@@ -282,6 +282,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,
>@@ -289,7 +343,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	[flat|nested] 121+ messages in thread

* RE: [PATCH v10 30/40] misc/mei/hdcp: Verify L_prime
  2019-01-31  6:59 ` [PATCH v10 30/40] misc/mei/hdcp: Verify L_prime Ramalingam C
@ 2019-02-04 16:16   ` Shankar, Uma
  0 siblings, 0 replies; 121+ messages in thread
From: Shankar, Uma @ 2019-02-04 16:16 UTC (permalink / raw)
  To: C, Ramalingam, intel-gfx, dri-devel, daniel.vetter, Winkler, Tomas



>-----Original Message-----
>From: C, Ramalingam
>Sent: Thursday, January 31, 2019 12:30 PM
>To: intel-gfx@lists.freedesktop.org; dri-devel@lists.freedesktop.org;
>daniel.vetter@ffwll.ch; Winkler, Tomas <tomas.winkler@intel.com>; Shankar,
>Uma <uma.shankar@intel.com>
>Cc: C, Ramalingam <ramalingam.c@intel.com>
>Subject: [PATCH v10 30/40] misc/mei/hdcp: Verify L_prime
>
>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>

Latest set looks ok. You can keep the RB.

>---
> 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 412a33e29d7d..3d7767d944dc 100644
>--- a/drivers/misc/mei/hdcp/mei_hdcp.c
>+++ b/drivers/misc/mei/hdcp/mei_hdcp.c
>@@ -336,6 +336,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,
>@@ -344,7 +401,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	[flat|nested] 121+ messages in thread

* Re: [PATCH v10 31/40] misc/mei/hdcp: Prepare Session Key
  2019-01-31  6:59 ` [PATCH v10 31/40] misc/mei/hdcp: Prepare Session Key Ramalingam C
@ 2019-02-04 16:17   ` Shankar, Uma
  0 siblings, 0 replies; 121+ messages in thread
From: Shankar, Uma @ 2019-02-04 16:17 UTC (permalink / raw)
  To: C, Ramalingam, intel-gfx, dri-devel, daniel.vetter, Winkler, Tomas



>-----Original Message-----
>From: C, Ramalingam
>Sent: Thursday, January 31, 2019 12:30 PM
>To: intel-gfx@lists.freedesktop.org; dri-devel@lists.freedesktop.org;
>daniel.vetter@ffwll.ch; Winkler, Tomas <tomas.winkler@intel.com>; Shankar,
>Uma <uma.shankar@intel.com>
>Cc: C, Ramalingam <ramalingam.c@intel.com>
>Subject: [PATCH v10 31/40] misc/mei/hdcp: Prepare Session Key
>
>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>

Latest set looks ok. You can keep the RB.

>---
> 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 3d7767d944dc..2be7b6b949c2 100644
>--- a/drivers/misc/mei/hdcp/mei_hdcp.c
>+++ b/drivers/misc/mei/hdcp/mei_hdcp.c
>@@ -393,6 +393,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,
>@@ -402,7 +458,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

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

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

* Re: [PATCH v10 32/40] misc/mei/hdcp: Repeater topology verification and ack
  2019-01-31  6:59 ` [PATCH v10 32/40] misc/mei/hdcp: Repeater topology verification and ack Ramalingam C
@ 2019-02-04 16:17   ` Shankar, Uma
  0 siblings, 0 replies; 121+ messages in thread
From: Shankar, Uma @ 2019-02-04 16:17 UTC (permalink / raw)
  To: C, Ramalingam, intel-gfx, dri-devel, daniel.vetter, Winkler, Tomas



>-----Original Message-----
>From: C, Ramalingam
>Sent: Thursday, January 31, 2019 12:30 PM
>To: intel-gfx@lists.freedesktop.org; dri-devel@lists.freedesktop.org;
>daniel.vetter@ffwll.ch; Winkler, Tomas <tomas.winkler@intel.com>; Shankar,
>Uma <uma.shankar@intel.com>
>Cc: C, Ramalingam <ramalingam.c@intel.com>
>Subject: [PATCH v10 32/40] misc/mei/hdcp: Repeater topology verification and
>ack
>
>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>

Latest set looks ok. You can keep the RB.

>---
> 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 2be7b6b949c2..c157c18371b4 100644
>--- a/drivers/misc/mei/hdcp/mei_hdcp.c
>+++ b/drivers/misc/mei/hdcp/mei_hdcp.c
>@@ -449,6 +449,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,
>@@ -459,7 +533,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

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

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

* Re: [PATCH v10 33/40] misc/mei/hdcp: Verify M_prime
  2019-01-31  6:59 ` [PATCH v10 33/40] misc/mei/hdcp: Verify M_prime Ramalingam C
@ 2019-02-04 16:18   ` Shankar, Uma
  0 siblings, 0 replies; 121+ messages in thread
From: Shankar, Uma @ 2019-02-04 16:18 UTC (permalink / raw)
  To: C, Ramalingam, intel-gfx, dri-devel, daniel.vetter, Winkler, Tomas



>-----Original Message-----
>From: C, Ramalingam
>Sent: Thursday, January 31, 2019 12:30 PM
>To: intel-gfx@lists.freedesktop.org; dri-devel@lists.freedesktop.org;
>daniel.vetter@ffwll.ch; Winkler, Tomas <tomas.winkler@intel.com>; Shankar,
>Uma <uma.shankar@intel.com>
>Cc: C, Ramalingam <ramalingam.c@intel.com>
>Subject: [PATCH v10 33/40] misc/mei/hdcp: Verify M_prime
>
>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>

Latest set looks ok. You can keep the RB.

>---
> 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 c157c18371b4..91f7b08d1df1 100644
>--- a/drivers/misc/mei/hdcp/mei_hdcp.c
>+++ b/drivers/misc/mei/hdcp/mei_hdcp.c
>@@ -523,6 +523,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,
>@@ -534,7 +598,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

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

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

* Re: [PATCH v10 34/40] misc/mei/hdcp: Enabling the HDCP authentication
  2019-01-31  6:59 ` [PATCH v10 34/40] misc/mei/hdcp: Enabling the HDCP authentication Ramalingam C
@ 2019-02-04 16:19   ` Shankar, Uma
  0 siblings, 0 replies; 121+ messages in thread
From: Shankar, Uma @ 2019-02-04 16:19 UTC (permalink / raw)
  To: C, Ramalingam, intel-gfx, dri-devel, daniel.vetter, Winkler, Tomas



>-----Original Message-----
>From: C, Ramalingam
>Sent: Thursday, January 31, 2019 12:30 PM
>To: intel-gfx@lists.freedesktop.org; dri-devel@lists.freedesktop.org;
>daniel.vetter@ffwll.ch; Winkler, Tomas <tomas.winkler@intel.com>; Shankar,
>Uma <uma.shankar@intel.com>
>Cc: C, Ramalingam <ramalingam.c@intel.com>
>Subject: [PATCH v10 34/40] misc/mei/hdcp: Enabling the HDCP authentication
>
>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>

Latest set looks ok. You can keep the RB.

>---
> 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 91f7b08d1df1..5303c729612b 100644
>--- a/drivers/misc/mei/hdcp/mei_hdcp.c
>+++ b/drivers/misc/mei/hdcp/mei_hdcp.c
>@@ -587,6 +587,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,
>@@ -599,7 +651,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

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

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

* Re: [PATCH v10 35/40] misc/mei/hdcp: Closing wired HDCP2.2 Tx Session
  2019-01-31  6:59 ` [PATCH v10 35/40] misc/mei/hdcp: Closing wired HDCP2.2 Tx Session Ramalingam C
@ 2019-02-04 16:20   ` Shankar, Uma
  0 siblings, 0 replies; 121+ messages in thread
From: Shankar, Uma @ 2019-02-04 16:20 UTC (permalink / raw)
  To: C, Ramalingam, intel-gfx, dri-devel, daniel.vetter, Winkler, Tomas



>-----Original Message-----
>From: C, Ramalingam
>Sent: Thursday, January 31, 2019 12:30 PM
>To: intel-gfx@lists.freedesktop.org; dri-devel@lists.freedesktop.org;
>daniel.vetter@ffwll.ch; Winkler, Tomas <tomas.winkler@intel.com>; Shankar,
>Uma <uma.shankar@intel.com>
>Cc: C, Ramalingam <ramalingam.c@intel.com>
>Subject: [PATCH v10 35/40] misc/mei/hdcp: Closing wired HDCP2.2 Tx Session
>
>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>

Latest set looks ok. You can keep the RB.

>---
> 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 5303c729612b..edfc70fb0617 100644
>--- a/drivers/misc/mei/hdcp/mei_hdcp.c
>+++ b/drivers/misc/mei/hdcp/mei_hdcp.c
>@@ -639,6 +639,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,
>@@ -652,7 +705,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

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

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

* Re: [PATCH v10 36/40] misc/mei/hdcp: Component framework for I915 Interface
  2019-01-31  6:59 ` [PATCH v10 36/40] misc/mei/hdcp: Component framework for I915 Interface Ramalingam C
  2019-01-31  8:23   ` Daniel Vetter
@ 2019-02-04 16:27   ` Shankar, Uma
  1 sibling, 0 replies; 121+ messages in thread
From: Shankar, Uma @ 2019-02-04 16:27 UTC (permalink / raw)
  To: C, Ramalingam, intel-gfx, dri-devel, daniel.vetter, Winkler, Tomas



>-----Original Message-----
>From: C, Ramalingam
>Sent: Thursday, January 31, 2019 12:30 PM
>To: intel-gfx@lists.freedesktop.org; dri-devel@lists.freedesktop.org;
>daniel.vetter@ffwll.ch; Winkler, Tomas <tomas.winkler@intel.com>; Shankar,
>Uma <uma.shankar@intel.com>
>Cc: C, Ramalingam <ramalingam.c@intel.com>
>Subject: [PATCH v10 36/40] misc/mei/hdcp: Component framework for I915
>Interface
>
>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.
>v8:
>  master comp is added to be matched with i915 subcomponent [daniel]
>
>Signed-off-by: Ramalingam C <ramalingam.c@intel.com>
>Reviewed-by: Uma Shankar <uma.shankar@intel.com>

This is a new interface change and definitely a lot is changed from the time I reviewed.
You can drop my RB and I would suggest to go with Daniel and Tomas's feedback for the same.

>---
> drivers/misc/mei/hdcp/mei_hdcp.c | 90
>+++++++++++++++++++++++++++++++++++++++-
> drivers/misc/mei/hdcp/mei_hdcp.h |  5 +++
> 2 files changed, 93 insertions(+), 2 deletions(-)
>
>diff --git a/drivers/misc/mei/hdcp/mei_hdcp.c
>b/drivers/misc/mei/hdcp/mei_hdcp.c
>index edfc70fb0617..be2ce12ca460 100644
>--- a/drivers/misc/mei/hdcp/mei_hdcp.c
>+++ b/drivers/misc/mei/hdcp/mei_hdcp.c
>@@ -23,6 +23,7 @@
> #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 <drm/i915_mei_hdcp_interface.h> @@ -692,8 +693,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,
>@@ -708,20 +708,106 @@ struct i915_hdcp_component_ops mei_hdcp_ops = {
> 	.close_hdcp_session = mei_close_hdcp_session,  };
>
>+static int mei_component_master_bind(struct device *dev) {
>+	struct mei_cl_device *cldev = to_mei_cl_device(dev);
>+	struct mei_hdcp_drv_data *drv_data = mei_cldev_get_drvdata(cldev);
>+	int ret;
>+
>+	dev_info(dev, "%s\n", __func__);
>+	drv_data->comp_master->ops = &mei_hdcp_ops;
>+	drv_data->comp_master->mei_dev = dev;
>+	ret = component_bind_all(dev, drv_data->comp_master);
>+	if (ret < 0)
>+		return ret;
>+
>+	return 0;
>+}
>+
>+static void mei_component_master_unbind(struct device *dev) {
>+	struct mei_cl_device *cldev = to_mei_cl_device(dev);
>+	struct mei_hdcp_drv_data *drv_data = mei_cldev_get_drvdata(cldev);
>+
>+	dev_info(dev, "%s\n", __func__);
>+	component_unbind_all(dev, drv_data->comp_master); }
>+
>+static const struct component_master_ops mei_component_master_ops = {
>+	.bind = mei_component_master_bind,
>+	.unbind = mei_component_master_unbind, };
>+
>+static int mei_hdcp_component_match(struct device *dev, int subcomponent,
>+				    void *data)
>+{
>+	return !strcmp(dev->driver->name, "i915") &&
>+	       subcomponent == I915_COMPONENT_HDCP; }
>+
> static int mei_hdcp_probe(struct mei_cl_device *cldev,
> 			  const struct mei_cl_device_id *id)  {
>+	struct mei_hdcp_drv_data *drv_data;
> 	int ret;
>
> 	ret = mei_cldev_enable(cldev);
> 	if (ret < 0)
> 		dev_err(&cldev->dev, "mei_cldev_enable Failed. %d\n", ret);
>
>+	drv_data = kzalloc(sizeof(*drv_data), GFP_KERNEL);
>+	if (!drv_data) {
>+		ret = -ENOMEM;
>+		goto drv_data_exit;
>+	}
>+
>+	drv_data->comp_master = kzalloc(sizeof(*drv_data->comp_master),
>+					GFP_KERNEL);
>+	if (!drv_data->comp_master) {
>+		ret = -ENOMEM;
>+		goto comp_master_exit;
>+	}
>+
>+	drv_data->master_match = NULL;
>+	component_match_add_typed(&cldev->dev, &drv_data->master_match,
>+				  mei_hdcp_component_match,
>+				  drv_data->comp_master);
>+	if (IS_ERR_OR_NULL(drv_data->master_match)) {
>+		ret = -ENOMEM;
>+		goto match_add_exit;
>+	}
>+
>+	mei_cldev_set_drvdata(cldev, drv_data);
>+	ret = component_master_add_with_match(&cldev->dev,
>+					      &mei_component_master_ops,
>+					      drv_data->master_match);
>+	if (ret < 0) {
>+		dev_err(&cldev->dev, "Master comp add failed %d\n", ret);
>+		mei_cldev_set_drvdata(cldev, NULL);
>+		goto match_add_exit;
>+	}
>+
>+	return 0;
>+
>+match_add_exit:
>+	kfree(drv_data->comp_master);
>+comp_master_exit:
>+	kfree(drv_data);
>+drv_data_exit:
>+	mei_cldev_disable(cldev);
>+
> 	return ret;
> }
>
> static int mei_hdcp_remove(struct mei_cl_device *cldev)  {
>+	struct mei_hdcp_drv_data *drv_data = mei_cldev_get_drvdata(cldev);
>+
>+	component_master_del(&cldev->dev, &mei_component_master_ops);
>+	kfree(drv_data->comp_master);
>+	kfree(drv_data);
>+	mei_cldev_set_drvdata(cldev, NULL);
>+
> 	return mei_cldev_disable(cldev);
> }
>
>diff --git a/drivers/misc/mei/hdcp/mei_hdcp.h
>b/drivers/misc/mei/hdcp/mei_hdcp.h
>index f831db3cbd54..5c872a57ba11 100644
>--- a/drivers/misc/mei/hdcp/mei_hdcp.h
>+++ b/drivers/misc/mei/hdcp/mei_hdcp.h
>@@ -363,6 +363,11 @@ struct wired_cmd_repeater_auth_stream_req_out {
> 	struct hdcp_port_id	port;
> } __packed;
>
>+struct mei_hdcp_drv_data {
>+	struct i915_hdcp_comp_master *comp_master;
>+	struct component_match *master_match;
>+};
>+
> enum mei_hdcp_ddi {
> 	MEI_DDI_INVALID_PORT = 0x0,
>
>--
>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] 121+ messages in thread

* RE: [PATCH v10 38/40] drm/i915: Fix KBL HDCP2.2 encrypt status signalling
  2019-01-31  6:59 ` [PATCH v10 38/40] drm/i915: Fix KBL HDCP2.2 encrypt status signalling Ramalingam C
  2019-02-04 15:32   ` C, Ramalingam
@ 2019-02-04 16:35   ` Shankar, Uma
  1 sibling, 0 replies; 121+ messages in thread
From: Shankar, Uma @ 2019-02-04 16:35 UTC (permalink / raw)
  To: C, Ramalingam, intel-gfx, dri-devel, daniel.vetter, Winkler, Tomas



>-----Original Message-----
>From: C, Ramalingam
>Sent: Thursday, January 31, 2019 12:30 PM
>To: intel-gfx@lists.freedesktop.org; dri-devel@lists.freedesktop.org;
>daniel.vetter@ffwll.ch; Winkler, Tomas <tomas.winkler@intel.com>; Shankar,
>Uma <uma.shankar@intel.com>
>Cc: C, Ramalingam <ramalingam.c@intel.com>
>Subject: [PATCH v10 38/40] drm/i915: Fix KBL HDCP2.2 encrypt status signalling
>
>Implement the required WA sequence for KBL to fix the incorrect positioning of
>the window of oppurtunity and enc_en signalling.

Typo in opportunity.

>
>v2:
>  WA is moved into the toggle_signalling [Daniel]
>
>Signed-off-by: Ramalingam C <ramalingam.c@intel.com>
>---
> drivers/gpu/drm/i915/intel_hdmi.c | 42
>+++++++++++++++++++++++++++++++++++++++
> 1 file changed, 42 insertions(+)
>
>diff --git a/drivers/gpu/drm/i915/intel_hdmi.c
>b/drivers/gpu/drm/i915/intel_hdmi.c
>index 2c4bf6d0c39f..ae20288f7bbf 100644
>--- a/drivers/gpu/drm/i915/intel_hdmi.c
>+++ b/drivers/gpu/drm/i915/intel_hdmi.c
>@@ -1083,10 +1083,44 @@ int intel_hdmi_hdcp_read_v_prime_part(struct
>intel_digital_port *intel_dig_port,
> 	return ret;
> }
>
Would be good to add a comment here as to what exactly is the WA and what
you are trying to do here.

>+static int 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 drm_crtc *crtc = connector->base.state->crtc;
>+	struct intel_crtc *intel_crtc = container_of(crtc,
>+						     struct intel_crtc, base);
>+	u32 scanline;
>+	int ret;
>+
>+	for (;;) {
>+		scanline = I915_READ(PIPEDSL(intel_crtc->pipe));
>+		if (scanline > 100 && scanline < 200)
>+			break;
>+		usleep_range(25, 50);
>+	}
>+
>+	ret = intel_ddi_toggle_hdcp_signalling(&intel_dig_port->base, false);
>+	if (ret) {
>+		DRM_ERROR("Disable HDCP signalling failed (%d)\n", ret);
>+		return ret;
>+	}
>+	ret = intel_ddi_toggle_hdcp_signalling(&intel_dig_port->base, true);
>+	if (ret) {
>+		DRM_ERROR("Enable HDCP signalling failed (%d)\n", ret);
>+		return ret;
>+	}
>+
>+	return 0;
>+}
>+
> static
> int intel_hdmi_hdcp_toggle_signalling(struct intel_digital_port *intel_dig_port,
> 				      bool enable)
> {
>+	struct intel_hdmi *hdmi = &intel_dig_port->hdmi;
>+	struct intel_connector *connector = hdmi->attached_connector;
>+	struct drm_i915_private *dev_priv = to_i915(connector->base.dev);
> 	int ret;
>
> 	if (!enable)
>@@ -1098,6 +1132,14 @@ int intel_hdmi_hdcp_toggle_signalling(struct
>intel_digital_port *intel_dig_port,
> 			  enable ? "Enable" : "Disable", ret);
> 		return ret;
> 	}
>+
>+	/*
>+	 * WA: To fix incorrect positioning of the window of
>+	 * opportunity and enc_en signalling in KABYLAKE.
>+	 */
>+	if (IS_KABYLAKE(dev_priv) && enable)
>+		return kbl_repositioning_enc_en_signal(connector);
>+
> 	return 0;
> }
>
>--
>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] 121+ messages in thread

* Re: [PATCH v10 38/40] drm/i915: Fix KBL HDCP2.2 encrypt status signalling
  2019-02-04 15:32   ` C, Ramalingam
@ 2019-02-05  8:54     ` Daniel Vetter
  0 siblings, 0 replies; 121+ messages in thread
From: Daniel Vetter @ 2019-02-05  8:54 UTC (permalink / raw)
  To: C, Ramalingam
  Cc: daniel.vetter, intel-gfx, uma.shankar, tomas.winkler, dri-devel

On Mon, Feb 04, 2019 at 09:02:35PM +0530, C, Ramalingam wrote:
> daniel,
> 
> Could you please review this patch too.? Already Updated this as per your
> previous review comment.

Oops, missed this one somehow. Looks much cleaner now imo.

Reviewed-by: Daniel Vetter <daniel.vetter@ffwll.ch>
> 
> --Ram
> 
> On 1/31/2019 12:29 PM, Ramalingam C wrote:
> > Implement the required WA sequence for KBL to fix the
> > incorrect positioning of the window of oppurtunity and enc_en
> > signalling.
> > 
> > v2:
> >    WA is moved into the toggle_signalling [Daniel]
> > 
> > Signed-off-by: Ramalingam C <ramalingam.c@intel.com>
> > ---
> >   drivers/gpu/drm/i915/intel_hdmi.c | 42 +++++++++++++++++++++++++++++++++++++++
> >   1 file changed, 42 insertions(+)
> > 
> > diff --git a/drivers/gpu/drm/i915/intel_hdmi.c b/drivers/gpu/drm/i915/intel_hdmi.c
> > index 2c4bf6d0c39f..ae20288f7bbf 100644
> > --- a/drivers/gpu/drm/i915/intel_hdmi.c
> > +++ b/drivers/gpu/drm/i915/intel_hdmi.c
> > @@ -1083,10 +1083,44 @@ int intel_hdmi_hdcp_read_v_prime_part(struct intel_digital_port *intel_dig_port,
> >   	return ret;
> >   }
> > +static int 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 drm_crtc *crtc = connector->base.state->crtc;
> > +	struct intel_crtc *intel_crtc = container_of(crtc,
> > +						     struct intel_crtc, base);
> > +	u32 scanline;
> > +	int ret;
> > +
> > +	for (;;) {
> > +		scanline = I915_READ(PIPEDSL(intel_crtc->pipe));
> > +		if (scanline > 100 && scanline < 200)
> > +			break;
> > +		usleep_range(25, 50);
> > +	}
> > +
> > +	ret = intel_ddi_toggle_hdcp_signalling(&intel_dig_port->base, false);
> > +	if (ret) {
> > +		DRM_ERROR("Disable HDCP signalling failed (%d)\n", ret);
> > +		return ret;
> > +	}
> > +	ret = intel_ddi_toggle_hdcp_signalling(&intel_dig_port->base, true);
> > +	if (ret) {
> > +		DRM_ERROR("Enable HDCP signalling failed (%d)\n", ret);
> > +		return ret;
> > +	}
> > +
> > +	return 0;
> > +}
> > +
> >   static
> >   int intel_hdmi_hdcp_toggle_signalling(struct intel_digital_port *intel_dig_port,
> >   				      bool enable)
> >   {
> > +	struct intel_hdmi *hdmi = &intel_dig_port->hdmi;
> > +	struct intel_connector *connector = hdmi->attached_connector;
> > +	struct drm_i915_private *dev_priv = to_i915(connector->base.dev);
> >   	int ret;
> >   	if (!enable)
> > @@ -1098,6 +1132,14 @@ int intel_hdmi_hdcp_toggle_signalling(struct intel_digital_port *intel_dig_port,
> >   			  enable ? "Enable" : "Disable", ret);
> >   		return ret;
> >   	}
> > +
> > +	/*
> > +	 * WA: To fix incorrect positioning of the window of
> > +	 * opportunity and enc_en signalling in KABYLAKE.
> > +	 */
> > +	if (IS_KABYLAKE(dev_priv) && enable)
> > +		return kbl_repositioning_enc_en_signal(connector);
> > +
> >   	return 0;
> >   }
> 

-- 
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] 121+ messages in thread

* Re: [PATCH 1/2] component: Add documentation
  2019-01-31 14:46   ` [PATCH 1/2] component: Add documentation Daniel Vetter
  2019-01-31 14:46     ` [PATCH 2/2] components: multiple components for a device Daniel Vetter
@ 2019-02-05 10:47     ` Rafael J. Wysocki
  2019-02-05 16:20       ` Daniel Vetter
  2019-02-05 16:21     ` [PATCH] " Daniel Vetter
  2 siblings, 1 reply; 121+ messages in thread
From: Rafael J. Wysocki @ 2019-02-05 10:47 UTC (permalink / raw)
  To: Daniel Vetter
  Cc: DRI Development, LKML, C, Ramalingam, Greg Kroah-Hartman,
	Russell King, Rafael J . Wysocki, Jaroslav Kysela, Takashi Iwai,
	Rodrigo Vivi, Jani Nikula, Daniel Vetter

 w/compOn Thu, Jan 31, 2019 at 3:46 PM Daniel Vetter
<daniel.vetter@ffwll.ch> wrote:
>
> Someone owes me a beer ...
>
> While typing these I think doing an s/component_master/aggregate/
> would be useful:
> - it's shorter :-)
> - I think component/aggregate is much more meaningful naming than
>   component/puppetmaster or something like that. At least to my
>   English ear "aggregate" emphasizes much more the "assemble a pile of
>   things into something bigger" aspect, and there's not really much
>   of a control hierarchy between aggregate and constituing components.
>
> But that's way more than a quick doc typing exercise ...
>
> Thanks to Ram for commenting on an initial draft of these docs.

Look goods to me overall (even though I'm not super-familiar with the
component framework), but see below.

> Cc: "C, Ramalingam" <ramalingam.c@intel.com>
> Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
> Cc: Russell King <rmk+kernel@arm.linux.org.uk>
> Cc: Rafael J. Wysocki <rafael@kernel.org>
> Cc: Jaroslav Kysela <perex@perex.cz>
> Cc: Takashi Iwai <tiwai@suse.com>
> Cc: Rodrigo Vivi <rodrigo.vivi@intel.com>
> Cc: Jani Nikula <jani.nikula@linux.intel.com>
> Signed-off-by: Daniel Vetter <daniel.vetter@intel.com>
> ---
>  Documentation/driver-api/device_link.rst |   3 +
>  Documentation/driver-api/index.rst       |   1 +
>  drivers/base/component.c                 | 107 ++++++++++++++++++++++-
>  include/linux/component.h                |  70 +++++++++++++++
>  4 files changed, 178 insertions(+), 3 deletions(-)
>
> diff --git a/Documentation/driver-api/device_link.rst b/Documentation/driver-api/device_link.rst
> index d6763272e747..2d5919b2b337 100644
> --- a/Documentation/driver-api/device_link.rst
> +++ b/Documentation/driver-api/device_link.rst
> @@ -1,6 +1,9 @@
>  .. |struct dev_pm_domain| replace:: :c:type:`struct dev_pm_domain <dev_pm_domain>`
>  .. |struct generic_pm_domain| replace:: :c:type:`struct generic_pm_domain <generic_pm_domain>`
>
> +
> +.. _device_link:
> +
>  ============
>  Device links
>  ============
> diff --git a/Documentation/driver-api/index.rst b/Documentation/driver-api/index.rst
> index ab38ced66a44..c0b600ed9961 100644
> --- a/Documentation/driver-api/index.rst
> +++ b/Documentation/driver-api/index.rst
> @@ -22,6 +22,7 @@ available subsections can be seen below.
>     device_connection
>     dma-buf
>     device_link
> +   component

Do I think correctly that this doc is going to be generated
automatically from the kerneldoc comments in component.c?

>     message-based
>     sound
>     frame-buffer
> diff --git a/drivers/base/component.c b/drivers/base/component.c
> index ddcea8739c12..e5b04bce8544 100644
> --- a/drivers/base/component.c
> +++ b/drivers/base/component.c
> @@ -16,6 +16,33 @@
>  #include <linux/slab.h>
>  #include <linux/debugfs.h>
>
> +/**
> + * DOC: overview
> + *
> + * The component frameworks allows drivers to collect a pile of sub-devices,

s/frameworks/framework/

> + * including their bound drivers, into an aggregate driver. Various subsystem

s/subsystem/subsystems/

> + * already provide functions to get hold of such components, e.g.
> + * of_clk_get_by_name(). Anytime there's such a subsystem specific way to find a
> + * a device the component framework should not be used.

I would use a positive statement here, like "The component framework
can be used when such a subsystem-specific way to find a device is not
available".

> The component framework
> + * fills the niche of aggregate drivers for specific hardware, where further
> + * standardization into a subsystem doesn't make sense.

I would say "would not be practical" instead of "doesn't make sense".

> The common example is
> + * when a logical device (e.g. a DRM display driver) is spread around the SoC on
> + * various component (scanout engines, blending blocks, transcoders for various
> + * outputs and so on).
> + *
> + * The component framework also doesn't solve runtime dependencies, e.g. for
> + * system suspend and resume operations. See also :ref:`device
> + * links<device_link>`.
> + *
> + * Components are registered using component_add() and unregistered with
> + * component_del(), usually from the driver's probe and disconnect functions.
> + *
> + * Aggregate drivers first assemble a component match list of what they need
> + * using component_match_add(). This is then registered as an aggregate driver
> + * using component_master_add_with_match(), and unregistered using
> + * component_master_del().
> + */
> +
>  struct component;
>
>  struct component_match_array {
> @@ -301,10 +328,24 @@ static int component_match_realloc(struct device *dev,
>         return 0;
>  }
>
> -/*
> - * Add a component to be matched, with a release function.
> +/**
> + * component_match_add_release - add a compent match with release callback

s/compent/component/ ?

> + * @master: device with the aggregate driver
> + * @matchptr: pointer to the list of component matches
> + * @release: release function for @compare_data
> + * @compare: compare function to match against all components
> + * @compare_data: opaque pointer passed to the @compare function
> + *
> + * This adds a new component match to the list stored in @matchptr, which the
> + * @master aggregate driver needs to function. @matchptr must be initialized to
> + * NULL before adding the first match.
> + *
> + * The allocated match list in @matchptr is automatically released using devm
> + * actions. At that point @release will be called, to free any references held
> + * by @compare_data, e.g. when @compare_data is a &device_node that must be
> + * released with of_node_put().
>   *
> - * The match array is first created or extended if necessary.
> + * See also component_match_add().
>   */
>  void component_match_add_release(struct device *master,
>         struct component_match **matchptr,
> @@ -367,6 +408,18 @@ static void free_master(struct master *master)
>         kfree(master);
>  }
>
> +/**
> + * component_master_add_with_match - register an aggregate driver
> + * @dev: device with the aggregate driver
> + * @ops: callbacks for the aggregate driver
> + * @match: component match list for the aggregate driver
> + *
> + * Registers a new aggregate driver consisting of the components added to @match
> + * by calling one of the component_match_add() functions. Once all components in
> + * @match are available it will be assembled by calling

A comma seems to be missing after "available".

> + * &component_master_ops.bind from @ops. Must be unregistered by calling
> + * component_master_del().
> + */
>  int component_master_add_with_match(struct device *dev,
>         const struct component_master_ops *ops,
>         struct component_match *match)
> @@ -403,6 +456,15 @@ int component_master_add_with_match(struct device *dev,
>  }
>  EXPORT_SYMBOL_GPL(component_master_add_with_match);
>
> +/**
> + * component_master_del - unregister an aggregate driver
> + * @dev: device with the aggregate driver
> + * @ops: callbacks for the aggregate driver
> + *
> + * Unregistered an aggregate driver registered with

s/Unregistered/Unregisters/ ?

> + * component_master_add_with_match(). If necessary the aggregate driver is first
> + * disassembled by calling &component_master_ops.unbind from @ops.

Q: How does the &component_master_ops.unbind annotation work?  Does it
produce any special output?

> + */
>  void component_master_del(struct device *dev,
>         const struct component_master_ops *ops)
>  {
> @@ -430,6 +492,15 @@ static void component_unbind(struct component *component,
>         devres_release_group(component->dev, component);
>  }
>
> +/**
> + * component_unbind_all - unbind all component to an aggregate driver
> + * @master_dev: device with the aggregate driver
> + * @data: opaque pointer, passed to all components
> + *
> + * This unbinds all components to the aggregate @dev by passing @data to their

I guess "This" is redundant.

> + * &component_ops.unbind functions. Should be called from
> + * &component_master_ops.unbind.
> + */
>  void component_unbind_all(struct device *master_dev, void *data)
>  {
>         struct master *master;
> @@ -503,6 +574,15 @@ static int component_bind(struct component *component, struct master *master,
>         return ret;
>  }
>
> +/**
> + * component_bind_all - bind all component to an aggregate driver
> + * @master_dev: device with the aggregate driver
> + * @data: opaque pointer, passed to all components
> + *
> + * This binds all components to the aggregate @dev by passing @data to their

Likewise.

> + * &component_ops.bind functions. Should be called from
> + * &component_master_ops.bind.
> + */
>  int component_bind_all(struct device *master_dev, void *data)
>  {
>         struct master *master;
> @@ -537,6 +617,18 @@ int component_bind_all(struct device *master_dev, void *data)
>  }
>  EXPORT_SYMBOL_GPL(component_bind_all);
>
> +/**
> + * component_add - register a component
> + * @dev: component device
> + * @ops: component callbacks
> + *
> + * Register a new component for @dev. Functions in @ops will be call when the

s/call/called/

> + * aggregate driver is ready to bind the overall driver by calling
> + * component_bind_all(). See also &struct component_ops.
> + *
> + * The component needs to be unregistered again at driver unload/disconnect by
> + * calling component_del().
> + */
>  int component_add(struct device *dev, const struct component_ops *ops)
>  {
>         struct component *component;
> @@ -568,6 +660,15 @@ int component_add(struct device *dev, const struct component_ops *ops)
>  }
>  EXPORT_SYMBOL_GPL(component_add);
>
> +/**
> + * component_del - unregister a component
> + * @dev: component device
> + * @ops: component callbacks
> + *
> + * Unregister a component added with component_add(). If the component is bound
> + * into an aggregate driver this will force the entire aggrate driver, including

A comma is missing after "driver".  Also s/aggrate/aggregate/

> + * all its components, to be unbound.
> + */
>  void component_del(struct device *dev, const struct component_ops *ops)
>  {
>         struct component *c, *component = NULL;
> diff --git a/include/linux/component.h b/include/linux/component.h
> index e71fbbbc74e2..67a899dd2e10 100644
> --- a/include/linux/component.h
> +++ b/include/linux/component.h
> @@ -4,11 +4,31 @@
>
>  #include <linux/stddef.h>
>
> +
>  struct device;
>
> +/**
> + * struct component_ops - callbacks for component drivers
> + *
> + * Components are registered with component_add() and unregistered with
> + * component_del().
> + */
>  struct component_ops {
> +       /**
> +        * @bind:
> +        *
> +        * Called through component_bind_all() when the aggregate driver is
> +        * ready to bind the overall driver.
> +        */
>         int (*bind)(struct device *comp, struct device *master,
>                     void *master_data);
> +       /**
> +        * @unbind:
> +        *
> +        * Called through component_unbind_all() when the aggregate driver is
> +        * ready to bind the overall driver, or when component_bind_all() fails
> +        * part-ways through and needs to unbind some already bound components.
> +        */
>         void (*unbind)(struct device *comp, struct device *master,
>                        void *master_data);
>  };
> @@ -21,8 +41,42 @@ void component_unbind_all(struct device *master, void *master_data);
>
>  struct master;
>
> +/**
> + * struct component_master_ops - callback for the aggregate driver
> + *
> + * Aggregate drivers are registered with component_master_add_with_match() and
> + * unregistered with component_master_del().
> + */
>  struct component_master_ops {
> +       /**
> +        * @bind:
> +        *
> +        * Called when all components or the aggregate driver, as specified in
> +        * the match list passed to component_master_add_with_match(), are
> +        * ready. Usually there are 3 steps to bind an aggregate driver:
> +        *
> +        * 1. Allocate a structure for the aggregate driver.
> +        *
> +        * 2. Bind all components to the aggregate driver by calling
> +        *    component_bind_all() with the aggregate driver structure as opaque
> +        *    pointer data.
> +        *
> +        * 3. Register the aggregate driver with the subsystem to publish its
> +        *    interfaces.
> +        *
> +        * Note that the lifetime of the aggregate driver does not align with
> +        * any of the underlying &struct device instances. Therefore devm cannot
> +        * be used and all resources acquired or allocated in this callback must
> +        * be expecitly released in the @unbind callback.

s/expecitly/explicitly/

> +        */
>         int (*bind)(struct device *master);
> +       /**
> +        * @unbind:
> +        *
> +        * Called when either the aggregate driver, using
> +        * component_master_del(), or one of its components, using
> +        * component_del(), is unregistered.
> +        */
>         void (*unbind)(struct device *master);
>  };
>
> @@ -38,6 +92,22 @@ void component_match_add_release(struct device *master,
>         void (*release)(struct device *, void *),
>         int (*compare)(struct device *, void *), void *compare_data);
>
> +/**
> + * component_match_add - add a compent match
> + * @master: device with the aggregate driver
> + * @matchptr: pointer to the list of component matches
> + * @compare: compare function to match against all components
> + * @compare_data: opaque pointer passed to the @compare function
> + *
> + * This adds a new component match to the list stored in @matchptr, which the

"This" appears to be redundant.

> + * @master aggregate driver needs to function. @matchptr must be initialized to
> + * NULL before adding the first match.
> + *
> + * The allocated match list in @matchptr is automatically released using devm
> + * actions.
> + *
> + * See also component_match_add_release().
> + */
>  static inline void component_match_add(struct device *master,
>         struct component_match **matchptr,
>         int (*compare)(struct device *, void *), void *compare_data)
> --
> 2.20.1
>

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

* RE: [PATCH v10 23/40] misc/mei/hdcp: Client driver for HDCP application
  2019-01-31  6:59 ` [PATCH v10 23/40] misc/mei/hdcp: Client driver for HDCP application Ramalingam C
@ 2019-02-05 12:33   ` Winkler, Tomas
  0 siblings, 0 replies; 121+ messages in thread
From: Winkler, Tomas @ 2019-02-05 12:33 UTC (permalink / raw)
  To: C, Ramalingam, intel-gfx, dri-devel, daniel.vetter, Shankar, Uma

> 
> 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
> d9215fc4e499..8c2d9565a4cb 100644
> --- a/drivers/misc/mei/Makefile
> +++ b/drivers/misc/mei/Makefile
> @@ -24,3 +24,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..b2de072aa0de
> --- /dev/null
> +++ b/drivers/misc/mei/hdcp/Makefile
> @@ -0,0 +1,7 @@
> +# SPDX-License-Identifier: GPL-2.0+
> +#
> +# 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..ca5010ad7dd7
> --- /dev/null
> +++ b/drivers/misc/mei/hdcp/mei_hdcp.c
> @@ -0,0 +1,65 @@
> +// SPDX-License-Identifier: (GPL-2.0+)
GPL-2.0 (drop +)
> +/*
> + * 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)
Should be now moving to GUID_INIT from UUID_LE()
Thought it may  be done later. 

> +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("GPL");
> +MODULE_DESCRIPTION("MEI HDCP");
> --
> 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] 121+ messages in thread

* RE: [PATCH v10 24/40] misc/mei/hdcp: Define ME FW interface for HDCP2.2
  2019-02-04 16:07   ` Shankar, Uma
@ 2019-02-05 13:01     ` Winkler, Tomas
  0 siblings, 0 replies; 121+ messages in thread
From: Winkler, Tomas @ 2019-02-05 13:01 UTC (permalink / raw)
  To: Shankar, Uma, C, Ramalingam, intel-gfx, dri-devel, daniel.vetter


> 
> >-----Original Message-----
> >From: C, Ramalingam
> >Sent: Thursday, January 31, 2019 12:30 PM
> >To: intel-gfx@lists.freedesktop.org; dri-devel@lists.freedesktop.org;
> >daniel.vetter@ffwll.ch; Winkler, Tomas <tomas.winkler@intel.com>;
> >Shankar, Uma <uma.shankar@intel.com>
> >Cc: C, Ramalingam <ramalingam.c@intel.com>
> >Subject: [PATCH v10 24/40] misc/mei/hdcp: Define ME FW interface for
> >HDCP2.2
> >
> >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>
> 
> Looks ok to me.
> Reviewed-by: Uma Shankar <uma.shankar@intel.com>
Acked-by Tomas Winkler <tomas.winkler@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..582a7e27ae29
> >--- /dev/null
> >+++ b/drivers/misc/mei/hdcp/mei_hdcp.h
> >@@ -0,0 +1,366 @@
> >+/* SPDX-License-Identifier: (GPL-2.0+) */
> >+/*
> >+ * 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

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

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

* Re: [PATCH v10 25/40] misc/mei/hdcp: Initiate Wired HDCP2.2 Tx Session
  2019-02-04 16:09   ` Shankar, Uma
@ 2019-02-05 13:09     ` Winkler, Tomas
  2019-02-05 14:13       ` C, Ramalingam
  2019-02-06 10:27       ` Winkler, Tomas
  0 siblings, 2 replies; 121+ messages in thread
From: Winkler, Tomas @ 2019-02-05 13:09 UTC (permalink / raw)
  To: C, Ramalingam, intel-gfx, dri-devel, daniel.vetter


> >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>
> 
> Latest set look ok. You can keep the RB.
> 
> >---
> > drivers/misc/mei/hdcp/mei_hdcp.c | 82
> >++++++++++++++++++++++++++++++++++++++++
> > drivers/misc/mei/hdcp/mei_hdcp.h | 28 ++++++++++++++
> > 2 files changed, 110 insertions(+)
> >
> >diff --git a/drivers/misc/mei/hdcp/mei_hdcp.c
> >b/drivers/misc/mei/hdcp/mei_hdcp.c
> >index ca5010ad7dd7..534d29c8ee86 100644
> >--- a/drivers/misc/mei/hdcp/mei_hdcp.c
> >+++ b/drivers/misc/mei/hdcp/mei_hdcp.c
> >@@ -23,6 +23,88 @@
> > #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 <drm/i915_mei_hdcp_interface.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) {


Breaking naming conventions : all functions should be prefixed with mei_hdcp_ 

e.g. mei_hdcp_ initiate_session() 

> >+	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 582a7e27ae29..f831db3cbd54 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 {
We've already reviewed. Move to i915 header or use mei_ prefix?
> >+	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	[flat|nested] 121+ messages in thread

* Re: [PATCH v10 25/40] misc/mei/hdcp: Initiate Wired HDCP2.2 Tx Session
  2019-02-05 13:09     ` Winkler, Tomas
@ 2019-02-05 14:13       ` C, Ramalingam
  2019-02-06 10:27       ` Winkler, Tomas
  1 sibling, 0 replies; 121+ messages in thread
From: C, Ramalingam @ 2019-02-05 14:13 UTC (permalink / raw)
  To: Winkler, Tomas, intel-gfx, dri-devel, daniel.vetter


Thanks Tomas.

On 2/5/2019 6:39 PM, Winkler, Tomas wrote:
>>> 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>
>> Latest set look ok. You can keep the RB.
>>
>>> ---
>>> drivers/misc/mei/hdcp/mei_hdcp.c | 82
>>> ++++++++++++++++++++++++++++++++++++++++
>>> drivers/misc/mei/hdcp/mei_hdcp.h | 28 ++++++++++++++
>>> 2 files changed, 110 insertions(+)
>>>
>>> diff --git a/drivers/misc/mei/hdcp/mei_hdcp.c
>>> b/drivers/misc/mei/hdcp/mei_hdcp.c
>>> index ca5010ad7dd7..534d29c8ee86 100644
>>> --- a/drivers/misc/mei/hdcp/mei_hdcp.c
>>> +++ b/drivers/misc/mei/hdcp/mei_hdcp.c
>>> @@ -23,6 +23,88 @@
>>> #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 <drm/i915_mei_hdcp_interface.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) {
>
> Breaking naming conventions : all functions should be prefixed with mei_hdcp_
>
> e.g. mei_hdcp_ initiate_session()
I will rename all the function name similarly.

--Ram
>
>>> +	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 582a7e27ae29..f831db3cbd54 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 {
> We've already reviewed. Move to i915 header or use mei_ prefix?
renaming it to mei_i915_port, like wise s/mei_hdcp_ddi/mei_fw_ddi to 
make more sense

--Ram
>>> +	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	[flat|nested] 121+ messages in thread

* Re: [PATCH 1/2] component: Add documentation
  2019-02-05 10:47     ` [PATCH 1/2] component: Add documentation Rafael J. Wysocki
@ 2019-02-05 16:20       ` Daniel Vetter
  0 siblings, 0 replies; 121+ messages in thread
From: Daniel Vetter @ 2019-02-05 16:20 UTC (permalink / raw)
  To: Rafael J. Wysocki
  Cc: Daniel Vetter, DRI Development, LKML, C, Ramalingam,
	Greg Kroah-Hartman, Russell King, Jaroslav Kysela, Takashi Iwai,
	Rodrigo Vivi, Jani Nikula, Daniel Vetter

On Tue, Feb 05, 2019 at 11:47:58AM +0100, Rafael J. Wysocki wrote:
>  w/compOn Thu, Jan 31, 2019 at 3:46 PM Daniel Vetter
> <daniel.vetter@ffwll.ch> wrote:
> >
> > Someone owes me a beer ...
> >
> > While typing these I think doing an s/component_master/aggregate/
> > would be useful:
> > - it's shorter :-)
> > - I think component/aggregate is much more meaningful naming than
> >   component/puppetmaster or something like that. At least to my
> >   English ear "aggregate" emphasizes much more the "assemble a pile of
> >   things into something bigger" aspect, and there's not really much
> >   of a control hierarchy between aggregate and constituing components.
> >
> > But that's way more than a quick doc typing exercise ...
> >
> > Thanks to Ram for commenting on an initial draft of these docs.
> 
> Look goods to me overall (even though I'm not super-familiar with the
> component framework), but see below.
> 
> > Cc: "C, Ramalingam" <ramalingam.c@intel.com>
> > Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
> > Cc: Russell King <rmk+kernel@arm.linux.org.uk>
> > Cc: Rafael J. Wysocki <rafael@kernel.org>
> > Cc: Jaroslav Kysela <perex@perex.cz>
> > Cc: Takashi Iwai <tiwai@suse.com>
> > Cc: Rodrigo Vivi <rodrigo.vivi@intel.com>
> > Cc: Jani Nikula <jani.nikula@linux.intel.com>
> > Signed-off-by: Daniel Vetter <daniel.vetter@intel.com>
> > ---
> >  Documentation/driver-api/device_link.rst |   3 +
> >  Documentation/driver-api/index.rst       |   1 +
> >  drivers/base/component.c                 | 107 ++++++++++++++++++++++-
> >  include/linux/component.h                |  70 +++++++++++++++
> >  4 files changed, 178 insertions(+), 3 deletions(-)
> >
> > diff --git a/Documentation/driver-api/device_link.rst b/Documentation/driver-api/device_link.rst
> > index d6763272e747..2d5919b2b337 100644
> > --- a/Documentation/driver-api/device_link.rst
> > +++ b/Documentation/driver-api/device_link.rst
> > @@ -1,6 +1,9 @@
> >  .. |struct dev_pm_domain| replace:: :c:type:`struct dev_pm_domain <dev_pm_domain>`
> >  .. |struct generic_pm_domain| replace:: :c:type:`struct generic_pm_domain <generic_pm_domain>`
> >
> > +
> > +.. _device_link:
> > +
> >  ============
> >  Device links
> >  ============
> > diff --git a/Documentation/driver-api/index.rst b/Documentation/driver-api/index.rst
> > index ab38ced66a44..c0b600ed9961 100644
> > --- a/Documentation/driver-api/index.rst
> > +++ b/Documentation/driver-api/index.rst
> > @@ -22,6 +22,7 @@ available subsections can be seen below.
> >     device_connection
> >     dma-buf
> >     device_link
> > +   component
> 
> Do I think correctly that this doc is going to be generated
> automatically from the kerneldoc comments in component.c?

No. I failed to git add component.rst, which has the necessary kernel-doc
directives to generate the documentation from the source code comments.

I've implemented all your other suggestions, thanks a lot for taking a
lot. Will send out v2 asap.

Thanks, Daniel

> 
> >     message-based
> >     sound
> >     frame-buffer
> > diff --git a/drivers/base/component.c b/drivers/base/component.c
> > index ddcea8739c12..e5b04bce8544 100644
> > --- a/drivers/base/component.c
> > +++ b/drivers/base/component.c
> > @@ -16,6 +16,33 @@
> >  #include <linux/slab.h>
> >  #include <linux/debugfs.h>
> >
> > +/**
> > + * DOC: overview
> > + *
> > + * The component frameworks allows drivers to collect a pile of sub-devices,
> 
> s/frameworks/framework/
> 
> > + * including their bound drivers, into an aggregate driver. Various subsystem
> 
> s/subsystem/subsystems/
> 
> > + * already provide functions to get hold of such components, e.g.
> > + * of_clk_get_by_name(). Anytime there's such a subsystem specific way to find a
> > + * a device the component framework should not be used.
> 
> I would use a positive statement here, like "The component framework
> can be used when such a subsystem-specific way to find a device is not
> available".
> 
> > The component framework
> > + * fills the niche of aggregate drivers for specific hardware, where further
> > + * standardization into a subsystem doesn't make sense.
> 
> I would say "would not be practical" instead of "doesn't make sense".
> 
> > The common example is
> > + * when a logical device (e.g. a DRM display driver) is spread around the SoC on
> > + * various component (scanout engines, blending blocks, transcoders for various
> > + * outputs and so on).
> > + *
> > + * The component framework also doesn't solve runtime dependencies, e.g. for
> > + * system suspend and resume operations. See also :ref:`device
> > + * links<device_link>`.
> > + *
> > + * Components are registered using component_add() and unregistered with
> > + * component_del(), usually from the driver's probe and disconnect functions.
> > + *
> > + * Aggregate drivers first assemble a component match list of what they need
> > + * using component_match_add(). This is then registered as an aggregate driver
> > + * using component_master_add_with_match(), and unregistered using
> > + * component_master_del().
> > + */
> > +
> >  struct component;
> >
> >  struct component_match_array {
> > @@ -301,10 +328,24 @@ static int component_match_realloc(struct device *dev,
> >         return 0;
> >  }
> >
> > -/*
> > - * Add a component to be matched, with a release function.
> > +/**
> > + * component_match_add_release - add a compent match with release callback
> 
> s/compent/component/ ?
> 
> > + * @master: device with the aggregate driver
> > + * @matchptr: pointer to the list of component matches
> > + * @release: release function for @compare_data
> > + * @compare: compare function to match against all components
> > + * @compare_data: opaque pointer passed to the @compare function
> > + *
> > + * This adds a new component match to the list stored in @matchptr, which the
> > + * @master aggregate driver needs to function. @matchptr must be initialized to
> > + * NULL before adding the first match.
> > + *
> > + * The allocated match list in @matchptr is automatically released using devm
> > + * actions. At that point @release will be called, to free any references held
> > + * by @compare_data, e.g. when @compare_data is a &device_node that must be
> > + * released with of_node_put().
> >   *
> > - * The match array is first created or extended if necessary.
> > + * See also component_match_add().
> >   */
> >  void component_match_add_release(struct device *master,
> >         struct component_match **matchptr,
> > @@ -367,6 +408,18 @@ static void free_master(struct master *master)
> >         kfree(master);
> >  }
> >
> > +/**
> > + * component_master_add_with_match - register an aggregate driver
> > + * @dev: device with the aggregate driver
> > + * @ops: callbacks for the aggregate driver
> > + * @match: component match list for the aggregate driver
> > + *
> > + * Registers a new aggregate driver consisting of the components added to @match
> > + * by calling one of the component_match_add() functions. Once all components in
> > + * @match are available it will be assembled by calling
> 
> A comma seems to be missing after "available".
> 
> > + * &component_master_ops.bind from @ops. Must be unregistered by calling
> > + * component_master_del().
> > + */
> >  int component_master_add_with_match(struct device *dev,
> >         const struct component_master_ops *ops,
> >         struct component_match *match)
> > @@ -403,6 +456,15 @@ int component_master_add_with_match(struct device *dev,
> >  }
> >  EXPORT_SYMBOL_GPL(component_master_add_with_match);
> >
> > +/**
> > + * component_master_del - unregister an aggregate driver
> > + * @dev: device with the aggregate driver
> > + * @ops: callbacks for the aggregate driver
> > + *
> > + * Unregistered an aggregate driver registered with
> 
> s/Unregistered/Unregisters/ ?
> 
> > + * component_master_add_with_match(). If necessary the aggregate driver is first
> > + * disassembled by calling &component_master_ops.unbind from @ops.
> 
> Q: How does the &component_master_ops.unbind annotation work?  Does it
> produce any special output?
> 
> > + */
> >  void component_master_del(struct device *dev,
> >         const struct component_master_ops *ops)
> >  {
> > @@ -430,6 +492,15 @@ static void component_unbind(struct component *component,
> >         devres_release_group(component->dev, component);
> >  }
> >
> > +/**
> > + * component_unbind_all - unbind all component to an aggregate driver
> > + * @master_dev: device with the aggregate driver
> > + * @data: opaque pointer, passed to all components
> > + *
> > + * This unbinds all components to the aggregate @dev by passing @data to their
> 
> I guess "This" is redundant.
> 
> > + * &component_ops.unbind functions. Should be called from
> > + * &component_master_ops.unbind.
> > + */
> >  void component_unbind_all(struct device *master_dev, void *data)
> >  {
> >         struct master *master;
> > @@ -503,6 +574,15 @@ static int component_bind(struct component *component, struct master *master,
> >         return ret;
> >  }
> >
> > +/**
> > + * component_bind_all - bind all component to an aggregate driver
> > + * @master_dev: device with the aggregate driver
> > + * @data: opaque pointer, passed to all components
> > + *
> > + * This binds all components to the aggregate @dev by passing @data to their
> 
> Likewise.
> 
> > + * &component_ops.bind functions. Should be called from
> > + * &component_master_ops.bind.
> > + */
> >  int component_bind_all(struct device *master_dev, void *data)
> >  {
> >         struct master *master;
> > @@ -537,6 +617,18 @@ int component_bind_all(struct device *master_dev, void *data)
> >  }
> >  EXPORT_SYMBOL_GPL(component_bind_all);
> >
> > +/**
> > + * component_add - register a component
> > + * @dev: component device
> > + * @ops: component callbacks
> > + *
> > + * Register a new component for @dev. Functions in @ops will be call when the
> 
> s/call/called/
> 
> > + * aggregate driver is ready to bind the overall driver by calling
> > + * component_bind_all(). See also &struct component_ops.
> > + *
> > + * The component needs to be unregistered again at driver unload/disconnect by
> > + * calling component_del().
> > + */
> >  int component_add(struct device *dev, const struct component_ops *ops)
> >  {
> >         struct component *component;
> > @@ -568,6 +660,15 @@ int component_add(struct device *dev, const struct component_ops *ops)
> >  }
> >  EXPORT_SYMBOL_GPL(component_add);
> >
> > +/**
> > + * component_del - unregister a component
> > + * @dev: component device
> > + * @ops: component callbacks
> > + *
> > + * Unregister a component added with component_add(). If the component is bound
> > + * into an aggregate driver this will force the entire aggrate driver, including
> 
> A comma is missing after "driver".  Also s/aggrate/aggregate/
> 
> > + * all its components, to be unbound.
> > + */
> >  void component_del(struct device *dev, const struct component_ops *ops)
> >  {
> >         struct component *c, *component = NULL;
> > diff --git a/include/linux/component.h b/include/linux/component.h
> > index e71fbbbc74e2..67a899dd2e10 100644
> > --- a/include/linux/component.h
> > +++ b/include/linux/component.h
> > @@ -4,11 +4,31 @@
> >
> >  #include <linux/stddef.h>
> >
> > +
> >  struct device;
> >
> > +/**
> > + * struct component_ops - callbacks for component drivers
> > + *
> > + * Components are registered with component_add() and unregistered with
> > + * component_del().
> > + */
> >  struct component_ops {
> > +       /**
> > +        * @bind:
> > +        *
> > +        * Called through component_bind_all() when the aggregate driver is
> > +        * ready to bind the overall driver.
> > +        */
> >         int (*bind)(struct device *comp, struct device *master,
> >                     void *master_data);
> > +       /**
> > +        * @unbind:
> > +        *
> > +        * Called through component_unbind_all() when the aggregate driver is
> > +        * ready to bind the overall driver, or when component_bind_all() fails
> > +        * part-ways through and needs to unbind some already bound components.
> > +        */
> >         void (*unbind)(struct device *comp, struct device *master,
> >                        void *master_data);
> >  };
> > @@ -21,8 +41,42 @@ void component_unbind_all(struct device *master, void *master_data);
> >
> >  struct master;
> >
> > +/**
> > + * struct component_master_ops - callback for the aggregate driver
> > + *
> > + * Aggregate drivers are registered with component_master_add_with_match() and
> > + * unregistered with component_master_del().
> > + */
> >  struct component_master_ops {
> > +       /**
> > +        * @bind:
> > +        *
> > +        * Called when all components or the aggregate driver, as specified in
> > +        * the match list passed to component_master_add_with_match(), are
> > +        * ready. Usually there are 3 steps to bind an aggregate driver:
> > +        *
> > +        * 1. Allocate a structure for the aggregate driver.
> > +        *
> > +        * 2. Bind all components to the aggregate driver by calling
> > +        *    component_bind_all() with the aggregate driver structure as opaque
> > +        *    pointer data.
> > +        *
> > +        * 3. Register the aggregate driver with the subsystem to publish its
> > +        *    interfaces.
> > +        *
> > +        * Note that the lifetime of the aggregate driver does not align with
> > +        * any of the underlying &struct device instances. Therefore devm cannot
> > +        * be used and all resources acquired or allocated in this callback must
> > +        * be expecitly released in the @unbind callback.
> 
> s/expecitly/explicitly/
> 
> > +        */
> >         int (*bind)(struct device *master);
> > +       /**
> > +        * @unbind:
> > +        *
> > +        * Called when either the aggregate driver, using
> > +        * component_master_del(), or one of its components, using
> > +        * component_del(), is unregistered.
> > +        */
> >         void (*unbind)(struct device *master);
> >  };
> >
> > @@ -38,6 +92,22 @@ void component_match_add_release(struct device *master,
> >         void (*release)(struct device *, void *),
> >         int (*compare)(struct device *, void *), void *compare_data);
> >
> > +/**
> > + * component_match_add - add a compent match
> > + * @master: device with the aggregate driver
> > + * @matchptr: pointer to the list of component matches
> > + * @compare: compare function to match against all components
> > + * @compare_data: opaque pointer passed to the @compare function
> > + *
> > + * This adds a new component match to the list stored in @matchptr, which the
> 
> "This" appears to be redundant.
> 
> > + * @master aggregate driver needs to function. @matchptr must be initialized to
> > + * NULL before adding the first match.
> > + *
> > + * The allocated match list in @matchptr is automatically released using devm
> > + * actions.
> > + *
> > + * See also component_match_add_release().
> > + */
> >  static inline void component_match_add(struct device *master,
> >         struct component_match **matchptr,
> >         int (*compare)(struct device *, void *), void *compare_data)
> > --
> > 2.20.1
> >

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

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

* [PATCH] component: Add documentation
  2019-01-31 14:46   ` [PATCH 1/2] component: Add documentation Daniel Vetter
  2019-01-31 14:46     ` [PATCH 2/2] components: multiple components for a device Daniel Vetter
  2019-02-05 10:47     ` [PATCH 1/2] component: Add documentation Rafael J. Wysocki
@ 2019-02-05 16:21     ` Daniel Vetter
  2019-02-05 16:49       ` Russell King - ARM Linux admin
  2 siblings, 1 reply; 121+ messages in thread
From: Daniel Vetter @ 2019-02-05 16:21 UTC (permalink / raw)
  To: DRI Development
  Cc: LKML, Daniel Vetter, C, Ramalingam, Greg Kroah-Hartman,
	Russell King, Rafael J . Wysocki, Jaroslav Kysela, Takashi Iwai,
	Rodrigo Vivi, Jani Nikula, Daniel Vetter

Someone owes me a beer ...

While typing these I think doing an s/component_master/aggregate/
would be useful:
- it's shorter :-)
- I think component/aggregate is much more meaningful naming than
  component/puppetmaster or something like that. At least to my
  English ear "aggregate" emphasizes much more the "assemble a pile of
  things into something bigger" aspect, and there's not really much
  of a control hierarchy between aggregate and constituing components.

But that's way more than a quick doc typing exercise ...

Thanks to Ram for commenting on an initial draft of these docs.

v2: Review from Rafael:
- git add Documenation/driver-api/component.rst
- lots of polish to the wording + spelling fixes.

Cc: "C, Ramalingam" <ramalingam.c@intel.com>
Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Cc: Russell King <rmk+kernel@arm.linux.org.uk>
Cc: Rafael J. Wysocki <rafael@kernel.org>
Cc: Jaroslav Kysela <perex@perex.cz>
Cc: Takashi Iwai <tiwai@suse.com>
Cc: Rodrigo Vivi <rodrigo.vivi@intel.com>
Cc: Jani Nikula <jani.nikula@linux.intel.com>
Signed-off-by: Daniel Vetter <daniel.vetter@intel.com>
---
 Documentation/driver-api/component.rst   |  17 ++++
 Documentation/driver-api/device_link.rst |   3 +
 Documentation/driver-api/index.rst       |   1 +
 drivers/base/component.c                 | 107 ++++++++++++++++++++++-
 include/linux/component.h                |  70 +++++++++++++++
 5 files changed, 195 insertions(+), 3 deletions(-)
 create mode 100644 Documentation/driver-api/component.rst

diff --git a/Documentation/driver-api/component.rst b/Documentation/driver-api/component.rst
new file mode 100644
index 000000000000..3407ff0424b9
--- /dev/null
+++ b/Documentation/driver-api/component.rst
@@ -0,0 +1,17 @@
+=========================================
+Component Framework for Aggregate Drivers
+=========================================
+
+.. kernel-doc:: drivers/base/component.c
+   :doc: overview
+
+
+API
+===
+
+.. kernel-doc:: include/linux/component.h
+   :internal:
+
+.. kernel-doc:: drivers/base/component.c
+   :export:
+
diff --git a/Documentation/driver-api/device_link.rst b/Documentation/driver-api/device_link.rst
index d6763272e747..2d5919b2b337 100644
--- a/Documentation/driver-api/device_link.rst
+++ b/Documentation/driver-api/device_link.rst
@@ -1,6 +1,9 @@
 .. |struct dev_pm_domain| replace:: :c:type:`struct dev_pm_domain <dev_pm_domain>`
 .. |struct generic_pm_domain| replace:: :c:type:`struct generic_pm_domain <generic_pm_domain>`
 
+
+.. _device_link:
+
 ============
 Device links
 ============
diff --git a/Documentation/driver-api/index.rst b/Documentation/driver-api/index.rst
index ab38ced66a44..c0b600ed9961 100644
--- a/Documentation/driver-api/index.rst
+++ b/Documentation/driver-api/index.rst
@@ -22,6 +22,7 @@ available subsections can be seen below.
    device_connection
    dma-buf
    device_link
+   component
    message-based
    sound
    frame-buffer
diff --git a/drivers/base/component.c b/drivers/base/component.c
index ddcea8739c12..4851e1006f11 100644
--- a/drivers/base/component.c
+++ b/drivers/base/component.c
@@ -16,6 +16,33 @@
 #include <linux/slab.h>
 #include <linux/debugfs.h>
 
+/**
+ * DOC: overview
+ *
+ * The component framework allows drivers to collect a pile of sub-devices,
+ * including their bound drivers, into an aggregate driver. Various subsystems
+ * already provide functions to get hold of such components, e.g.
+ * of_clk_get_by_name(). The component framework can be used when such a
+ * subsystem-specific way to find a device is not available: The component
+ * framework fills the niche of aggregate drivers for specific hardware, where
+ * further standardization into a subsystem would not be practical. The common
+ * example is when a logical device (e.g. a DRM display driver) is spread around
+ * the SoC on various component (scanout engines, blending blocks, transcoders
+ * for various outputs and so on).
+ *
+ * The component framework also doesn't solve runtime dependencies, e.g. for
+ * system suspend and resume operations. See also :ref:`device
+ * links<device_link>`.
+ *
+ * Components are registered using component_add() and unregistered with
+ * component_del(), usually from the driver's probe and disconnect functions.
+ *
+ * Aggregate drivers first assemble a component match list of what they need
+ * using component_match_add(). This is then registered as an aggregate driver
+ * using component_master_add_with_match(), and unregistered using
+ * component_master_del().
+ */
+
 struct component;
 
 struct component_match_array {
@@ -301,10 +328,24 @@ static int component_match_realloc(struct device *dev,
 	return 0;
 }
 
-/*
- * Add a component to be matched, with a release function.
+/**
+ * component_match_add_release - add a component match with release callback
+ * @master: device with the aggregate driver
+ * @matchptr: pointer to the list of component matches
+ * @release: release function for @compare_data
+ * @compare: compare function to match against all components
+ * @compare_data: opaque pointer passed to the @compare function
+ *
+ * This adds a new component match to the list stored in @matchptr, which the
+ * @master aggregate driver needs to function. @matchptr must be initialized to
+ * NULL before adding the first match.
+ *
+ * The allocated match list in @matchptr is automatically released using devm
+ * actions. At that point @release will be called, to free any references held
+ * by @compare_data, e.g. when @compare_data is a &device_node that must be
+ * released with of_node_put().
  *
- * The match array is first created or extended if necessary.
+ * See also component_match_add().
  */
 void component_match_add_release(struct device *master,
 	struct component_match **matchptr,
@@ -367,6 +408,18 @@ static void free_master(struct master *master)
 	kfree(master);
 }
 
+/**
+ * component_master_add_with_match - register an aggregate driver
+ * @dev: device with the aggregate driver
+ * @ops: callbacks for the aggregate driver
+ * @match: component match list for the aggregate driver
+ *
+ * Registers a new aggregate driver consisting of the components added to @match
+ * by calling one of the component_match_add() functions. Once all components in
+ * @match are available, it will be assembled by calling
+ * &component_master_ops.bind from @ops. Must be unregistered by calling
+ * component_master_del().
+ */
 int component_master_add_with_match(struct device *dev,
 	const struct component_master_ops *ops,
 	struct component_match *match)
@@ -403,6 +456,15 @@ int component_master_add_with_match(struct device *dev,
 }
 EXPORT_SYMBOL_GPL(component_master_add_with_match);
 
+/**
+ * component_master_del - unregister an aggregate driver
+ * @dev: device with the aggregate driver
+ * @ops: callbacks for the aggregate driver
+ *
+ * Unregisters an aggregate driver registered with
+ * component_master_add_with_match(). If necessary the aggregate driver is first
+ * disassembled by calling &component_master_ops.unbind from @ops.
+ */
 void component_master_del(struct device *dev,
 	const struct component_master_ops *ops)
 {
@@ -430,6 +492,15 @@ static void component_unbind(struct component *component,
 	devres_release_group(component->dev, component);
 }
 
+/**
+ * component_unbind_all - unbind all component to an aggregate driver
+ * @master_dev: device with the aggregate driver
+ * @data: opaque pointer, passed to all components
+ *
+ * Unbinds all components to the aggregate @dev by passing @data to their
+ * &component_ops.unbind functions. Should be called from
+ * &component_master_ops.unbind.
+ */
 void component_unbind_all(struct device *master_dev, void *data)
 {
 	struct master *master;
@@ -503,6 +574,15 @@ static int component_bind(struct component *component, struct master *master,
 	return ret;
 }
 
+/**
+ * component_bind_all - bind all component to an aggregate driver
+ * @master_dev: device with the aggregate driver
+ * @data: opaque pointer, passed to all components
+ *
+ * Binds all components to the aggregate @dev by passing @data to their
+ * &component_ops.bind functions. Should be called from
+ * &component_master_ops.bind.
+ */
 int component_bind_all(struct device *master_dev, void *data)
 {
 	struct master *master;
@@ -537,6 +617,18 @@ int component_bind_all(struct device *master_dev, void *data)
 }
 EXPORT_SYMBOL_GPL(component_bind_all);
 
+/**
+ * component_add - register a component
+ * @dev: component device
+ * @ops: component callbacks
+ *
+ * Register a new component for @dev. Functions in @ops will be called when the
+ * aggregate driver is ready to bind the overall driver by calling
+ * component_bind_all(). See also &struct component_ops.
+ *
+ * The component needs to be unregistered again at driver unload/disconnect by
+ * calling component_del().
+ */
 int component_add(struct device *dev, const struct component_ops *ops)
 {
 	struct component *component;
@@ -568,6 +660,15 @@ int component_add(struct device *dev, const struct component_ops *ops)
 }
 EXPORT_SYMBOL_GPL(component_add);
 
+/**
+ * component_del - unregister a component
+ * @dev: component device
+ * @ops: component callbacks
+ *
+ * Unregister a component added with component_add(). If the component is bound
+ * into an aggregate driver, this will force the entire aggregate driver, including
+ * all its components, to be unbound.
+ */
 void component_del(struct device *dev, const struct component_ops *ops)
 {
 	struct component *c, *component = NULL;
diff --git a/include/linux/component.h b/include/linux/component.h
index e71fbbbc74e2..b5a989e3871e 100644
--- a/include/linux/component.h
+++ b/include/linux/component.h
@@ -4,11 +4,31 @@
 
 #include <linux/stddef.h>
 
+
 struct device;
 
+/**
+ * struct component_ops - callbacks for component drivers
+ *
+ * Components are registered with component_add() and unregistered with
+ * component_del().
+ */
 struct component_ops {
+	/**
+	 * @bind:
+	 *
+	 * Called through component_bind_all() when the aggregate driver is
+	 * ready to bind the overall driver.
+	 */
 	int (*bind)(struct device *comp, struct device *master,
 		    void *master_data);
+	/**
+	 * @unbind:
+	 *
+	 * Called through component_unbind_all() when the aggregate driver is
+	 * ready to bind the overall driver, or when component_bind_all() fails
+	 * part-ways through and needs to unbind some already bound components.
+	 */
 	void (*unbind)(struct device *comp, struct device *master,
 		       void *master_data);
 };
@@ -21,8 +41,42 @@ void component_unbind_all(struct device *master, void *master_data);
 
 struct master;
 
+/**
+ * struct component_master_ops - callback for the aggregate driver
+ *
+ * Aggregate drivers are registered with component_master_add_with_match() and
+ * unregistered with component_master_del().
+ */
 struct component_master_ops {
+	/**
+	 * @bind:
+	 *
+	 * Called when all components or the aggregate driver, as specified in
+	 * the match list passed to component_master_add_with_match(), are
+	 * ready. Usually there are 3 steps to bind an aggregate driver:
+	 *
+	 * 1. Allocate a structure for the aggregate driver.
+	 *
+	 * 2. Bind all components to the aggregate driver by calling
+	 *    component_bind_all() with the aggregate driver structure as opaque
+	 *    pointer data.
+	 *
+	 * 3. Register the aggregate driver with the subsystem to publish its
+	 *    interfaces.
+	 *
+	 * Note that the lifetime of the aggregate driver does not align with
+	 * any of the underlying &struct device instances. Therefore devm cannot
+	 * be used and all resources acquired or allocated in this callback must
+	 * be explicitly released in the @unbind callback.
+	 */
 	int (*bind)(struct device *master);
+	/**
+	 * @unbind:
+	 *
+	 * Called when either the aggregate driver, using
+	 * component_master_del(), or one of its components, using
+	 * component_del(), is unregistered.
+	 */
 	void (*unbind)(struct device *master);
 };
 
@@ -38,6 +92,22 @@ void component_match_add_release(struct device *master,
 	void (*release)(struct device *, void *),
 	int (*compare)(struct device *, void *), void *compare_data);
 
+/**
+ * component_match_add - add a compent match
+ * @master: device with the aggregate driver
+ * @matchptr: pointer to the list of component matches
+ * @compare: compare function to match against all components
+ * @compare_data: opaque pointer passed to the @compare function
+ *
+ * Adds a new component match to the list stored in @matchptr, which the
+ * @master aggregate driver needs to function. @matchptr must be initialized to
+ * NULL before adding the first match.
+ *
+ * The allocated match list in @matchptr is automatically released using devm
+ * actions.
+ *
+ * See also component_match_add_release().
+ */
 static inline void component_match_add(struct device *master,
 	struct component_match **matchptr,
 	int (*compare)(struct device *, void *), void *compare_data)
-- 
2.20.1


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

* Re: [PATCH] component: Add documentation
  2019-02-05 16:21     ` [PATCH] " Daniel Vetter
@ 2019-02-05 16:49       ` Russell King - ARM Linux admin
  2019-02-05 18:45         ` Daniel Vetter
  0 siblings, 1 reply; 121+ messages in thread
From: Russell King - ARM Linux admin @ 2019-02-05 16:49 UTC (permalink / raw)
  To: Daniel Vetter
  Cc: DRI Development, LKML, C, Ramalingam, Greg Kroah-Hartman,
	Rafael J . Wysocki, Jaroslav Kysela, Takashi Iwai, Rodrigo Vivi,
	Jani Nikula, Daniel Vetter

On Tue, Feb 05, 2019 at 05:21:07PM +0100, Daniel Vetter wrote:
> Someone owes me a beer ...

I find that deeply offensive - it is clearly directed at me personally
as author of the component helper.

There are double-standards in the kernel ecosystem with respect to
documentation - there are entire subsystems way more complicated than
the component *helper* which are lacking in documentation, and the
subsystem authors response to requests to change that basically get
ignored, or the response is "write the documentation yourself".

Why does there seem to be one rule for me and one rule for everyone
else?

Please remove this line.

> 
> While typing these I think doing an s/component_master/aggregate/
> would be useful:
> - it's shorter :-)
> - I think component/aggregate is much more meaningful naming than
>   component/puppetmaster or something like that. At least to my
>   English ear "aggregate" emphasizes much more the "assemble a pile of
>   things into something bigger" aspect, and there's not really much
>   of a control hierarchy between aggregate and constituing components.
> 
> But that's way more than a quick doc typing exercise ...
> 
> Thanks to Ram for commenting on an initial draft of these docs.
> 
> v2: Review from Rafael:
> - git add Documenation/driver-api/component.rst
> - lots of polish to the wording + spelling fixes.
> 
> Cc: "C, Ramalingam" <ramalingam.c@intel.com>
> Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
> Cc: Russell King <rmk+kernel@arm.linux.org.uk>
> Cc: Rafael J. Wysocki <rafael@kernel.org>
> Cc: Jaroslav Kysela <perex@perex.cz>
> Cc: Takashi Iwai <tiwai@suse.com>
> Cc: Rodrigo Vivi <rodrigo.vivi@intel.com>
> Cc: Jani Nikula <jani.nikula@linux.intel.com>
> Signed-off-by: Daniel Vetter <daniel.vetter@intel.com>
> ---
>  Documentation/driver-api/component.rst   |  17 ++++
>  Documentation/driver-api/device_link.rst |   3 +
>  Documentation/driver-api/index.rst       |   1 +
>  drivers/base/component.c                 | 107 ++++++++++++++++++++++-
>  include/linux/component.h                |  70 +++++++++++++++
>  5 files changed, 195 insertions(+), 3 deletions(-)
>  create mode 100644 Documentation/driver-api/component.rst
> 
> diff --git a/Documentation/driver-api/component.rst b/Documentation/driver-api/component.rst
> new file mode 100644
> index 000000000000..3407ff0424b9
> --- /dev/null
> +++ b/Documentation/driver-api/component.rst
> @@ -0,0 +1,17 @@
> +=========================================
> +Component Framework for Aggregate Drivers
> +=========================================
> +
> +.. kernel-doc:: drivers/base/component.c
> +   :doc: overview
> +
> +
> +API
> +===
> +
> +.. kernel-doc:: include/linux/component.h
> +   :internal:
> +
> +.. kernel-doc:: drivers/base/component.c
> +   :export:
> +
> diff --git a/Documentation/driver-api/device_link.rst b/Documentation/driver-api/device_link.rst
> index d6763272e747..2d5919b2b337 100644
> --- a/Documentation/driver-api/device_link.rst
> +++ b/Documentation/driver-api/device_link.rst
> @@ -1,6 +1,9 @@
>  .. |struct dev_pm_domain| replace:: :c:type:`struct dev_pm_domain <dev_pm_domain>`
>  .. |struct generic_pm_domain| replace:: :c:type:`struct generic_pm_domain <generic_pm_domain>`
>  
> +
> +.. _device_link:
> +
>  ============
>  Device links
>  ============
> diff --git a/Documentation/driver-api/index.rst b/Documentation/driver-api/index.rst
> index ab38ced66a44..c0b600ed9961 100644
> --- a/Documentation/driver-api/index.rst
> +++ b/Documentation/driver-api/index.rst
> @@ -22,6 +22,7 @@ available subsections can be seen below.
>     device_connection
>     dma-buf
>     device_link
> +   component
>     message-based
>     sound
>     frame-buffer
> diff --git a/drivers/base/component.c b/drivers/base/component.c
> index ddcea8739c12..4851e1006f11 100644
> --- a/drivers/base/component.c
> +++ b/drivers/base/component.c
> @@ -16,6 +16,33 @@
>  #include <linux/slab.h>
>  #include <linux/debugfs.h>
>  
> +/**
> + * DOC: overview
> + *
> + * The component framework allows drivers to collect a pile of sub-devices,

Helper.

> + * including their bound drivers, into an aggregate driver. Various subsystems
> + * already provide functions to get hold of such components, e.g.
> + * of_clk_get_by_name(). The component framework can be used when such a

helper

> + * subsystem-specific way to find a device is not available: The component
> + * framework fills the niche of aggregate drivers for specific hardware, where

helper

> + * further standardization into a subsystem would not be practical. The common
> + * example is when a logical device (e.g. a DRM display driver) is spread around
> + * the SoC on various component (scanout engines, blending blocks, transcoders
> + * for various outputs and so on).
> + *
> + * The component framework also doesn't solve runtime dependencies, e.g. for

helper

> + * system suspend and resume operations. See also :ref:`device
> + * links<device_link>`.
> + *
> + * Components are registered using component_add() and unregistered with
> + * component_del(), usually from the driver's probe and disconnect functions.
> + *
> + * Aggregate drivers first assemble a component match list of what they need
> + * using component_match_add(). This is then registered as an aggregate driver
> + * using component_master_add_with_match(), and unregistered using
> + * component_master_del().
> + */
> +
>  struct component;
>  
>  struct component_match_array {
> @@ -301,10 +328,24 @@ static int component_match_realloc(struct device *dev,
>  	return 0;
>  }
>  
> -/*
> - * Add a component to be matched, with a release function.
> +/**
> + * component_match_add_release - add a component match with release callback
> + * @master: device with the aggregate driver
> + * @matchptr: pointer to the list of component matches
> + * @release: release function for @compare_data
> + * @compare: compare function to match against all components
> + * @compare_data: opaque pointer passed to the @compare function
> + *
> + * This adds a new component match to the list stored in @matchptr, which the
> + * @master aggregate driver needs to function. @matchptr must be initialized to
> + * NULL before adding the first match.

The last sentence is confusing - it suggests that "matchptr" should
itself be null, rather than the pointer matchptr points at.  "The
list of component matches pointed to by @matchptr must be initialised
to NULL" would probably be better.  Same for component_match_add().

> + *
> + * The allocated match list in @matchptr is automatically released using devm
> + * actions. At that point @release will be called, to free any references held
> + * by @compare_data, e.g. when @compare_data is a &device_node that must be
> + * released with of_node_put().

"using devm actions, where upon @release will be called to free any
references held by @compare_data ..."

>   *
> - * The match array is first created or extended if necessary.
> + * See also component_match_add().
>   */
>  void component_match_add_release(struct device *master,
>  	struct component_match **matchptr,
> @@ -367,6 +408,18 @@ static void free_master(struct master *master)
>  	kfree(master);
>  }
>  
> +/**
> + * component_master_add_with_match - register an aggregate driver
> + * @dev: device with the aggregate driver
> + * @ops: callbacks for the aggregate driver
> + * @match: component match list for the aggregate driver
> + *
> + * Registers a new aggregate driver consisting of the components added to @match
> + * by calling one of the component_match_add() functions. Once all components in

As there is a function called component_match_add(), this doesn't
make too much sense as it directs people only to that function.  It
would be better to mention both here.  (Have you checked how it comes
out as a HTML document with the hyperlinks?)

> + * @match are available, it will be assembled by calling
> + * &component_master_ops.bind from @ops. Must be unregistered by calling
> + * component_master_del().
> + */
>  int component_master_add_with_match(struct device *dev,
>  	const struct component_master_ops *ops,
>  	struct component_match *match)
> @@ -403,6 +456,15 @@ int component_master_add_with_match(struct device *dev,
>  }
>  EXPORT_SYMBOL_GPL(component_master_add_with_match);
>  
> +/**
> + * component_master_del - unregister an aggregate driver
> + * @dev: device with the aggregate driver
> + * @ops: callbacks for the aggregate driver
> + *
> + * Unregisters an aggregate driver registered with
> + * component_master_add_with_match(). If necessary the aggregate driver is first
> + * disassembled by calling &component_master_ops.unbind from @ops.
> + */
>  void component_master_del(struct device *dev,
>  	const struct component_master_ops *ops)
>  {
> @@ -430,6 +492,15 @@ static void component_unbind(struct component *component,
>  	devres_release_group(component->dev, component);
>  }
>  
> +/**
> + * component_unbind_all - unbind all component to an aggregate driver
> + * @master_dev: device with the aggregate driver
> + * @data: opaque pointer, passed to all components
> + *
> + * Unbinds all components to the aggregate @dev by passing @data to their
> + * &component_ops.unbind functions. Should be called from
> + * &component_master_ops.unbind.
> + */
>  void component_unbind_all(struct device *master_dev, void *data)
>  {
>  	struct master *master;
> @@ -503,6 +574,15 @@ static int component_bind(struct component *component, struct master *master,
>  	return ret;
>  }
>  
> +/**
> + * component_bind_all - bind all component to an aggregate driver
> + * @master_dev: device with the aggregate driver
> + * @data: opaque pointer, passed to all components
> + *
> + * Binds all components to the aggregate @dev by passing @data to their
> + * &component_ops.bind functions. Should be called from
> + * &component_master_ops.bind.
> + */
>  int component_bind_all(struct device *master_dev, void *data)
>  {
>  	struct master *master;
> @@ -537,6 +617,18 @@ int component_bind_all(struct device *master_dev, void *data)
>  }
>  EXPORT_SYMBOL_GPL(component_bind_all);
>  
> +/**
> + * component_add - register a component
> + * @dev: component device
> + * @ops: component callbacks
> + *
> + * Register a new component for @dev. Functions in @ops will be called when the
> + * aggregate driver is ready to bind the overall driver by calling
> + * component_bind_all(). See also &struct component_ops.
> + *
> + * The component needs to be unregistered again at driver unload/disconnect by

"again" is unnecessary.

> + * calling component_del().
> + */
>  int component_add(struct device *dev, const struct component_ops *ops)
>  {
>  	struct component *component;
> @@ -568,6 +660,15 @@ int component_add(struct device *dev, const struct component_ops *ops)
>  }
>  EXPORT_SYMBOL_GPL(component_add);
>  
> +/**
> + * component_del - unregister a component
> + * @dev: component device
> + * @ops: component callbacks
> + *
> + * Unregister a component added with component_add(). If the component is bound
> + * into an aggregate driver, this will force the entire aggregate driver, including
> + * all its components, to be unbound.
> + */
>  void component_del(struct device *dev, const struct component_ops *ops)
>  {
>  	struct component *c, *component = NULL;
> diff --git a/include/linux/component.h b/include/linux/component.h
> index e71fbbbc74e2..b5a989e3871e 100644
> --- a/include/linux/component.h
> +++ b/include/linux/component.h
> @@ -4,11 +4,31 @@
>  
>  #include <linux/stddef.h>
>  
> +
>  struct device;
>  
> +/**
> + * struct component_ops - callbacks for component drivers
> + *
> + * Components are registered with component_add() and unregistered with
> + * component_del().
> + */
>  struct component_ops {
> +	/**
> +	 * @bind:
> +	 *
> +	 * Called through component_bind_all() when the aggregate driver is
> +	 * ready to bind the overall driver.
> +	 */
>  	int (*bind)(struct device *comp, struct device *master,
>  		    void *master_data);
> +	/**
> +	 * @unbind:
> +	 *
> +	 * Called through component_unbind_all() when the aggregate driver is
> +	 * ready to bind the overall driver, or when component_bind_all() fails
> +	 * part-ways through and needs to unbind some already bound components.
> +	 */
>  	void (*unbind)(struct device *comp, struct device *master,
>  		       void *master_data);
>  };
> @@ -21,8 +41,42 @@ void component_unbind_all(struct device *master, void *master_data);
>  
>  struct master;
>  
> +/**
> + * struct component_master_ops - callback for the aggregate driver
> + *
> + * Aggregate drivers are registered with component_master_add_with_match() and
> + * unregistered with component_master_del().
> + */
>  struct component_master_ops {
> +	/**
> +	 * @bind:
> +	 *
> +	 * Called when all components or the aggregate driver, as specified in
> +	 * the match list passed to component_master_add_with_match(), are
> +	 * ready. Usually there are 3 steps to bind an aggregate driver:
> +	 *
> +	 * 1. Allocate a structure for the aggregate driver.
> +	 *
> +	 * 2. Bind all components to the aggregate driver by calling
> +	 *    component_bind_all() with the aggregate driver structure as opaque
> +	 *    pointer data.

These two aren't part of the component helper specification, although
nailing down what is passed per subsystem would be a good idea to allow
components to be re-used within the subsystem.  For DRM, it should be
the struct drm_device.

> +	 *
> +	 * 3. Register the aggregate driver with the subsystem to publish its
> +	 *    interfaces.
> +	 *
> +	 * Note that the lifetime of the aggregate driver does not align with
> +	 * any of the underlying &struct device instances. Therefore devm cannot
> +	 * be used and all resources acquired or allocated in this callback must
> +	 * be explicitly released in the @unbind callback.
> +	 */
>  	int (*bind)(struct device *master);
> +	/**
> +	 * @unbind:
> +	 *
> +	 * Called when either the aggregate driver, using
> +	 * component_master_del(), or one of its components, using
> +	 * component_del(), is unregistered.
> +	 */
>  	void (*unbind)(struct device *master);
>  };
>  
> @@ -38,6 +92,22 @@ void component_match_add_release(struct device *master,
>  	void (*release)(struct device *, void *),
>  	int (*compare)(struct device *, void *), void *compare_data);
>  
> +/**
> + * component_match_add - add a compent match
> + * @master: device with the aggregate driver
> + * @matchptr: pointer to the list of component matches
> + * @compare: compare function to match against all components
> + * @compare_data: opaque pointer passed to the @compare function
> + *
> + * Adds a new component match to the list stored in @matchptr, which the
> + * @master aggregate driver needs to function. @matchptr must be initialized to
> + * NULL before adding the first match.
> + *
> + * The allocated match list in @matchptr is automatically released using devm
> + * actions.
> + *
> + * See also component_match_add_release().
> + */
>  static inline void component_match_add(struct device *master,
>  	struct component_match **matchptr,
>  	int (*compare)(struct device *, void *), void *compare_data)
> -- 
> 2.20.1
> 
> 

-- 
RMK's Patch system: https://www.armlinux.org.uk/developer/patches/
FTTC broadband for 0.8mile line in suburbia: sync at 12.1Mbps down 622kbps up
According to speedtest.net: 11.9Mbps down 500kbps up

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

* Re: [PATCH] component: Add documentation
  2019-02-05 16:49       ` Russell King - ARM Linux admin
@ 2019-02-05 18:45         ` Daniel Vetter
  0 siblings, 0 replies; 121+ messages in thread
From: Daniel Vetter @ 2019-02-05 18:45 UTC (permalink / raw)
  To: Russell King - ARM Linux admin
  Cc: Daniel Vetter, DRI Development, LKML, C, Ramalingam,
	Greg Kroah-Hartman, Rafael J . Wysocki, Jaroslav Kysela,
	Takashi Iwai, Rodrigo Vivi, Jani Nikula, Daniel Vetter

On Tue, Feb 05, 2019 at 04:49:02PM +0000, Russell King - ARM Linux admin wrote:
> On Tue, Feb 05, 2019 at 05:21:07PM +0100, Daniel Vetter wrote:
> > Someone owes me a beer ...
> 
> I find that deeply offensive - it is clearly directed at me personally
> as author of the component helper.
> 
> There are double-standards in the kernel ecosystem with respect to
> documentation - there are entire subsystems way more complicated than
> the component *helper* which are lacking in documentation, and the
> subsystem authors response to requests to change that basically get
> ignored, or the response is "write the documentation yourself".
> 
> Why does there seem to be one rule for me and one rule for everyone
> else?
> 
> Please remove this line.

Will do, but wasn't aimed at you at all, but at Greg for asking for the
documentation. But yeah that wasn't clear at all, my apologies.

Will apply all your suggestions except for the ones I'm commenting on here
in my reply.

[snip]

> > +/**
> > + * component_master_add_with_match - register an aggregate driver
> > + * @dev: device with the aggregate driver
> > + * @ops: callbacks for the aggregate driver
> > + * @match: component match list for the aggregate driver
> > + *
> > + * Registers a new aggregate driver consisting of the components added to @match
> > + * by calling one of the component_match_add() functions. Once all components in
> 
> As there is a function called component_match_add(), this doesn't
> make too much sense as it directs people only to that function.  It
> would be better to mention both here.  (Have you checked how it comes
> out as a HTML document with the hyperlinks?)

component_match_add() creates a link to the kerneldoc for the
component_match_add. There I've added some text to point to all the other
variants of this family of functions. Same for all the other variants,
those should all have links to the others.


[snip]

> > +/**
> > + * struct component_master_ops - callback for the aggregate driver
> > + *
> > + * Aggregate drivers are registered with component_master_add_with_match() and
> > + * unregistered with component_master_del().
> > + */
> >  struct component_master_ops {
> > +	/**
> > +	 * @bind:
> > +	 *
> > +	 * Called when all components or the aggregate driver, as specified in
> > +	 * the match list passed to component_master_add_with_match(), are
> > +	 * ready. Usually there are 3 steps to bind an aggregate driver:
> > +	 *
> > +	 * 1. Allocate a structure for the aggregate driver.
> > +	 *
> > +	 * 2. Bind all components to the aggregate driver by calling
> > +	 *    component_bind_all() with the aggregate driver structure as opaque
> > +	 *    pointer data.
> 
> These two aren't part of the component helper specification, although
> nailing down what is passed per subsystem would be a good idea to allow
> components to be re-used within the subsystem.  For DRM, it should be
> the struct drm_device.

Hm, great point. I have no idea where we should put it so people find
this. Definitely not here, since this isn't drivers/gpu. I think adding a
small section to the driver initialization docs we already have would make
sense.

I'll add another patch for that in this series, with this one here that
drm paragraph will even have somewhere meaningful to point to!

Thanks for your review.

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

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

* Re: [PATCH v10 26/40] misc/mei/hdcp: Verify Receiver Cert and prepare km
  2019-02-04 16:10   ` Shankar, Uma
@ 2019-02-06  8:28     ` Winkler, Tomas
  0 siblings, 0 replies; 121+ messages in thread
From: Winkler, Tomas @ 2019-02-06  8:28 UTC (permalink / raw)
  To: C, Ramalingam, intel-gfx, dri-devel, daniel.vetter

>
> >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>
> 
> Latest set look ok. You can keep the RB.
> 
> >---
> > 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 534d29c8ee86..24665fff640d 100644
> >--- a/drivers/misc/mei/hdcp/mei_hdcp.c
> >+++ b/drivers/misc/mei/hdcp/mei_hdcp.c
> >@@ -90,11 +90,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,


mei_hdcp_ - prefix 

> >+				    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	[flat|nested] 121+ messages in thread

* RE: [PATCH v10 25/40] misc/mei/hdcp: Initiate Wired HDCP2.2 Tx Session
  2019-02-05 13:09     ` Winkler, Tomas
  2019-02-05 14:13       ` C, Ramalingam
@ 2019-02-06 10:27       ` Winkler, Tomas
  2019-02-06 21:14         ` C, Ramalingam
  1 sibling, 1 reply; 121+ messages in thread
From: Winkler, Tomas @ 2019-02-06 10:27 UTC (permalink / raw)
  To: C, Ramalingam, 'intel-gfx@lists.freedesktop.org',
	'dri-devel@lists.freedesktop.org',
	'daniel.vetter@ffwll.ch'
  Cc: Shankar, Uma

> 
> > >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>
> >
> > Latest set look ok. You can keep the RB.
> >
> > >---
> > > drivers/misc/mei/hdcp/mei_hdcp.c | 82
> > >++++++++++++++++++++++++++++++++++++++++
> > > drivers/misc/mei/hdcp/mei_hdcp.h | 28 ++++++++++++++
> > > 2 files changed, 110 insertions(+)
> > >
> > >diff --git a/drivers/misc/mei/hdcp/mei_hdcp.c
> > >b/drivers/misc/mei/hdcp/mei_hdcp.c
> > >index ca5010ad7dd7..534d29c8ee86 100644
> > >--- a/drivers/misc/mei/hdcp/mei_hdcp.c
> > >+++ b/drivers/misc/mei/hdcp/mei_hdcp.c
> > >@@ -23,6 +23,88 @@
> > > #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 <drm/i915_mei_hdcp_interface.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) {
> 
> 
> Breaking naming conventions : all functions should be prefixed with mei_hdcp_
> 
> e.g. mei_hdcp_ initiate_session()
> 
> > >+	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 582a7e27ae29..f831db3cbd54 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 {
> We've already reviewed. Move to i915 header or use mei_ prefix?
> > >+	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__ */
I wonder why we are casting it to another enum here and they you consistently  casting it to u8 back when assigned.


mei_hdcp.c:     session_init_in.port.physical_port = (u8)GET_MEI_DDI_INDEX(data->port);
mei_hdcp.c:     verify_rxcert_in.port.physical_port = (u8)GET_MEI_DDI_INDEX(data->port);
mei_hdcp.c:     send_hprime_in.port.physical_port = (u8)GET_MEI_DDI_INDEX(data->port);
mei_hdcp.c:     pairing_info_in.port.physical_port = (u8)GET_MEI_DDI_INDEX(data->port);
mei_hdcp.c:     lc_init_in.port.physical_port = (u8)GET_MEI_DDI_INDEX(data->port);
mei_hdcp.c:     verify_lprime_in.port.physical_port = (u8)GET_MEI_DDI_INDEX(data->port);
mei_hdcp.c:     get_skey_in.port.physical_port = (u8)GET_MEI_DDI_INDEX(data->port);
mei_hdcp.c:     verify_mprime_in.port.physical_port = (u8)GET_MEI_DDI_INDEX(data->port);
mei_hdcp.c:     enable_auth_in.port.physical_port = (u8)GET_MEI_DDI_INDEX(data->port);
mei_hdcp.c:     session_close_in.port.physical_port = (u8)GET_MEI_DDI_INDEX(data->port);


This macro is only used in mei_hdcp.c so I would just make an inline function of it and push it to the c file.
Thanks
Tomas

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

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

* [PATCH 1/3] component: Add documentation
  2019-01-31  6:59 ` [PATCH v10 01/40] components: multiple components for a device Ramalingam C
  2019-01-31  7:50   ` Greg Kroah-Hartman
  2019-01-31 14:46   ` [PATCH 1/2] component: Add documentation Daniel Vetter
@ 2019-02-06 16:45   ` Daniel Vetter
  2019-02-06 16:45     ` [PATCH 2/3] components: multiple components for a device Daniel Vetter
                       ` (2 more replies)
  2 siblings, 3 replies; 121+ messages in thread
From: Daniel Vetter @ 2019-02-06 16:45 UTC (permalink / raw)
  To: DRI Development
  Cc: Rafael J . Wysocki, Daniel Vetter, Daniel Vetter,
	Intel Graphics Development, Takashi Iwai, Jaroslav Kysela,
	Greg Kroah-Hartman, Russell King

Someone owes me a beer ...

While typing these I think doing an s/component_master/aggregate/
would be useful:
- it's shorter :-)
- I think component/aggregate is much more meaningful naming than
  component/puppetmaster or something like that. At least to my
  English ear "aggregate" emphasizes much more the "assemble a pile of
  things into something bigger" aspect, and there's not really much
  of a control hierarchy between aggregate and constituing components.

But that's way more than a quick doc typing exercise ...

Thanks to Ram for commenting on an initial draft of these docs.

v2: Review from Rafael:
- git add Documenation/driver-api/component.rst
- lots of polish to the wording + spelling fixes.

v3: Review from Russell:
- s/framework/helper
- clarify the documentation for component_match_add functions.

Cc: "C, Ramalingam" <ramalingam.c@intel.com>
Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Cc: Russell King <rmk+kernel@arm.linux.org.uk>
Cc: Rafael J. Wysocki <rafael@kernel.org>
Cc: Jaroslav Kysela <perex@perex.cz>
Cc: Takashi Iwai <tiwai@suse.com>
Cc: Rodrigo Vivi <rodrigo.vivi@intel.com>
Cc: Jani Nikula <jani.nikula@linux.intel.com>
Signed-off-by: Daniel Vetter <daniel.vetter@intel.com>
---
 Documentation/driver-api/component.rst   |  17 ++++
 Documentation/driver-api/device_link.rst |   3 +
 Documentation/driver-api/index.rst       |   1 +
 drivers/base/component.c                 | 107 ++++++++++++++++++++++-
 include/linux/component.h                |  71 +++++++++++++++
 5 files changed, 196 insertions(+), 3 deletions(-)
 create mode 100644 Documentation/driver-api/component.rst

diff --git a/Documentation/driver-api/component.rst b/Documentation/driver-api/component.rst
new file mode 100644
index 000000000000..2da4a8f20607
--- /dev/null
+++ b/Documentation/driver-api/component.rst
@@ -0,0 +1,17 @@
+======================================
+Component Helper for Aggregate Drivers
+======================================
+
+.. kernel-doc:: drivers/base/component.c
+   :doc: overview
+
+
+API
+===
+
+.. kernel-doc:: include/linux/component.h
+   :internal:
+
+.. kernel-doc:: drivers/base/component.c
+   :export:
+
diff --git a/Documentation/driver-api/device_link.rst b/Documentation/driver-api/device_link.rst
index d6763272e747..2d5919b2b337 100644
--- a/Documentation/driver-api/device_link.rst
+++ b/Documentation/driver-api/device_link.rst
@@ -1,6 +1,9 @@
 .. |struct dev_pm_domain| replace:: :c:type:`struct dev_pm_domain <dev_pm_domain>`
 .. |struct generic_pm_domain| replace:: :c:type:`struct generic_pm_domain <generic_pm_domain>`
 
+
+.. _device_link:
+
 ============
 Device links
 ============
diff --git a/Documentation/driver-api/index.rst b/Documentation/driver-api/index.rst
index ab38ced66a44..c0b600ed9961 100644
--- a/Documentation/driver-api/index.rst
+++ b/Documentation/driver-api/index.rst
@@ -22,6 +22,7 @@ available subsections can be seen below.
    device_connection
    dma-buf
    device_link
+   component
    message-based
    sound
    frame-buffer
diff --git a/drivers/base/component.c b/drivers/base/component.c
index ddcea8739c12..f34d4b784709 100644
--- a/drivers/base/component.c
+++ b/drivers/base/component.c
@@ -16,6 +16,32 @@
 #include <linux/slab.h>
 #include <linux/debugfs.h>
 
+/**
+ * DOC: overview
+ *
+ * The component helper allows drivers to collect a pile of sub-devices,
+ * including their bound drivers, into an aggregate driver. Various subsystems
+ * already provide functions to get hold of such components, e.g.
+ * of_clk_get_by_name(). The component helper can be used when such a
+ * subsystem-specific way to find a device is not available: The component
+ * helper fills the niche of aggregate drivers for specific hardware, where
+ * further standardization into a subsystem would not be practical. The common
+ * example is when a logical device (e.g. a DRM display driver) is spread around
+ * the SoC on various component (scanout engines, blending blocks, transcoders
+ * for various outputs and so on).
+ *
+ * The component helper also doesn't solve runtime dependencies, e.g. for system
+ * suspend and resume operations. See also :ref:`device links<device_link>`.
+ *
+ * Components are registered using component_add() and unregistered with
+ * component_del(), usually from the driver's probe and disconnect functions.
+ *
+ * Aggregate drivers first assemble a component match list of what they need
+ * using component_match_add(). This is then registered as an aggregate driver
+ * using component_master_add_with_match(), and unregistered using
+ * component_master_del().
+ */
+
 struct component;
 
 struct component_match_array {
@@ -301,10 +327,25 @@ static int component_match_realloc(struct device *dev,
 	return 0;
 }
 
-/*
- * Add a component to be matched, with a release function.
+/**
+ * component_match_add_release - add a component match with release callback
+ * @master: device with the aggregate driver
+ * @matchptr: pointer to the list of component matches
+ * @release: release function for @compare_data
+ * @compare: compare function to match against all components
+ * @compare_data: opaque pointer passed to the @compare function
+ *
+ * This adds a new component match to the list stored in @matchptr, which the
+ * @master aggregate driver needs to function. The list of component matches
+ * pointed to by @matchptr must be initialized to NULL before adding the first
+ * match.
+ *
+ * The allocated match list in @matchptr is automatically released using devm
+ * actions, where upon @release will be called to free any references held by
+ * @compare_data, e.g. when @compare_data is a &device_node that must be
+ * released with of_node_put().
  *
- * The match array is first created or extended if necessary.
+ * See also component_match_add().
  */
 void component_match_add_release(struct device *master,
 	struct component_match **matchptr,
@@ -367,6 +408,18 @@ static void free_master(struct master *master)
 	kfree(master);
 }
 
+/**
+ * component_master_add_with_match - register an aggregate driver
+ * @dev: device with the aggregate driver
+ * @ops: callbacks for the aggregate driver
+ * @match: component match list for the aggregate driver
+ *
+ * Registers a new aggregate driver consisting of the components added to @match
+ * by calling one of the component_match_add() functions. Once all components in
+ * @match are available, it will be assembled by calling
+ * &component_master_ops.bind from @ops. Must be unregistered by calling
+ * component_master_del().
+ */
 int component_master_add_with_match(struct device *dev,
 	const struct component_master_ops *ops,
 	struct component_match *match)
@@ -403,6 +456,15 @@ int component_master_add_with_match(struct device *dev,
 }
 EXPORT_SYMBOL_GPL(component_master_add_with_match);
 
+/**
+ * component_master_del - unregister an aggregate driver
+ * @dev: device with the aggregate driver
+ * @ops: callbacks for the aggregate driver
+ *
+ * Unregisters an aggregate driver registered with
+ * component_master_add_with_match(). If necessary the aggregate driver is first
+ * disassembled by calling &component_master_ops.unbind from @ops.
+ */
 void component_master_del(struct device *dev,
 	const struct component_master_ops *ops)
 {
@@ -430,6 +492,15 @@ static void component_unbind(struct component *component,
 	devres_release_group(component->dev, component);
 }
 
+/**
+ * component_unbind_all - unbind all component to an aggregate driver
+ * @master_dev: device with the aggregate driver
+ * @data: opaque pointer, passed to all components
+ *
+ * Unbinds all components to the aggregate @dev by passing @data to their
+ * &component_ops.unbind functions. Should be called from
+ * &component_master_ops.unbind.
+ */
 void component_unbind_all(struct device *master_dev, void *data)
 {
 	struct master *master;
@@ -503,6 +574,15 @@ static int component_bind(struct component *component, struct master *master,
 	return ret;
 }
 
+/**
+ * component_bind_all - bind all component to an aggregate driver
+ * @master_dev: device with the aggregate driver
+ * @data: opaque pointer, passed to all components
+ *
+ * Binds all components to the aggregate @dev by passing @data to their
+ * &component_ops.bind functions. Should be called from
+ * &component_master_ops.bind.
+ */
 int component_bind_all(struct device *master_dev, void *data)
 {
 	struct master *master;
@@ -537,6 +617,18 @@ int component_bind_all(struct device *master_dev, void *data)
 }
 EXPORT_SYMBOL_GPL(component_bind_all);
 
+/**
+ * component_add - register a component
+ * @dev: component device
+ * @ops: component callbacks
+ *
+ * Register a new component for @dev. Functions in @ops will be called when the
+ * aggregate driver is ready to bind the overall driver by calling
+ * component_bind_all(). See also &struct component_ops.
+ *
+ * The component needs to be unregistered at driver unload/disconnect by calling
+ * component_del().
+ */
 int component_add(struct device *dev, const struct component_ops *ops)
 {
 	struct component *component;
@@ -568,6 +660,15 @@ int component_add(struct device *dev, const struct component_ops *ops)
 }
 EXPORT_SYMBOL_GPL(component_add);
 
+/**
+ * component_del - unregister a component
+ * @dev: component device
+ * @ops: component callbacks
+ *
+ * Unregister a component added with component_add(). If the component is bound
+ * into an aggregate driver, this will force the entire aggregate driver, including
+ * all its components, to be unbound.
+ */
 void component_del(struct device *dev, const struct component_ops *ops)
 {
 	struct component *c, *component = NULL;
diff --git a/include/linux/component.h b/include/linux/component.h
index e71fbbbc74e2..4911598b4c42 100644
--- a/include/linux/component.h
+++ b/include/linux/component.h
@@ -4,11 +4,31 @@
 
 #include <linux/stddef.h>
 
+
 struct device;
 
+/**
+ * struct component_ops - callbacks for component drivers
+ *
+ * Components are registered with component_add() and unregistered with
+ * component_del().
+ */
 struct component_ops {
+	/**
+	 * @bind:
+	 *
+	 * Called through component_bind_all() when the aggregate driver is
+	 * ready to bind the overall driver.
+	 */
 	int (*bind)(struct device *comp, struct device *master,
 		    void *master_data);
+	/**
+	 * @unbind:
+	 *
+	 * Called through component_unbind_all() when the aggregate driver is
+	 * ready to bind the overall driver, or when component_bind_all() fails
+	 * part-ways through and needs to unbind some already bound components.
+	 */
 	void (*unbind)(struct device *comp, struct device *master,
 		       void *master_data);
 };
@@ -21,8 +41,42 @@ void component_unbind_all(struct device *master, void *master_data);
 
 struct master;
 
+/**
+ * struct component_master_ops - callback for the aggregate driver
+ *
+ * Aggregate drivers are registered with component_master_add_with_match() and
+ * unregistered with component_master_del().
+ */
 struct component_master_ops {
+	/**
+	 * @bind:
+	 *
+	 * Called when all components or the aggregate driver, as specified in
+	 * the match list passed to component_master_add_with_match(), are
+	 * ready. Usually there are 3 steps to bind an aggregate driver:
+	 *
+	 * 1. Allocate a structure for the aggregate driver.
+	 *
+	 * 2. Bind all components to the aggregate driver by calling
+	 *    component_bind_all() with the aggregate driver structure as opaque
+	 *    pointer data.
+	 *
+	 * 3. Register the aggregate driver with the subsystem to publish its
+	 *    interfaces.
+	 *
+	 * Note that the lifetime of the aggregate driver does not align with
+	 * any of the underlying &struct device instances. Therefore devm cannot
+	 * be used and all resources acquired or allocated in this callback must
+	 * be explicitly released in the @unbind callback.
+	 */
 	int (*bind)(struct device *master);
+	/**
+	 * @unbind:
+	 *
+	 * Called when either the aggregate driver, using
+	 * component_master_del(), or one of its components, using
+	 * component_del(), is unregistered.
+	 */
 	void (*unbind)(struct device *master);
 };
 
@@ -38,6 +92,23 @@ void component_match_add_release(struct device *master,
 	void (*release)(struct device *, void *),
 	int (*compare)(struct device *, void *), void *compare_data);
 
+/**
+ * component_match_add - add a compent match
+ * @master: device with the aggregate driver
+ * @matchptr: pointer to the list of component matches
+ * @compare: compare function to match against all components
+ * @compare_data: opaque pointer passed to the @compare function
+ *
+ * This adds a new component match to the list stored in @matchptr, which the
+ * @master aggregate driver needs to function. The list of component matches
+ * pointed to by @matchptr must be initialized to NULL before adding the first
+ * match.
+ *
+ * The allocated match list in @matchptr is automatically released using devm
+ * actions.
+ *
+ * See also component_match_add_release().
+ */
 static inline void component_match_add(struct device *master,
 	struct component_match **matchptr,
 	int (*compare)(struct device *, void *), void *compare_data)
-- 
2.20.1

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

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

* [PATCH 2/3] components: multiple components for a device
  2019-02-06 16:45   ` [PATCH 1/3] " Daniel Vetter
@ 2019-02-06 16:45     ` Daniel Vetter
  2019-02-06 22:57       ` Rafael J. Wysocki
  2019-02-06 16:45     ` [PATCH 3/3] drm/doc: document recommended component helper usage Daniel Vetter
  2019-02-06 16:47       ` Daniel Vetter
  2 siblings, 1 reply; 121+ messages in thread
From: Daniel Vetter @ 2019-02-06 16:45 UTC (permalink / raw)
  To: DRI Development
  Cc: Rafael J . Wysocki, Daniel Vetter, Intel Graphics Development,
	Rodrigo Vivi, Takashi Iwai, Jaroslav Kysela, Greg Kroah-Hartman,
	Russell King

Component framework is extended to support multiple components for
a struct device. These will be matched with different masters based on
its sub component value.

We are introducing this, as I915 needs two different components
with different subcomponent value, which will be matched to two
different component masters(Audio and HDCP) based on the subcomponent
values.

v2: Add documenation.

v3: Rebase on top of updated documenation.

Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch> (v1 code)
Signed-off-by: Ramalingam C <ramalingam.c@intel.com> (v1 commit message)
Cc: Ramalingam C <ramalingam.c@intel.com>
Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Cc: Russell King <rmk+kernel@arm.linux.org.uk>
Cc: Rafael J. Wysocki <rafael@kernel.org>
Cc: Jaroslav Kysela <perex@perex.cz>
Cc: Takashi Iwai <tiwai@suse.com>
Cc: Rodrigo Vivi <rodrigo.vivi@intel.com>
Cc: Jani Nikula <jani.nikula@linux.intel.com>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
---
 drivers/base/component.c  | 160 +++++++++++++++++++++++++++++---------
 include/linux/component.h |   9 ++-
 2 files changed, 129 insertions(+), 40 deletions(-)

diff --git a/drivers/base/component.c b/drivers/base/component.c
index f34d4b784709..68ccd5a0d5d6 100644
--- a/drivers/base/component.c
+++ b/drivers/base/component.c
@@ -47,6 +47,7 @@ struct component;
 struct component_match_array {
 	void *data;
 	int (*compare)(struct device *, void *);
+	int (*compare_typed)(struct device *, int, void *);
 	void (*release)(struct device *, void *);
 	struct component *component;
 	bool duplicate;
@@ -74,6 +75,7 @@ struct component {
 	bool bound;
 
 	const struct component_ops *ops;
+	int subcomponent;
 	struct device *dev;
 };
 
@@ -158,7 +160,7 @@ static struct master *__master_find(struct device *dev,
 }
 
 static struct component *find_component(struct master *master,
-	int (*compare)(struct device *, void *), void *compare_data)
+	struct component_match_array *mc)
 {
 	struct component *c;
 
@@ -166,8 +168,13 @@ static struct component *find_component(struct master *master,
 		if (c->master && c->master != master)
 			continue;
 
-		if (compare(c->dev, compare_data))
+		if (mc->compare_typed) {
+			if (mc->compare_typed(c->dev, c->subcomponent,
+					      mc->data))
+				return c;
+		} else if (mc->compare(c->dev, mc->data)) {
 			return c;
+		}
 	}
 
 	return NULL;
@@ -192,7 +199,7 @@ static int find_components(struct master *master)
 		if (match->compare[i].component)
 			continue;
 
-		c = find_component(master, mc->compare, mc->data);
+		c = find_component(master, mc);
 		if (!c) {
 			ret = -ENXIO;
 			break;
@@ -327,30 +334,12 @@ static int component_match_realloc(struct device *dev,
 	return 0;
 }
 
-/**
- * component_match_add_release - add a component match with release callback
- * @master: device with the aggregate driver
- * @matchptr: pointer to the list of component matches
- * @release: release function for @compare_data
- * @compare: compare function to match against all components
- * @compare_data: opaque pointer passed to the @compare function
- *
- * This adds a new component match to the list stored in @matchptr, which the
- * @master aggregate driver needs to function. The list of component matches
- * pointed to by @matchptr must be initialized to NULL before adding the first
- * match.
- *
- * The allocated match list in @matchptr is automatically released using devm
- * actions, where upon @release will be called to free any references held by
- * @compare_data, e.g. when @compare_data is a &device_node that must be
- * released with of_node_put().
- *
- * See also component_match_add().
- */
-void component_match_add_release(struct device *master,
+static void __component_match_add(struct device *master,
 	struct component_match **matchptr,
 	void (*release)(struct device *, void *),
-	int (*compare)(struct device *, void *), void *compare_data)
+	int (*compare)(struct device *, void *),
+	int (*compare_typed)(struct device *, int, void *),
+	void *compare_data)
 {
 	struct component_match *match = *matchptr;
 
@@ -382,13 +371,69 @@ void component_match_add_release(struct device *master,
 	}
 
 	match->compare[match->num].compare = compare;
+	match->compare[match->num].compare_typed = compare_typed;
 	match->compare[match->num].release = release;
 	match->compare[match->num].data = compare_data;
 	match->compare[match->num].component = NULL;
 	match->num++;
 }
+
+/**
+ * component_match_add_release - add a component match with release callback
+ * @master: device with the aggregate driver
+ * @matchptr: pointer to the list of component matches
+ * @release: release function for @compare_data
+ * @compare: compare function to match against all components
+ * @compare_data: opaque pointer passed to the @compare function
+ *
+ * This adds a new component match to the list stored in @matchptr, which the
+ * @master aggregate driver needs to function. The list of component matches
+ * pointed to by @matchptr must be initialized to NULL before adding the first
+ * match. This only matches against components added with component_add().
+ *
+ * The allocated match list in @matchptr is automatically released using devm
+ * actions, where upon @release will be called to free any references held by
+ * @compare_data, e.g. when @compare_data is a &device_node that must be
+ * released with of_node_put().
+ *
+ * See also component_match_add() and component_match_add_typed().
+ */
+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)
+{
+	__component_match_add(master, matchptr, release, compare, NULL,
+			      compare_data);
+}
 EXPORT_SYMBOL(component_match_add_release);
 
+/**
+ * component_match_add_typed - add a compent match for a typed component
+ * @master: device with the aggregate driver
+ * @matchptr: pointer to the list of component matches
+ * @compare_typed: compare function to match against all typed components
+ * @compare_data: opaque pointer passed to the @compare function
+ *
+ * This adds a new component match to the list stored in @matchptr, which the
+ * @master aggregate driver needs to function. The list of component matches
+ * pointed to by @matchptr must be initialized to NULL before adding the first
+ * match. This only matches against components added with component_add_typed().
+ *
+ * The allocated match list in @matchptr is automatically released using devm
+ * actions.
+ *
+ * See also component_match_add_release() and component_match_add_typed().
+ */
+void component_match_add_typed(struct device *master,
+	struct component_match **matchptr,
+	int (*compare_typed)(struct device *, int, void *), void *compare_data)
+{
+	__component_match_add(master, matchptr, NULL, NULL, compare_typed,
+			      compare_data);
+}
+EXPORT_SYMBOL(component_match_add_typed);
+
 static void free_master(struct master *master)
 {
 	struct component_match *match = master->match;
@@ -617,19 +662,8 @@ int component_bind_all(struct device *master_dev, void *data)
 }
 EXPORT_SYMBOL_GPL(component_bind_all);
 
-/**
- * component_add - register a component
- * @dev: component device
- * @ops: component callbacks
- *
- * Register a new component for @dev. Functions in @ops will be called when the
- * aggregate driver is ready to bind the overall driver by calling
- * component_bind_all(). See also &struct component_ops.
- *
- * The component needs to be unregistered at driver unload/disconnect by calling
- * component_del().
- */
-int component_add(struct device *dev, const struct component_ops *ops)
+static int __component_add(struct device *dev, const struct component_ops *ops,
+	int subcomponent)
 {
 	struct component *component;
 	int ret;
@@ -640,6 +674,7 @@ int component_add(struct device *dev, const struct component_ops *ops)
 
 	component->ops = ops;
 	component->dev = dev;
+	component->subcomponent = subcomponent;
 
 	dev_dbg(dev, "adding component (ops %ps)\n", ops);
 
@@ -658,6 +693,55 @@ int component_add(struct device *dev, const struct component_ops *ops)
 
 	return ret < 0 ? ret : 0;
 }
+
+/**
+ * component_add_typed - register a component
+ * @dev: component device
+ * @ops: component callbacks
+ * @subcomponent: nonzero identifier for subcomponents
+ *
+ * Register a new component for @dev. Functions in @ops will be call when the
+ * aggregate driver is ready to bind the overall driver by calling
+ * component_bind_all(). See also &struct component_ops.
+ *
+ * @subcomponent must be nonzero and is used to differentiate between multiple
+ * components registerd on the same device @dev. These components are match
+ * using component_match_add_typed().
+ *
+ * The component needs to be unregistered at driver unload/disconnect by
+ * calling component_del().
+ *
+ * See also component_add().
+ */
+int component_add_typed(struct device *dev, const struct component_ops *ops,
+	int subcomponent)
+{
+	if (WARN_ON(subcomponent == 0))
+		return -EINVAL;
+
+	return __component_add(dev, ops, subcomponent);
+}
+EXPORT_SYMBOL_GPL(component_add_typed);
+
+/**
+ * component_add - register a component
+ * @dev: component device
+ * @ops: component callbacks
+ *
+ * Register a new component for @dev. Functions in @ops will be called when the
+ * aggregate driver is ready to bind the overall driver by calling
+ * component_bind_all(). See also &struct component_ops.
+ *
+ * The component needs to be unregistered at driver unload/disconnect by
+ * calling component_del().
+ *
+ * See also component_add_typed() for a variant that allows multipled different
+ * components on the same device.
+ */
+int component_add(struct device *dev, const struct component_ops *ops)
+{
+	return __component_add(dev, ops, 0);
+}
 EXPORT_SYMBOL_GPL(component_add);
 
 /**
diff --git a/include/linux/component.h b/include/linux/component.h
index 4911598b4c42..9d155d91889d 100644
--- a/include/linux/component.h
+++ b/include/linux/component.h
@@ -34,6 +34,8 @@ struct component_ops {
 };
 
 int component_add(struct device *, const struct component_ops *);
+int component_add_typed(struct device *dev, const struct component_ops *ops,
+	int subcomponent);
 void component_del(struct device *, const struct component_ops *);
 
 int component_bind_all(struct device *master, void *master_data);
@@ -91,6 +93,9 @@ 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_add_typed(struct device *master,
+	struct component_match **matchptr,
+	int (*compare_typed)(struct device *, int, void *), void *compare_data);
 
 /**
  * component_match_add - add a compent match
@@ -102,12 +107,12 @@ void component_match_add_release(struct device *master,
  * This adds a new component match to the list stored in @matchptr, which the
  * @master aggregate driver needs to function. The list of component matches
  * pointed to by @matchptr must be initialized to NULL before adding the first
- * match.
+ * match. This only matches against components added with component_add().
  *
  * The allocated match list in @matchptr is automatically released using devm
  * actions.
  *
- * See also component_match_add_release().
+ * See also component_match_add_release() and component_match_add_typed().
  */
 static inline void component_match_add(struct device *master,
 	struct component_match **matchptr,
-- 
2.20.1

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

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

* [PATCH 3/3] drm/doc: document recommended component helper usage
  2019-02-06 16:45   ` [PATCH 1/3] " Daniel Vetter
  2019-02-06 16:45     ` [PATCH 2/3] components: multiple components for a device Daniel Vetter
@ 2019-02-06 16:45     ` Daniel Vetter
  2019-02-06 16:47       ` Daniel Vetter
  2 siblings, 0 replies; 121+ messages in thread
From: Daniel Vetter @ 2019-02-06 16:45 UTC (permalink / raw)
  To: DRI Development
  Cc: Daniel Vetter, Intel Graphics Development,
	Russell King - ARM Linux admin, Daniel Vetter

Now that component has docs it's worth spending a few words and
hyperlinks on recommended best practices in drm.

Cc: Russell King - ARM Linux admin <linux@armlinux.org.uk>
Signed-off-by: Daniel Vetter <daniel.vetter@intel.com>
---
 Documentation/driver-api/component.rst |  2 ++
 Documentation/gpu/drm-internals.rst    |  5 +++++
 drivers/gpu/drm/drm_drv.c              | 14 ++++++++++++++
 3 files changed, 21 insertions(+)

diff --git a/Documentation/driver-api/component.rst b/Documentation/driver-api/component.rst
index 2da4a8f20607..57e37590733f 100644
--- a/Documentation/driver-api/component.rst
+++ b/Documentation/driver-api/component.rst
@@ -1,3 +1,5 @@
+.. _component:
+
 ======================================
 Component Helper for Aggregate Drivers
 ======================================
diff --git a/Documentation/gpu/drm-internals.rst b/Documentation/gpu/drm-internals.rst
index 3ae23a5454ac..966bd2d9f0cc 100644
--- a/Documentation/gpu/drm-internals.rst
+++ b/Documentation/gpu/drm-internals.rst
@@ -93,6 +93,11 @@ Device Instance and Driver Handling
 Driver Load
 -----------
 
+Component Helper Usage
+~~~~~~~~~~~~~~~~~~~~~~
+
+.. kernel-doc:: drivers/gpu/drm/drm_drv.c
+   :doc: component helper usage recommendations
 
 IRQ Helper Library
 ~~~~~~~~~~~~~~~~~~
diff --git a/drivers/gpu/drm/drm_drv.c b/drivers/gpu/drm/drm_drv.c
index 381581b01d48..aae413003705 100644
--- a/drivers/gpu/drm/drm_drv.c
+++ b/drivers/gpu/drm/drm_drv.c
@@ -456,6 +456,20 @@ static void drm_fs_inode_free(struct inode *inode)
 	}
 }
 
+/**
+ * DOC: component helper usage recommendations
+ *
+ * DRM drivers that drive hardware where a logical device consists of a pile of
+ * independent hardware blocks are recommended to use the :ref:`component helper
+ * library<component>`. The entire device initialization procedure should be run
+ * from the &component_master_ops.master_bind callback, starting with
+ * drm_dev_init(), then binding all components with component_bind_all() and
+ * finishing with drm_dev_register(). For consistency and easier sharing of
+ * components across drivers the opaque pointer passed to all components through
+ * component_bind_all() should point at &struct drm_device of the device
+ * instance, not some driver specific private structure.
+ */
+
 /**
  * drm_dev_init - Initialise new DRM device
  * @dev: DRM device
-- 
2.20.1

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

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

* [PATCH] component: Add documentation
  2019-02-06 16:45   ` [PATCH 1/3] " Daniel Vetter
@ 2019-02-06 16:47       ` Daniel Vetter
  2019-02-06 16:45     ` [PATCH 3/3] drm/doc: document recommended component helper usage Daniel Vetter
  2019-02-06 16:47       ` Daniel Vetter
  2 siblings, 0 replies; 121+ messages in thread
From: Daniel Vetter @ 2019-02-06 16:47 UTC (permalink / raw)
  To: DRI Development
  Cc: LKML, Daniel Vetter, C, Ramalingam, Greg Kroah-Hartman,
	Russell King, Rafael J . Wysocki, Jaroslav Kysela, Takashi Iwai,
	Rodrigo Vivi, Jani Nikula, Daniel Vetter

While typing these I think doing an s/component_master/aggregate/
would be useful:
- it's shorter :-)
- I think component/aggregate is much more meaningful naming than
  component/puppetmaster or something like that. At least to my
  English ear "aggregate" emphasizes much more the "assemble a pile of
  things into something bigger" aspect, and there's not really much
  of a control hierarchy between aggregate and constituing components.

But that's way more than a quick doc typing exercise ...

Thanks to Ram for commenting on an initial draft of these docs.

v2: Review from Rafael:
- git add Documenation/driver-api/component.rst
- lots of polish to the wording + spelling fixes.

v3: Review from Russell:
- s/framework/helper
- clarify the documentation for component_match_add functions.

Cc: "C, Ramalingam" <ramalingam.c@intel.com>
Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Cc: Russell King <rmk+kernel@arm.linux.org.uk>
Cc: Rafael J. Wysocki <rafael@kernel.org>
Cc: Jaroslav Kysela <perex@perex.cz>
Cc: Takashi Iwai <tiwai@suse.com>
Cc: Rodrigo Vivi <rodrigo.vivi@intel.com>
Cc: Jani Nikula <jani.nikula@linux.intel.com>
Signed-off-by: Daniel Vetter <daniel.vetter@intel.com>
---
 Documentation/driver-api/component.rst   |  17 ++++
 Documentation/driver-api/device_link.rst |   3 +
 Documentation/driver-api/index.rst       |   1 +
 drivers/base/component.c                 | 107 ++++++++++++++++++++++-
 include/linux/component.h                |  71 +++++++++++++++
 5 files changed, 196 insertions(+), 3 deletions(-)
 create mode 100644 Documentation/driver-api/component.rst

diff --git a/Documentation/driver-api/component.rst b/Documentation/driver-api/component.rst
new file mode 100644
index 000000000000..2da4a8f20607
--- /dev/null
+++ b/Documentation/driver-api/component.rst
@@ -0,0 +1,17 @@
+======================================
+Component Helper for Aggregate Drivers
+======================================
+
+.. kernel-doc:: drivers/base/component.c
+   :doc: overview
+
+
+API
+===
+
+.. kernel-doc:: include/linux/component.h
+   :internal:
+
+.. kernel-doc:: drivers/base/component.c
+   :export:
+
diff --git a/Documentation/driver-api/device_link.rst b/Documentation/driver-api/device_link.rst
index d6763272e747..2d5919b2b337 100644
--- a/Documentation/driver-api/device_link.rst
+++ b/Documentation/driver-api/device_link.rst
@@ -1,6 +1,9 @@
 .. |struct dev_pm_domain| replace:: :c:type:`struct dev_pm_domain <dev_pm_domain>`
 .. |struct generic_pm_domain| replace:: :c:type:`struct generic_pm_domain <generic_pm_domain>`
 
+
+.. _device_link:
+
 ============
 Device links
 ============
diff --git a/Documentation/driver-api/index.rst b/Documentation/driver-api/index.rst
index ab38ced66a44..c0b600ed9961 100644
--- a/Documentation/driver-api/index.rst
+++ b/Documentation/driver-api/index.rst
@@ -22,6 +22,7 @@ available subsections can be seen below.
    device_connection
    dma-buf
    device_link
+   component
    message-based
    sound
    frame-buffer
diff --git a/drivers/base/component.c b/drivers/base/component.c
index ddcea8739c12..f34d4b784709 100644
--- a/drivers/base/component.c
+++ b/drivers/base/component.c
@@ -16,6 +16,32 @@
 #include <linux/slab.h>
 #include <linux/debugfs.h>
 
+/**
+ * DOC: overview
+ *
+ * The component helper allows drivers to collect a pile of sub-devices,
+ * including their bound drivers, into an aggregate driver. Various subsystems
+ * already provide functions to get hold of such components, e.g.
+ * of_clk_get_by_name(). The component helper can be used when such a
+ * subsystem-specific way to find a device is not available: The component
+ * helper fills the niche of aggregate drivers for specific hardware, where
+ * further standardization into a subsystem would not be practical. The common
+ * example is when a logical device (e.g. a DRM display driver) is spread around
+ * the SoC on various component (scanout engines, blending blocks, transcoders
+ * for various outputs and so on).
+ *
+ * The component helper also doesn't solve runtime dependencies, e.g. for system
+ * suspend and resume operations. See also :ref:`device links<device_link>`.
+ *
+ * Components are registered using component_add() and unregistered with
+ * component_del(), usually from the driver's probe and disconnect functions.
+ *
+ * Aggregate drivers first assemble a component match list of what they need
+ * using component_match_add(). This is then registered as an aggregate driver
+ * using component_master_add_with_match(), and unregistered using
+ * component_master_del().
+ */
+
 struct component;
 
 struct component_match_array {
@@ -301,10 +327,25 @@ static int component_match_realloc(struct device *dev,
 	return 0;
 }
 
-/*
- * Add a component to be matched, with a release function.
+/**
+ * component_match_add_release - add a component match with release callback
+ * @master: device with the aggregate driver
+ * @matchptr: pointer to the list of component matches
+ * @release: release function for @compare_data
+ * @compare: compare function to match against all components
+ * @compare_data: opaque pointer passed to the @compare function
+ *
+ * This adds a new component match to the list stored in @matchptr, which the
+ * @master aggregate driver needs to function. The list of component matches
+ * pointed to by @matchptr must be initialized to NULL before adding the first
+ * match.
+ *
+ * The allocated match list in @matchptr is automatically released using devm
+ * actions, where upon @release will be called to free any references held by
+ * @compare_data, e.g. when @compare_data is a &device_node that must be
+ * released with of_node_put().
  *
- * The match array is first created or extended if necessary.
+ * See also component_match_add().
  */
 void component_match_add_release(struct device *master,
 	struct component_match **matchptr,
@@ -367,6 +408,18 @@ static void free_master(struct master *master)
 	kfree(master);
 }
 
+/**
+ * component_master_add_with_match - register an aggregate driver
+ * @dev: device with the aggregate driver
+ * @ops: callbacks for the aggregate driver
+ * @match: component match list for the aggregate driver
+ *
+ * Registers a new aggregate driver consisting of the components added to @match
+ * by calling one of the component_match_add() functions. Once all components in
+ * @match are available, it will be assembled by calling
+ * &component_master_ops.bind from @ops. Must be unregistered by calling
+ * component_master_del().
+ */
 int component_master_add_with_match(struct device *dev,
 	const struct component_master_ops *ops,
 	struct component_match *match)
@@ -403,6 +456,15 @@ int component_master_add_with_match(struct device *dev,
 }
 EXPORT_SYMBOL_GPL(component_master_add_with_match);
 
+/**
+ * component_master_del - unregister an aggregate driver
+ * @dev: device with the aggregate driver
+ * @ops: callbacks for the aggregate driver
+ *
+ * Unregisters an aggregate driver registered with
+ * component_master_add_with_match(). If necessary the aggregate driver is first
+ * disassembled by calling &component_master_ops.unbind from @ops.
+ */
 void component_master_del(struct device *dev,
 	const struct component_master_ops *ops)
 {
@@ -430,6 +492,15 @@ static void component_unbind(struct component *component,
 	devres_release_group(component->dev, component);
 }
 
+/**
+ * component_unbind_all - unbind all component to an aggregate driver
+ * @master_dev: device with the aggregate driver
+ * @data: opaque pointer, passed to all components
+ *
+ * Unbinds all components to the aggregate @dev by passing @data to their
+ * &component_ops.unbind functions. Should be called from
+ * &component_master_ops.unbind.
+ */
 void component_unbind_all(struct device *master_dev, void *data)
 {
 	struct master *master;
@@ -503,6 +574,15 @@ static int component_bind(struct component *component, struct master *master,
 	return ret;
 }
 
+/**
+ * component_bind_all - bind all component to an aggregate driver
+ * @master_dev: device with the aggregate driver
+ * @data: opaque pointer, passed to all components
+ *
+ * Binds all components to the aggregate @dev by passing @data to their
+ * &component_ops.bind functions. Should be called from
+ * &component_master_ops.bind.
+ */
 int component_bind_all(struct device *master_dev, void *data)
 {
 	struct master *master;
@@ -537,6 +617,18 @@ int component_bind_all(struct device *master_dev, void *data)
 }
 EXPORT_SYMBOL_GPL(component_bind_all);
 
+/**
+ * component_add - register a component
+ * @dev: component device
+ * @ops: component callbacks
+ *
+ * Register a new component for @dev. Functions in @ops will be called when the
+ * aggregate driver is ready to bind the overall driver by calling
+ * component_bind_all(). See also &struct component_ops.
+ *
+ * The component needs to be unregistered at driver unload/disconnect by calling
+ * component_del().
+ */
 int component_add(struct device *dev, const struct component_ops *ops)
 {
 	struct component *component;
@@ -568,6 +660,15 @@ int component_add(struct device *dev, const struct component_ops *ops)
 }
 EXPORT_SYMBOL_GPL(component_add);
 
+/**
+ * component_del - unregister a component
+ * @dev: component device
+ * @ops: component callbacks
+ *
+ * Unregister a component added with component_add(). If the component is bound
+ * into an aggregate driver, this will force the entire aggregate driver, including
+ * all its components, to be unbound.
+ */
 void component_del(struct device *dev, const struct component_ops *ops)
 {
 	struct component *c, *component = NULL;
diff --git a/include/linux/component.h b/include/linux/component.h
index e71fbbbc74e2..4911598b4c42 100644
--- a/include/linux/component.h
+++ b/include/linux/component.h
@@ -4,11 +4,31 @@
 
 #include <linux/stddef.h>
 
+
 struct device;
 
+/**
+ * struct component_ops - callbacks for component drivers
+ *
+ * Components are registered with component_add() and unregistered with
+ * component_del().
+ */
 struct component_ops {
+	/**
+	 * @bind:
+	 *
+	 * Called through component_bind_all() when the aggregate driver is
+	 * ready to bind the overall driver.
+	 */
 	int (*bind)(struct device *comp, struct device *master,
 		    void *master_data);
+	/**
+	 * @unbind:
+	 *
+	 * Called through component_unbind_all() when the aggregate driver is
+	 * ready to bind the overall driver, or when component_bind_all() fails
+	 * part-ways through and needs to unbind some already bound components.
+	 */
 	void (*unbind)(struct device *comp, struct device *master,
 		       void *master_data);
 };
@@ -21,8 +41,42 @@ void component_unbind_all(struct device *master, void *master_data);
 
 struct master;
 
+/**
+ * struct component_master_ops - callback for the aggregate driver
+ *
+ * Aggregate drivers are registered with component_master_add_with_match() and
+ * unregistered with component_master_del().
+ */
 struct component_master_ops {
+	/**
+	 * @bind:
+	 *
+	 * Called when all components or the aggregate driver, as specified in
+	 * the match list passed to component_master_add_with_match(), are
+	 * ready. Usually there are 3 steps to bind an aggregate driver:
+	 *
+	 * 1. Allocate a structure for the aggregate driver.
+	 *
+	 * 2. Bind all components to the aggregate driver by calling
+	 *    component_bind_all() with the aggregate driver structure as opaque
+	 *    pointer data.
+	 *
+	 * 3. Register the aggregate driver with the subsystem to publish its
+	 *    interfaces.
+	 *
+	 * Note that the lifetime of the aggregate driver does not align with
+	 * any of the underlying &struct device instances. Therefore devm cannot
+	 * be used and all resources acquired or allocated in this callback must
+	 * be explicitly released in the @unbind callback.
+	 */
 	int (*bind)(struct device *master);
+	/**
+	 * @unbind:
+	 *
+	 * Called when either the aggregate driver, using
+	 * component_master_del(), or one of its components, using
+	 * component_del(), is unregistered.
+	 */
 	void (*unbind)(struct device *master);
 };
 
@@ -38,6 +92,23 @@ void component_match_add_release(struct device *master,
 	void (*release)(struct device *, void *),
 	int (*compare)(struct device *, void *), void *compare_data);
 
+/**
+ * component_match_add - add a compent match
+ * @master: device with the aggregate driver
+ * @matchptr: pointer to the list of component matches
+ * @compare: compare function to match against all components
+ * @compare_data: opaque pointer passed to the @compare function
+ *
+ * This adds a new component match to the list stored in @matchptr, which the
+ * @master aggregate driver needs to function. The list of component matches
+ * pointed to by @matchptr must be initialized to NULL before adding the first
+ * match.
+ *
+ * The allocated match list in @matchptr is automatically released using devm
+ * actions.
+ *
+ * See also component_match_add_release().
+ */
 static inline void component_match_add(struct device *master,
 	struct component_match **matchptr,
 	int (*compare)(struct device *, void *), void *compare_data)
-- 
2.20.1


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

* [PATCH] component: Add documentation
@ 2019-02-06 16:47       ` Daniel Vetter
  0 siblings, 0 replies; 121+ messages in thread
From: Daniel Vetter @ 2019-02-06 16:47 UTC (permalink / raw)
  To: DRI Development
  Cc: Rafael J . Wysocki, Daniel Vetter, Daniel Vetter, Takashi Iwai,
	LKML, Jaroslav Kysela, Rodrigo Vivi, Greg Kroah-Hartman,
	Russell King

While typing these I think doing an s/component_master/aggregate/
would be useful:
- it's shorter :-)
- I think component/aggregate is much more meaningful naming than
  component/puppetmaster or something like that. At least to my
  English ear "aggregate" emphasizes much more the "assemble a pile of
  things into something bigger" aspect, and there's not really much
  of a control hierarchy between aggregate and constituing components.

But that's way more than a quick doc typing exercise ...

Thanks to Ram for commenting on an initial draft of these docs.

v2: Review from Rafael:
- git add Documenation/driver-api/component.rst
- lots of polish to the wording + spelling fixes.

v3: Review from Russell:
- s/framework/helper
- clarify the documentation for component_match_add functions.

Cc: "C, Ramalingam" <ramalingam.c@intel.com>
Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Cc: Russell King <rmk+kernel@arm.linux.org.uk>
Cc: Rafael J. Wysocki <rafael@kernel.org>
Cc: Jaroslav Kysela <perex@perex.cz>
Cc: Takashi Iwai <tiwai@suse.com>
Cc: Rodrigo Vivi <rodrigo.vivi@intel.com>
Cc: Jani Nikula <jani.nikula@linux.intel.com>
Signed-off-by: Daniel Vetter <daniel.vetter@intel.com>
---
 Documentation/driver-api/component.rst   |  17 ++++
 Documentation/driver-api/device_link.rst |   3 +
 Documentation/driver-api/index.rst       |   1 +
 drivers/base/component.c                 | 107 ++++++++++++++++++++++-
 include/linux/component.h                |  71 +++++++++++++++
 5 files changed, 196 insertions(+), 3 deletions(-)
 create mode 100644 Documentation/driver-api/component.rst

diff --git a/Documentation/driver-api/component.rst b/Documentation/driver-api/component.rst
new file mode 100644
index 000000000000..2da4a8f20607
--- /dev/null
+++ b/Documentation/driver-api/component.rst
@@ -0,0 +1,17 @@
+======================================
+Component Helper for Aggregate Drivers
+======================================
+
+.. kernel-doc:: drivers/base/component.c
+   :doc: overview
+
+
+API
+===
+
+.. kernel-doc:: include/linux/component.h
+   :internal:
+
+.. kernel-doc:: drivers/base/component.c
+   :export:
+
diff --git a/Documentation/driver-api/device_link.rst b/Documentation/driver-api/device_link.rst
index d6763272e747..2d5919b2b337 100644
--- a/Documentation/driver-api/device_link.rst
+++ b/Documentation/driver-api/device_link.rst
@@ -1,6 +1,9 @@
 .. |struct dev_pm_domain| replace:: :c:type:`struct dev_pm_domain <dev_pm_domain>`
 .. |struct generic_pm_domain| replace:: :c:type:`struct generic_pm_domain <generic_pm_domain>`
 
+
+.. _device_link:
+
 ============
 Device links
 ============
diff --git a/Documentation/driver-api/index.rst b/Documentation/driver-api/index.rst
index ab38ced66a44..c0b600ed9961 100644
--- a/Documentation/driver-api/index.rst
+++ b/Documentation/driver-api/index.rst
@@ -22,6 +22,7 @@ available subsections can be seen below.
    device_connection
    dma-buf
    device_link
+   component
    message-based
    sound
    frame-buffer
diff --git a/drivers/base/component.c b/drivers/base/component.c
index ddcea8739c12..f34d4b784709 100644
--- a/drivers/base/component.c
+++ b/drivers/base/component.c
@@ -16,6 +16,32 @@
 #include <linux/slab.h>
 #include <linux/debugfs.h>
 
+/**
+ * DOC: overview
+ *
+ * The component helper allows drivers to collect a pile of sub-devices,
+ * including their bound drivers, into an aggregate driver. Various subsystems
+ * already provide functions to get hold of such components, e.g.
+ * of_clk_get_by_name(). The component helper can be used when such a
+ * subsystem-specific way to find a device is not available: The component
+ * helper fills the niche of aggregate drivers for specific hardware, where
+ * further standardization into a subsystem would not be practical. The common
+ * example is when a logical device (e.g. a DRM display driver) is spread around
+ * the SoC on various component (scanout engines, blending blocks, transcoders
+ * for various outputs and so on).
+ *
+ * The component helper also doesn't solve runtime dependencies, e.g. for system
+ * suspend and resume operations. See also :ref:`device links<device_link>`.
+ *
+ * Components are registered using component_add() and unregistered with
+ * component_del(), usually from the driver's probe and disconnect functions.
+ *
+ * Aggregate drivers first assemble a component match list of what they need
+ * using component_match_add(). This is then registered as an aggregate driver
+ * using component_master_add_with_match(), and unregistered using
+ * component_master_del().
+ */
+
 struct component;
 
 struct component_match_array {
@@ -301,10 +327,25 @@ static int component_match_realloc(struct device *dev,
 	return 0;
 }
 
-/*
- * Add a component to be matched, with a release function.
+/**
+ * component_match_add_release - add a component match with release callback
+ * @master: device with the aggregate driver
+ * @matchptr: pointer to the list of component matches
+ * @release: release function for @compare_data
+ * @compare: compare function to match against all components
+ * @compare_data: opaque pointer passed to the @compare function
+ *
+ * This adds a new component match to the list stored in @matchptr, which the
+ * @master aggregate driver needs to function. The list of component matches
+ * pointed to by @matchptr must be initialized to NULL before adding the first
+ * match.
+ *
+ * The allocated match list in @matchptr is automatically released using devm
+ * actions, where upon @release will be called to free any references held by
+ * @compare_data, e.g. when @compare_data is a &device_node that must be
+ * released with of_node_put().
  *
- * The match array is first created or extended if necessary.
+ * See also component_match_add().
  */
 void component_match_add_release(struct device *master,
 	struct component_match **matchptr,
@@ -367,6 +408,18 @@ static void free_master(struct master *master)
 	kfree(master);
 }
 
+/**
+ * component_master_add_with_match - register an aggregate driver
+ * @dev: device with the aggregate driver
+ * @ops: callbacks for the aggregate driver
+ * @match: component match list for the aggregate driver
+ *
+ * Registers a new aggregate driver consisting of the components added to @match
+ * by calling one of the component_match_add() functions. Once all components in
+ * @match are available, it will be assembled by calling
+ * &component_master_ops.bind from @ops. Must be unregistered by calling
+ * component_master_del().
+ */
 int component_master_add_with_match(struct device *dev,
 	const struct component_master_ops *ops,
 	struct component_match *match)
@@ -403,6 +456,15 @@ int component_master_add_with_match(struct device *dev,
 }
 EXPORT_SYMBOL_GPL(component_master_add_with_match);
 
+/**
+ * component_master_del - unregister an aggregate driver
+ * @dev: device with the aggregate driver
+ * @ops: callbacks for the aggregate driver
+ *
+ * Unregisters an aggregate driver registered with
+ * component_master_add_with_match(). If necessary the aggregate driver is first
+ * disassembled by calling &component_master_ops.unbind from @ops.
+ */
 void component_master_del(struct device *dev,
 	const struct component_master_ops *ops)
 {
@@ -430,6 +492,15 @@ static void component_unbind(struct component *component,
 	devres_release_group(component->dev, component);
 }
 
+/**
+ * component_unbind_all - unbind all component to an aggregate driver
+ * @master_dev: device with the aggregate driver
+ * @data: opaque pointer, passed to all components
+ *
+ * Unbinds all components to the aggregate @dev by passing @data to their
+ * &component_ops.unbind functions. Should be called from
+ * &component_master_ops.unbind.
+ */
 void component_unbind_all(struct device *master_dev, void *data)
 {
 	struct master *master;
@@ -503,6 +574,15 @@ static int component_bind(struct component *component, struct master *master,
 	return ret;
 }
 
+/**
+ * component_bind_all - bind all component to an aggregate driver
+ * @master_dev: device with the aggregate driver
+ * @data: opaque pointer, passed to all components
+ *
+ * Binds all components to the aggregate @dev by passing @data to their
+ * &component_ops.bind functions. Should be called from
+ * &component_master_ops.bind.
+ */
 int component_bind_all(struct device *master_dev, void *data)
 {
 	struct master *master;
@@ -537,6 +617,18 @@ int component_bind_all(struct device *master_dev, void *data)
 }
 EXPORT_SYMBOL_GPL(component_bind_all);
 
+/**
+ * component_add - register a component
+ * @dev: component device
+ * @ops: component callbacks
+ *
+ * Register a new component for @dev. Functions in @ops will be called when the
+ * aggregate driver is ready to bind the overall driver by calling
+ * component_bind_all(). See also &struct component_ops.
+ *
+ * The component needs to be unregistered at driver unload/disconnect by calling
+ * component_del().
+ */
 int component_add(struct device *dev, const struct component_ops *ops)
 {
 	struct component *component;
@@ -568,6 +660,15 @@ int component_add(struct device *dev, const struct component_ops *ops)
 }
 EXPORT_SYMBOL_GPL(component_add);
 
+/**
+ * component_del - unregister a component
+ * @dev: component device
+ * @ops: component callbacks
+ *
+ * Unregister a component added with component_add(). If the component is bound
+ * into an aggregate driver, this will force the entire aggregate driver, including
+ * all its components, to be unbound.
+ */
 void component_del(struct device *dev, const struct component_ops *ops)
 {
 	struct component *c, *component = NULL;
diff --git a/include/linux/component.h b/include/linux/component.h
index e71fbbbc74e2..4911598b4c42 100644
--- a/include/linux/component.h
+++ b/include/linux/component.h
@@ -4,11 +4,31 @@
 
 #include <linux/stddef.h>
 
+
 struct device;
 
+/**
+ * struct component_ops - callbacks for component drivers
+ *
+ * Components are registered with component_add() and unregistered with
+ * component_del().
+ */
 struct component_ops {
+	/**
+	 * @bind:
+	 *
+	 * Called through component_bind_all() when the aggregate driver is
+	 * ready to bind the overall driver.
+	 */
 	int (*bind)(struct device *comp, struct device *master,
 		    void *master_data);
+	/**
+	 * @unbind:
+	 *
+	 * Called through component_unbind_all() when the aggregate driver is
+	 * ready to bind the overall driver, or when component_bind_all() fails
+	 * part-ways through and needs to unbind some already bound components.
+	 */
 	void (*unbind)(struct device *comp, struct device *master,
 		       void *master_data);
 };
@@ -21,8 +41,42 @@ void component_unbind_all(struct device *master, void *master_data);
 
 struct master;
 
+/**
+ * struct component_master_ops - callback for the aggregate driver
+ *
+ * Aggregate drivers are registered with component_master_add_with_match() and
+ * unregistered with component_master_del().
+ */
 struct component_master_ops {
+	/**
+	 * @bind:
+	 *
+	 * Called when all components or the aggregate driver, as specified in
+	 * the match list passed to component_master_add_with_match(), are
+	 * ready. Usually there are 3 steps to bind an aggregate driver:
+	 *
+	 * 1. Allocate a structure for the aggregate driver.
+	 *
+	 * 2. Bind all components to the aggregate driver by calling
+	 *    component_bind_all() with the aggregate driver structure as opaque
+	 *    pointer data.
+	 *
+	 * 3. Register the aggregate driver with the subsystem to publish its
+	 *    interfaces.
+	 *
+	 * Note that the lifetime of the aggregate driver does not align with
+	 * any of the underlying &struct device instances. Therefore devm cannot
+	 * be used and all resources acquired or allocated in this callback must
+	 * be explicitly released in the @unbind callback.
+	 */
 	int (*bind)(struct device *master);
+	/**
+	 * @unbind:
+	 *
+	 * Called when either the aggregate driver, using
+	 * component_master_del(), or one of its components, using
+	 * component_del(), is unregistered.
+	 */
 	void (*unbind)(struct device *master);
 };
 
@@ -38,6 +92,23 @@ void component_match_add_release(struct device *master,
 	void (*release)(struct device *, void *),
 	int (*compare)(struct device *, void *), void *compare_data);
 
+/**
+ * component_match_add - add a compent match
+ * @master: device with the aggregate driver
+ * @matchptr: pointer to the list of component matches
+ * @compare: compare function to match against all components
+ * @compare_data: opaque pointer passed to the @compare function
+ *
+ * This adds a new component match to the list stored in @matchptr, which the
+ * @master aggregate driver needs to function. The list of component matches
+ * pointed to by @matchptr must be initialized to NULL before adding the first
+ * match.
+ *
+ * The allocated match list in @matchptr is automatically released using devm
+ * actions.
+ *
+ * See also component_match_add_release().
+ */
 static inline void component_match_add(struct device *master,
 	struct component_match **matchptr,
 	int (*compare)(struct device *, void *), void *compare_data)
-- 
2.20.1

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

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

* Re: [PATCH v10 25/40] misc/mei/hdcp: Initiate Wired HDCP2.2 Tx Session
  2019-02-06 10:27       ` Winkler, Tomas
@ 2019-02-06 21:14         ` C, Ramalingam
  0 siblings, 0 replies; 121+ messages in thread
From: C, Ramalingam @ 2019-02-06 21:14 UTC (permalink / raw)
  To: Winkler, Tomas, 'intel-gfx@lists.freedesktop.org',
	'dri-devel@lists.freedesktop.org',
	'daniel.vetter@ffwll.ch'



On 2/6/2019 3:57 PM, Winkler, Tomas wrote:
>>>> 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>
>>> Latest set look ok. You can keep the RB.
>>>
>>>> ---
>>>> drivers/misc/mei/hdcp/mei_hdcp.c | 82
>>>> ++++++++++++++++++++++++++++++++++++++++
>>>> drivers/misc/mei/hdcp/mei_hdcp.h | 28 ++++++++++++++
>>>> 2 files changed, 110 insertions(+)
>>>>
>>>> diff --git a/drivers/misc/mei/hdcp/mei_hdcp.c
>>>> b/drivers/misc/mei/hdcp/mei_hdcp.c
>>>> index ca5010ad7dd7..534d29c8ee86 100644
>>>> --- a/drivers/misc/mei/hdcp/mei_hdcp.c
>>>> +++ b/drivers/misc/mei/hdcp/mei_hdcp.c
>>>> @@ -23,6 +23,88 @@
>>>> #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 <drm/i915_mei_hdcp_interface.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) {
>>
>> Breaking naming conventions : all functions should be prefixed with mei_hdcp_
>>
>> e.g. mei_hdcp_ initiate_session()
>>
>>>> +	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 582a7e27ae29..f831db3cbd54 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 {
>> We've already reviewed. Move to i915 header or use mei_ prefix?
>>>> +	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__ */
> I wonder why we are casting it to another enum here and they you consistently  casting it to u8 back when assigned.
>
>
> mei_hdcp.c:     session_init_in.port.physical_port = (u8)GET_MEI_DDI_INDEX(data->port);
> mei_hdcp.c:     verify_rxcert_in.port.physical_port = (u8)GET_MEI_DDI_INDEX(data->port);
> mei_hdcp.c:     send_hprime_in.port.physical_port = (u8)GET_MEI_DDI_INDEX(data->port);
> mei_hdcp.c:     pairing_info_in.port.physical_port = (u8)GET_MEI_DDI_INDEX(data->port);
> mei_hdcp.c:     lc_init_in.port.physical_port = (u8)GET_MEI_DDI_INDEX(data->port);
> mei_hdcp.c:     verify_lprime_in.port.physical_port = (u8)GET_MEI_DDI_INDEX(data->port);
> mei_hdcp.c:     get_skey_in.port.physical_port = (u8)GET_MEI_DDI_INDEX(data->port);
> mei_hdcp.c:     verify_mprime_in.port.physical_port = (u8)GET_MEI_DDI_INDEX(data->port);
> mei_hdcp.c:     enable_auth_in.port.physical_port = (u8)GET_MEI_DDI_INDEX(data->port);
> mei_hdcp.c:     session_close_in.port.physical_port = (u8)GET_MEI_DDI_INDEX(data->port);
>
>
> This macro is only used in mei_hdcp.c so I would just make an inline function of it and push it to the c file.
Addressed in v11 which is published already.

Thanks
--Ram.
> Thanks
> Tomas
>

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

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

* Re: [PATCH] component: Add documentation
  2019-02-06 16:47       ` Daniel Vetter
  (?)
@ 2019-02-06 22:01       ` Rafael J. Wysocki
  -1 siblings, 0 replies; 121+ messages in thread
From: Rafael J. Wysocki @ 2019-02-06 22:01 UTC (permalink / raw)
  To: Daniel Vetter
  Cc: DRI Development, LKML, C, Ramalingam, Greg Kroah-Hartman,
	Russell King, Rafael J . Wysocki, Jaroslav Kysela, Takashi Iwai,
	Rodrigo Vivi, Jani Nikula, Daniel Vetter

On Wed, Feb 6, 2019 at 5:47 PM Daniel Vetter <daniel.vetter@ffwll.ch> wrote:
>
> While typing these I think doing an s/component_master/aggregate/
> would be useful:
> - it's shorter :-)
> - I think component/aggregate is much more meaningful naming than
>   component/puppetmaster or something like that. At least to my
>   English ear "aggregate" emphasizes much more the "assemble a pile of
>   things into something bigger" aspect, and there's not really much
>   of a control hierarchy between aggregate and constituing components.
>
> But that's way more than a quick doc typing exercise ...
>
> Thanks to Ram for commenting on an initial draft of these docs.
>
> v2: Review from Rafael:
> - git add Documenation/driver-api/component.rst
> - lots of polish to the wording + spelling fixes.
>
> v3: Review from Russell:
> - s/framework/helper
> - clarify the documentation for component_match_add functions.
>
> Cc: "C, Ramalingam" <ramalingam.c@intel.com>
> Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
> Cc: Russell King <rmk+kernel@arm.linux.org.uk>
> Cc: Rafael J. Wysocki <rafael@kernel.org>
> Cc: Jaroslav Kysela <perex@perex.cz>
> Cc: Takashi Iwai <tiwai@suse.com>
> Cc: Rodrigo Vivi <rodrigo.vivi@intel.com>
> Cc: Jani Nikula <jani.nikula@linux.intel.com>
> Signed-off-by: Daniel Vetter <daniel.vetter@intel.com>

Reviewed-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>

> ---
>  Documentation/driver-api/component.rst   |  17 ++++
>  Documentation/driver-api/device_link.rst |   3 +
>  Documentation/driver-api/index.rst       |   1 +
>  drivers/base/component.c                 | 107 ++++++++++++++++++++++-
>  include/linux/component.h                |  71 +++++++++++++++
>  5 files changed, 196 insertions(+), 3 deletions(-)
>  create mode 100644 Documentation/driver-api/component.rst
>
> diff --git a/Documentation/driver-api/component.rst b/Documentation/driver-api/component.rst
> new file mode 100644
> index 000000000000..2da4a8f20607
> --- /dev/null
> +++ b/Documentation/driver-api/component.rst
> @@ -0,0 +1,17 @@
> +======================================
> +Component Helper for Aggregate Drivers
> +======================================
> +
> +.. kernel-doc:: drivers/base/component.c
> +   :doc: overview
> +
> +
> +API
> +===
> +
> +.. kernel-doc:: include/linux/component.h
> +   :internal:
> +
> +.. kernel-doc:: drivers/base/component.c
> +   :export:
> +
> diff --git a/Documentation/driver-api/device_link.rst b/Documentation/driver-api/device_link.rst
> index d6763272e747..2d5919b2b337 100644
> --- a/Documentation/driver-api/device_link.rst
> +++ b/Documentation/driver-api/device_link.rst
> @@ -1,6 +1,9 @@
>  .. |struct dev_pm_domain| replace:: :c:type:`struct dev_pm_domain <dev_pm_domain>`
>  .. |struct generic_pm_domain| replace:: :c:type:`struct generic_pm_domain <generic_pm_domain>`
>
> +
> +.. _device_link:
> +
>  ============
>  Device links
>  ============
> diff --git a/Documentation/driver-api/index.rst b/Documentation/driver-api/index.rst
> index ab38ced66a44..c0b600ed9961 100644
> --- a/Documentation/driver-api/index.rst
> +++ b/Documentation/driver-api/index.rst
> @@ -22,6 +22,7 @@ available subsections can be seen below.
>     device_connection
>     dma-buf
>     device_link
> +   component
>     message-based
>     sound
>     frame-buffer
> diff --git a/drivers/base/component.c b/drivers/base/component.c
> index ddcea8739c12..f34d4b784709 100644
> --- a/drivers/base/component.c
> +++ b/drivers/base/component.c
> @@ -16,6 +16,32 @@
>  #include <linux/slab.h>
>  #include <linux/debugfs.h>
>
> +/**
> + * DOC: overview
> + *
> + * The component helper allows drivers to collect a pile of sub-devices,
> + * including their bound drivers, into an aggregate driver. Various subsystems
> + * already provide functions to get hold of such components, e.g.
> + * of_clk_get_by_name(). The component helper can be used when such a
> + * subsystem-specific way to find a device is not available: The component
> + * helper fills the niche of aggregate drivers for specific hardware, where
> + * further standardization into a subsystem would not be practical. The common
> + * example is when a logical device (e.g. a DRM display driver) is spread around
> + * the SoC on various component (scanout engines, blending blocks, transcoders
> + * for various outputs and so on).
> + *
> + * The component helper also doesn't solve runtime dependencies, e.g. for system
> + * suspend and resume operations. See also :ref:`device links<device_link>`.
> + *
> + * Components are registered using component_add() and unregistered with
> + * component_del(), usually from the driver's probe and disconnect functions.
> + *
> + * Aggregate drivers first assemble a component match list of what they need
> + * using component_match_add(). This is then registered as an aggregate driver
> + * using component_master_add_with_match(), and unregistered using
> + * component_master_del().
> + */
> +
>  struct component;
>
>  struct component_match_array {
> @@ -301,10 +327,25 @@ static int component_match_realloc(struct device *dev,
>         return 0;
>  }
>
> -/*
> - * Add a component to be matched, with a release function.
> +/**
> + * component_match_add_release - add a component match with release callback
> + * @master: device with the aggregate driver
> + * @matchptr: pointer to the list of component matches
> + * @release: release function for @compare_data
> + * @compare: compare function to match against all components
> + * @compare_data: opaque pointer passed to the @compare function
> + *
> + * This adds a new component match to the list stored in @matchptr, which the
> + * @master aggregate driver needs to function. The list of component matches
> + * pointed to by @matchptr must be initialized to NULL before adding the first
> + * match.
> + *
> + * The allocated match list in @matchptr is automatically released using devm
> + * actions, where upon @release will be called to free any references held by
> + * @compare_data, e.g. when @compare_data is a &device_node that must be
> + * released with of_node_put().
>   *
> - * The match array is first created or extended if necessary.
> + * See also component_match_add().
>   */
>  void component_match_add_release(struct device *master,
>         struct component_match **matchptr,
> @@ -367,6 +408,18 @@ static void free_master(struct master *master)
>         kfree(master);
>  }
>
> +/**
> + * component_master_add_with_match - register an aggregate driver
> + * @dev: device with the aggregate driver
> + * @ops: callbacks for the aggregate driver
> + * @match: component match list for the aggregate driver
> + *
> + * Registers a new aggregate driver consisting of the components added to @match
> + * by calling one of the component_match_add() functions. Once all components in
> + * @match are available, it will be assembled by calling
> + * &component_master_ops.bind from @ops. Must be unregistered by calling
> + * component_master_del().
> + */
>  int component_master_add_with_match(struct device *dev,
>         const struct component_master_ops *ops,
>         struct component_match *match)
> @@ -403,6 +456,15 @@ int component_master_add_with_match(struct device *dev,
>  }
>  EXPORT_SYMBOL_GPL(component_master_add_with_match);
>
> +/**
> + * component_master_del - unregister an aggregate driver
> + * @dev: device with the aggregate driver
> + * @ops: callbacks for the aggregate driver
> + *
> + * Unregisters an aggregate driver registered with
> + * component_master_add_with_match(). If necessary the aggregate driver is first
> + * disassembled by calling &component_master_ops.unbind from @ops.
> + */
>  void component_master_del(struct device *dev,
>         const struct component_master_ops *ops)
>  {
> @@ -430,6 +492,15 @@ static void component_unbind(struct component *component,
>         devres_release_group(component->dev, component);
>  }
>
> +/**
> + * component_unbind_all - unbind all component to an aggregate driver
> + * @master_dev: device with the aggregate driver
> + * @data: opaque pointer, passed to all components
> + *
> + * Unbinds all components to the aggregate @dev by passing @data to their
> + * &component_ops.unbind functions. Should be called from
> + * &component_master_ops.unbind.
> + */
>  void component_unbind_all(struct device *master_dev, void *data)
>  {
>         struct master *master;
> @@ -503,6 +574,15 @@ static int component_bind(struct component *component, struct master *master,
>         return ret;
>  }
>
> +/**
> + * component_bind_all - bind all component to an aggregate driver
> + * @master_dev: device with the aggregate driver
> + * @data: opaque pointer, passed to all components
> + *
> + * Binds all components to the aggregate @dev by passing @data to their
> + * &component_ops.bind functions. Should be called from
> + * &component_master_ops.bind.
> + */
>  int component_bind_all(struct device *master_dev, void *data)
>  {
>         struct master *master;
> @@ -537,6 +617,18 @@ int component_bind_all(struct device *master_dev, void *data)
>  }
>  EXPORT_SYMBOL_GPL(component_bind_all);
>
> +/**
> + * component_add - register a component
> + * @dev: component device
> + * @ops: component callbacks
> + *
> + * Register a new component for @dev. Functions in @ops will be called when the
> + * aggregate driver is ready to bind the overall driver by calling
> + * component_bind_all(). See also &struct component_ops.
> + *
> + * The component needs to be unregistered at driver unload/disconnect by calling
> + * component_del().
> + */
>  int component_add(struct device *dev, const struct component_ops *ops)
>  {
>         struct component *component;
> @@ -568,6 +660,15 @@ int component_add(struct device *dev, const struct component_ops *ops)
>  }
>  EXPORT_SYMBOL_GPL(component_add);
>
> +/**
> + * component_del - unregister a component
> + * @dev: component device
> + * @ops: component callbacks
> + *
> + * Unregister a component added with component_add(). If the component is bound
> + * into an aggregate driver, this will force the entire aggregate driver, including
> + * all its components, to be unbound.
> + */
>  void component_del(struct device *dev, const struct component_ops *ops)
>  {
>         struct component *c, *component = NULL;
> diff --git a/include/linux/component.h b/include/linux/component.h
> index e71fbbbc74e2..4911598b4c42 100644
> --- a/include/linux/component.h
> +++ b/include/linux/component.h
> @@ -4,11 +4,31 @@
>
>  #include <linux/stddef.h>
>
> +
>  struct device;
>
> +/**
> + * struct component_ops - callbacks for component drivers
> + *
> + * Components are registered with component_add() and unregistered with
> + * component_del().
> + */
>  struct component_ops {
> +       /**
> +        * @bind:
> +        *
> +        * Called through component_bind_all() when the aggregate driver is
> +        * ready to bind the overall driver.
> +        */
>         int (*bind)(struct device *comp, struct device *master,
>                     void *master_data);
> +       /**
> +        * @unbind:
> +        *
> +        * Called through component_unbind_all() when the aggregate driver is
> +        * ready to bind the overall driver, or when component_bind_all() fails
> +        * part-ways through and needs to unbind some already bound components.
> +        */
>         void (*unbind)(struct device *comp, struct device *master,
>                        void *master_data);
>  };
> @@ -21,8 +41,42 @@ void component_unbind_all(struct device *master, void *master_data);
>
>  struct master;
>
> +/**
> + * struct component_master_ops - callback for the aggregate driver
> + *
> + * Aggregate drivers are registered with component_master_add_with_match() and
> + * unregistered with component_master_del().
> + */
>  struct component_master_ops {
> +       /**
> +        * @bind:
> +        *
> +        * Called when all components or the aggregate driver, as specified in
> +        * the match list passed to component_master_add_with_match(), are
> +        * ready. Usually there are 3 steps to bind an aggregate driver:
> +        *
> +        * 1. Allocate a structure for the aggregate driver.
> +        *
> +        * 2. Bind all components to the aggregate driver by calling
> +        *    component_bind_all() with the aggregate driver structure as opaque
> +        *    pointer data.
> +        *
> +        * 3. Register the aggregate driver with the subsystem to publish its
> +        *    interfaces.
> +        *
> +        * Note that the lifetime of the aggregate driver does not align with
> +        * any of the underlying &struct device instances. Therefore devm cannot
> +        * be used and all resources acquired or allocated in this callback must
> +        * be explicitly released in the @unbind callback.
> +        */
>         int (*bind)(struct device *master);
> +       /**
> +        * @unbind:
> +        *
> +        * Called when either the aggregate driver, using
> +        * component_master_del(), or one of its components, using
> +        * component_del(), is unregistered.
> +        */
>         void (*unbind)(struct device *master);
>  };
>
> @@ -38,6 +92,23 @@ void component_match_add_release(struct device *master,
>         void (*release)(struct device *, void *),
>         int (*compare)(struct device *, void *), void *compare_data);
>
> +/**
> + * component_match_add - add a compent match
> + * @master: device with the aggregate driver
> + * @matchptr: pointer to the list of component matches
> + * @compare: compare function to match against all components
> + * @compare_data: opaque pointer passed to the @compare function
> + *
> + * This adds a new component match to the list stored in @matchptr, which the
> + * @master aggregate driver needs to function. The list of component matches
> + * pointed to by @matchptr must be initialized to NULL before adding the first
> + * match.
> + *
> + * The allocated match list in @matchptr is automatically released using devm
> + * actions.
> + *
> + * See also component_match_add_release().
> + */
>  static inline void component_match_add(struct device *master,
>         struct component_match **matchptr,
>         int (*compare)(struct device *, void *), void *compare_data)
> --
> 2.20.1
>

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

* Re: [PATCH 2/3] components: multiple components for a device
  2019-02-06 16:45     ` [PATCH 2/3] components: multiple components for a device Daniel Vetter
@ 2019-02-06 22:57       ` Rafael J. Wysocki
  2019-02-07 22:35         ` Daniel Vetter
  2019-02-07 22:40         ` Daniel Vetter
  0 siblings, 2 replies; 121+ messages in thread
From: Rafael J. Wysocki @ 2019-02-06 22:57 UTC (permalink / raw)
  To: Daniel Vetter
  Cc: Rafael J . Wysocki, Intel Graphics Development, Takashi Iwai,
	DRI Development, Jaroslav Kysela, Greg Kroah-Hartman,
	Russell King

) On Wed, Feb 6, 2019 at 5:46 PM Daniel Vetter <daniel.vetter@ffwll.ch> wrote:
>
> Component framework is extended to support multiple components for
> a struct device. These will be matched with different masters based on
> its sub component value.
>
> We are introducing this, as I915 needs two different components
> with different subcomponent value, which will be matched to two
> different component masters(Audio and HDCP) based on the subcomponent
> values.
>
> v2: Add documenation.
>
> v3: Rebase on top of updated documenation.
>
> Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch> (v1 code)
> Signed-off-by: Ramalingam C <ramalingam.c@intel.com> (v1 commit message)
> Cc: Ramalingam C <ramalingam.c@intel.com>
> Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
> Cc: Russell King <rmk+kernel@arm.linux.org.uk>
> Cc: Rafael J. Wysocki <rafael@kernel.org>
> Cc: Jaroslav Kysela <perex@perex.cz>
> Cc: Takashi Iwai <tiwai@suse.com>
> Cc: Rodrigo Vivi <rodrigo.vivi@intel.com>
> Cc: Jani Nikula <jani.nikula@linux.intel.com>
> Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
> ---
>  drivers/base/component.c  | 160 +++++++++++++++++++++++++++++---------
>  include/linux/component.h |   9 ++-
>  2 files changed, 129 insertions(+), 40 deletions(-)
>
> diff --git a/drivers/base/component.c b/drivers/base/component.c
> index f34d4b784709..68ccd5a0d5d6 100644
> --- a/drivers/base/component.c
> +++ b/drivers/base/component.c
> @@ -47,6 +47,7 @@ struct component;
>  struct component_match_array {
>         void *data;
>         int (*compare)(struct device *, void *);
> +       int (*compare_typed)(struct device *, int, void *);
>         void (*release)(struct device *, void *);
>         struct component *component;
>         bool duplicate;
> @@ -74,6 +75,7 @@ struct component {
>         bool bound;
>
>         const struct component_ops *ops;
> +       int subcomponent;
>         struct device *dev;
>  };
>
> @@ -158,7 +160,7 @@ static struct master *__master_find(struct device *dev,
>  }
>
>  static struct component *find_component(struct master *master,
> -       int (*compare)(struct device *, void *), void *compare_data)
> +       struct component_match_array *mc)
>  {
>         struct component *c;
>
> @@ -166,8 +168,13 @@ static struct component *find_component(struct master *master,
>                 if (c->master && c->master != master)
>                         continue;
>
> -               if (compare(c->dev, compare_data))
> +               if (mc->compare_typed) {
> +                       if (mc->compare_typed(c->dev, c->subcomponent,
> +                                             mc->data))

This line break looks kind of weird to me,

> +                               return c;
> +               } else if (mc->compare(c->dev, mc->data)) {
>                         return c;
> +               }

Also, why don't you do

if (mc->compare(c->dev, mc->data) || (mc->compare_typed &&
    mc->compare_typed(c->dev, c->subcomponent, mc->data)))
        return c;

The only difference is that ->compare() will run first and if it finds
a match, c will be returned right away.  Does it matter?

>         }
>
>         return NULL;
> @@ -192,7 +199,7 @@ static int find_components(struct master *master)
>                 if (match->compare[i].component)
>                         continue;
>
> -               c = find_component(master, mc->compare, mc->data);
> +               c = find_component(master, mc);
>                 if (!c) {
>                         ret = -ENXIO;
>                         break;
> @@ -327,30 +334,12 @@ static int component_match_realloc(struct device *dev,
>         return 0;
>  }
>
> -/**
> - * component_match_add_release - add a component match with release callback
> - * @master: device with the aggregate driver
> - * @matchptr: pointer to the list of component matches
> - * @release: release function for @compare_data
> - * @compare: compare function to match against all components
> - * @compare_data: opaque pointer passed to the @compare function
> - *
> - * This adds a new component match to the list stored in @matchptr, which the

"This" appears to be redundant here (and in some places below too).
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

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

* Re: [PATCH 2/3] components: multiple components for a device
  2019-02-06 22:57       ` Rafael J. Wysocki
@ 2019-02-07 22:35         ` Daniel Vetter
  2019-02-07 22:40         ` Daniel Vetter
  1 sibling, 0 replies; 121+ messages in thread
From: Daniel Vetter @ 2019-02-07 22:35 UTC (permalink / raw)
  To: Rafael J. Wysocki
  Cc: Daniel Vetter, Intel Graphics Development, Takashi Iwai,
	DRI Development, Jaroslav Kysela, Greg Kroah-Hartman,
	Russell King

On Wed, Feb 06, 2019 at 11:57:04PM +0100, Rafael J. Wysocki wrote:
> ) On Wed, Feb 6, 2019 at 5:46 PM Daniel Vetter <daniel.vetter@ffwll.ch> wrote:
> >
> > Component framework is extended to support multiple components for
> > a struct device. These will be matched with different masters based on
> > its sub component value.
> >
> > We are introducing this, as I915 needs two different components
> > with different subcomponent value, which will be matched to two
> > different component masters(Audio and HDCP) based on the subcomponent
> > values.
> >
> > v2: Add documenation.
> >
> > v3: Rebase on top of updated documenation.
> >
> > Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch> (v1 code)
> > Signed-off-by: Ramalingam C <ramalingam.c@intel.com> (v1 commit message)
> > Cc: Ramalingam C <ramalingam.c@intel.com>
> > Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
> > Cc: Russell King <rmk+kernel@arm.linux.org.uk>
> > Cc: Rafael J. Wysocki <rafael@kernel.org>
> > Cc: Jaroslav Kysela <perex@perex.cz>
> > Cc: Takashi Iwai <tiwai@suse.com>
> > Cc: Rodrigo Vivi <rodrigo.vivi@intel.com>
> > Cc: Jani Nikula <jani.nikula@linux.intel.com>
> > Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
> > ---
> >  drivers/base/component.c  | 160 +++++++++++++++++++++++++++++---------
> >  include/linux/component.h |   9 ++-
> >  2 files changed, 129 insertions(+), 40 deletions(-)
> >
> > diff --git a/drivers/base/component.c b/drivers/base/component.c
> > index f34d4b784709..68ccd5a0d5d6 100644
> > --- a/drivers/base/component.c
> > +++ b/drivers/base/component.c
> > @@ -47,6 +47,7 @@ struct component;
> >  struct component_match_array {
> >         void *data;
> >         int (*compare)(struct device *, void *);
> > +       int (*compare_typed)(struct device *, int, void *);
> >         void (*release)(struct device *, void *);
> >         struct component *component;
> >         bool duplicate;
> > @@ -74,6 +75,7 @@ struct component {
> >         bool bound;
> >
> >         const struct component_ops *ops;
> > +       int subcomponent;
> >         struct device *dev;
> >  };
> >
> > @@ -158,7 +160,7 @@ static struct master *__master_find(struct device *dev,
> >  }
> >
> >  static struct component *find_component(struct master *master,
> > -       int (*compare)(struct device *, void *), void *compare_data)
> > +       struct component_match_array *mc)
> >  {
> >         struct component *c;
> >
> > @@ -166,8 +168,13 @@ static struct component *find_component(struct master *master,
> >                 if (c->master && c->master != master)
> >                         continue;
> >
> > -               if (compare(c->dev, compare_data))
> > +               if (mc->compare_typed) {
> > +                       if (mc->compare_typed(c->dev, c->subcomponent,
> > +                                             mc->data))
> 
> This line break looks kind of weird to me,
> 
> > +                               return c;
> > +               } else if (mc->compare(c->dev, mc->data)) {
> >                         return c;
> > +               }
> 
> Also, why don't you do
> 
> if (mc->compare(c->dev, mc->data) || (mc->compare_typed &&
>     mc->compare_typed(c->dev, c->subcomponent, mc->data)))
>         return c;
> 
> The only difference is that ->compare() will run first and if it finds
> a match, c will be returned right away.  Does it matter?

Sounds good.

> 
> >         }
> >
> >         return NULL;
> > @@ -192,7 +199,7 @@ static int find_components(struct master *master)
> >                 if (match->compare[i].component)
> >                         continue;
> >
> > -               c = find_component(master, mc->compare, mc->data);
> > +               c = find_component(master, mc);
> >                 if (!c) {
> >                         ret = -ENXIO;
> >                         break;
> > @@ -327,30 +334,12 @@ static int component_match_realloc(struct device *dev,
> >         return 0;
> >  }
> >
> > -/**
> > - * component_match_add_release - add a component match with release callback
> > - * @master: device with the aggregate driver
> > - * @matchptr: pointer to the list of component matches
> > - * @release: release function for @compare_data
> > - * @compare: compare function to match against all components
> > - * @compare_data: opaque pointer passed to the @compare function
> > - *
> > - * This adds a new component match to the list stored in @matchptr, which the
> 
> "This" appears to be redundant here (and in some places below too).

Yup, also removed from the previous patch.

I'll respin, thanks for taking a look.
-Daniel
-- 
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] 121+ messages in thread

* Re: [PATCH 2/3] components: multiple components for a device
  2019-02-06 22:57       ` Rafael J. Wysocki
  2019-02-07 22:35         ` Daniel Vetter
@ 2019-02-07 22:40         ` Daniel Vetter
  2019-02-07 22:48           ` Rafael J. Wysocki
  1 sibling, 1 reply; 121+ messages in thread
From: Daniel Vetter @ 2019-02-07 22:40 UTC (permalink / raw)
  To: Rafael J. Wysocki
  Cc: Daniel Vetter, Intel Graphics Development, Rodrigo Vivi,
	Takashi Iwai, DRI Development, Jaroslav Kysela,
	Greg Kroah-Hartman, Russell King

On Wed, Feb 06, 2019 at 11:57:04PM +0100, Rafael J. Wysocki wrote:
> ) On Wed, Feb 6, 2019 at 5:46 PM Daniel Vetter <daniel.vetter@ffwll.ch> wrote:
> >
> > Component framework is extended to support multiple components for
> > a struct device. These will be matched with different masters based on
> > its sub component value.
> >
> > We are introducing this, as I915 needs two different components
> > with different subcomponent value, which will be matched to two
> > different component masters(Audio and HDCP) based on the subcomponent
> > values.
> >
> > v2: Add documenation.
> >
> > v3: Rebase on top of updated documenation.
> >
> > Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch> (v1 code)
> > Signed-off-by: Ramalingam C <ramalingam.c@intel.com> (v1 commit message)
> > Cc: Ramalingam C <ramalingam.c@intel.com>
> > Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
> > Cc: Russell King <rmk+kernel@arm.linux.org.uk>
> > Cc: Rafael J. Wysocki <rafael@kernel.org>
> > Cc: Jaroslav Kysela <perex@perex.cz>
> > Cc: Takashi Iwai <tiwai@suse.com>
> > Cc: Rodrigo Vivi <rodrigo.vivi@intel.com>
> > Cc: Jani Nikula <jani.nikula@linux.intel.com>
> > Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
> > ---
> >  drivers/base/component.c  | 160 +++++++++++++++++++++++++++++---------
> >  include/linux/component.h |   9 ++-
> >  2 files changed, 129 insertions(+), 40 deletions(-)
> >
> > diff --git a/drivers/base/component.c b/drivers/base/component.c
> > index f34d4b784709..68ccd5a0d5d6 100644
> > --- a/drivers/base/component.c
> > +++ b/drivers/base/component.c
> > @@ -47,6 +47,7 @@ struct component;
> >  struct component_match_array {
> >         void *data;
> >         int (*compare)(struct device *, void *);
> > +       int (*compare_typed)(struct device *, int, void *);
> >         void (*release)(struct device *, void *);
> >         struct component *component;
> >         bool duplicate;
> > @@ -74,6 +75,7 @@ struct component {
> >         bool bound;
> >
> >         const struct component_ops *ops;
> > +       int subcomponent;
> >         struct device *dev;
> >  };
> >
> > @@ -158,7 +160,7 @@ static struct master *__master_find(struct device *dev,
> >  }
> >
> >  static struct component *find_component(struct master *master,
> > -       int (*compare)(struct device *, void *), void *compare_data)
> > +       struct component_match_array *mc)
> >  {
> >         struct component *c;
> >
> > @@ -166,8 +168,13 @@ static struct component *find_component(struct master *master,
> >                 if (c->master && c->master != master)
> >                         continue;
> >
> > -               if (compare(c->dev, compare_data))
> > +               if (mc->compare_typed) {
> > +                       if (mc->compare_typed(c->dev, c->subcomponent,
> > +                                             mc->data))
> 
> This line break looks kind of weird to me,
> 
> > +                               return c;
> > +               } else if (mc->compare(c->dev, mc->data)) {
> >                         return c;
> > +               }
> 
> Also, why don't you do
> 
> if (mc->compare(c->dev, mc->data) || (mc->compare_typed &&
>     mc->compare_typed(c->dev, c->subcomponent, mc->data)))
>         return c;
> 
> The only difference is that ->compare() will run first and if it finds
> a match, c will be returned right away.  Does it matter?

Tried it, yes it does matter: We have either ->compare or ->compare_typed,
so calling one unconditionally blows up. Can still be streamlined a bit I
think.
-Daniel

> 
> >         }
> >
> >         return NULL;
> > @@ -192,7 +199,7 @@ static int find_components(struct master *master)
> >                 if (match->compare[i].component)
> >                         continue;
> >
> > -               c = find_component(master, mc->compare, mc->data);
> > +               c = find_component(master, mc);
> >                 if (!c) {
> >                         ret = -ENXIO;
> >                         break;
> > @@ -327,30 +334,12 @@ static int component_match_realloc(struct device *dev,
> >         return 0;
> >  }
> >
> > -/**
> > - * component_match_add_release - add a component match with release callback
> > - * @master: device with the aggregate driver
> > - * @matchptr: pointer to the list of component matches
> > - * @release: release function for @compare_data
> > - * @compare: compare function to match against all components
> > - * @compare_data: opaque pointer passed to the @compare function
> > - *
> > - * This adds a new component match to the list stored in @matchptr, which the
> 
> "This" appears to be redundant here (and in some places below too).

-- 
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] 121+ messages in thread

* Re: [PATCH 2/3] components: multiple components for a device
  2019-02-07 22:40         ` Daniel Vetter
@ 2019-02-07 22:48           ` Rafael J. Wysocki
  0 siblings, 0 replies; 121+ messages in thread
From: Rafael J. Wysocki @ 2019-02-07 22:48 UTC (permalink / raw)
  To: Daniel Vetter
  Cc: Greg Kroah-Hartman, Intel Graphics Development,
	Rafael J. Wysocki, Takashi Iwai, DRI Development,
	Jaroslav Kysela, Rodrigo Vivi, Daniel Vetter, Russell King

On Thu, Feb 7, 2019 at 11:40 PM Daniel Vetter <daniel@ffwll.ch> wrote:
>
> On Wed, Feb 06, 2019 at 11:57:04PM +0100, Rafael J. Wysocki wrote:
> > ) On Wed, Feb 6, 2019 at 5:46 PM Daniel Vetter <daniel.vetter@ffwll.ch> wrote:
> > >
> > > Component framework is extended to support multiple components for
> > > a struct device. These will be matched with different masters based on
> > > its sub component value.
> > >
> > > We are introducing this, as I915 needs two different components
> > > with different subcomponent value, which will be matched to two
> > > different component masters(Audio and HDCP) based on the subcomponent
> > > values.
> > >
> > > v2: Add documenation.
> > >
> > > v3: Rebase on top of updated documenation.
> > >
> > > Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch> (v1 code)
> > > Signed-off-by: Ramalingam C <ramalingam.c@intel.com> (v1 commit message)
> > > Cc: Ramalingam C <ramalingam.c@intel.com>
> > > Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
> > > Cc: Russell King <rmk+kernel@arm.linux.org.uk>
> > > Cc: Rafael J. Wysocki <rafael@kernel.org>
> > > Cc: Jaroslav Kysela <perex@perex.cz>
> > > Cc: Takashi Iwai <tiwai@suse.com>
> > > Cc: Rodrigo Vivi <rodrigo.vivi@intel.com>
> > > Cc: Jani Nikula <jani.nikula@linux.intel.com>
> > > Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
> > > ---
> > >  drivers/base/component.c  | 160 +++++++++++++++++++++++++++++---------
> > >  include/linux/component.h |   9 ++-
> > >  2 files changed, 129 insertions(+), 40 deletions(-)
> > >
> > > diff --git a/drivers/base/component.c b/drivers/base/component.c
> > > index f34d4b784709..68ccd5a0d5d6 100644
> > > --- a/drivers/base/component.c
> > > +++ b/drivers/base/component.c
> > > @@ -47,6 +47,7 @@ struct component;
> > >  struct component_match_array {
> > >         void *data;
> > >         int (*compare)(struct device *, void *);
> > > +       int (*compare_typed)(struct device *, int, void *);
> > >         void (*release)(struct device *, void *);
> > >         struct component *component;
> > >         bool duplicate;
> > > @@ -74,6 +75,7 @@ struct component {
> > >         bool bound;
> > >
> > >         const struct component_ops *ops;
> > > +       int subcomponent;
> > >         struct device *dev;
> > >  };
> > >
> > > @@ -158,7 +160,7 @@ static struct master *__master_find(struct device *dev,
> > >  }
> > >
> > >  static struct component *find_component(struct master *master,
> > > -       int (*compare)(struct device *, void *), void *compare_data)
> > > +       struct component_match_array *mc)
> > >  {
> > >         struct component *c;
> > >
> > > @@ -166,8 +168,13 @@ static struct component *find_component(struct master *master,
> > >                 if (c->master && c->master != master)
> > >                         continue;
> > >
> > > -               if (compare(c->dev, compare_data))
> > > +               if (mc->compare_typed) {
> > > +                       if (mc->compare_typed(c->dev, c->subcomponent,
> > > +                                             mc->data))
> >
> > This line break looks kind of weird to me,
> >
> > > +                               return c;
> > > +               } else if (mc->compare(c->dev, mc->data)) {
> > >                         return c;
> > > +               }
> >
> > Also, why don't you do
> >
> > if (mc->compare(c->dev, mc->data) || (mc->compare_typed &&
> >     mc->compare_typed(c->dev, c->subcomponent, mc->data)))
> >         return c;
> >
> > The only difference is that ->compare() will run first and if it finds
> > a match, c will be returned right away.  Does it matter?
>
> Tried it, yes it does matter: We have either ->compare or ->compare_typed,

Well, that's not obvious. :-)
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

end of thread, other threads:[~2019-02-07 22:48 UTC | newest]

Thread overview: 121+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-01-31  6:59 [PATCH v10 00/40] drm/i915: Implement HDCP2.2 Ramalingam C
2019-01-31  6:59 ` [PATCH v10 01/40] components: multiple components for a device Ramalingam C
2019-01-31  7:50   ` Greg Kroah-Hartman
2019-01-31  8:00     ` Daniel Vetter
2019-01-31  8:12       ` Greg Kroah-Hartman
2019-01-31  8:39         ` Daniel Vetter
2019-01-31 14:46   ` [PATCH 1/2] component: Add documentation Daniel Vetter
2019-01-31 14:46     ` [PATCH 2/2] components: multiple components for a device Daniel Vetter
2019-02-04 16:00       ` Daniel Vetter
2019-02-04 16:00         ` Daniel Vetter
2019-02-05 10:47     ` [PATCH 1/2] component: Add documentation Rafael J. Wysocki
2019-02-05 16:20       ` Daniel Vetter
2019-02-05 16:21     ` [PATCH] " Daniel Vetter
2019-02-05 16:49       ` Russell King - ARM Linux admin
2019-02-05 18:45         ` Daniel Vetter
2019-02-06 16:45   ` [PATCH 1/3] " Daniel Vetter
2019-02-06 16:45     ` [PATCH 2/3] components: multiple components for a device Daniel Vetter
2019-02-06 22:57       ` Rafael J. Wysocki
2019-02-07 22:35         ` Daniel Vetter
2019-02-07 22:40         ` Daniel Vetter
2019-02-07 22:48           ` Rafael J. Wysocki
2019-02-06 16:45     ` [PATCH 3/3] drm/doc: document recommended component helper usage Daniel Vetter
2019-02-06 16:47     ` [PATCH] component: Add documentation Daniel Vetter
2019-02-06 16:47       ` Daniel Vetter
2019-02-06 22:01       ` Rafael J. Wysocki
2019-01-31  6:59 ` [PATCH v10 02/40] i915/snd_hdac: I915 subcomponent for the snd_hdac Ramalingam C
2019-02-04 15:00   ` Daniel Vetter
2019-02-04 15:09     ` Takashi Iwai
2019-01-31  6:59 ` [PATCH v10 03/40] drm/i915: Gathering the HDCP1.4 routines together Ramalingam C
2019-02-04 13:11   ` Shankar, Uma
2019-01-31  6:59 ` [PATCH v10 04/40] drm: header for i915 - MEI_HDCP interface Ramalingam C
2019-02-04 13:24   ` Shankar, Uma
2019-01-31  6:59 ` [PATCH v10 05/40] drm/i915: Initialize HDCP2.2 Ramalingam C
2019-02-04 13:29   ` Shankar, Uma
2019-01-31  6:59 ` [PATCH v10 06/40] drm/i915: MEI interface definition Ramalingam C
2019-01-31  8:17   ` Daniel Vetter
2019-01-31 13:39     ` C, Ramalingam
2019-01-31  6:59 ` [PATCH v10 07/40] drm/i915: hdcp1.4 CP_IRQ handling and SW encryption tracking Ramalingam C
2019-01-31  7:56   ` Daniel Vetter
2019-01-31 13:41     ` C, Ramalingam
2019-02-04 14:09   ` Shankar, Uma
2019-02-04 14:43     ` C, Ramalingam
2019-01-31  6:59 ` [PATCH v10 08/40] drm/i915: Enable and Disable of HDCP2.2 Ramalingam C
2019-02-04 14:17   ` Shankar, Uma
2019-01-31  6:59 ` [PATCH v10 09/40] drm/i915: Implement HDCP2.2 receiver authentication Ramalingam C
2019-02-04 14:20   ` Shankar, Uma
2019-01-31  6:59 ` [PATCH v10 10/40] drm: helper functions for hdcp2 seq_num to from u32 Ramalingam C
2019-02-04 14:20   ` Shankar, Uma
2019-01-31  6:59 ` [PATCH v10 11/40] drm/i915: Implement HDCP2.2 repeater authentication Ramalingam C
2019-02-04 14:21   ` Shankar, Uma
2019-01-31  6:59 ` [PATCH v10 12/40] drm: HDCP2.2 link check period Ramalingam C
2019-02-04 14:24   ` Shankar, Uma
2019-02-04 14:50     ` C, Ramalingam
2019-01-31  6:59 ` [PATCH v10 13/40] drm/i915: Implement HDCP2.2 link integrity check Ramalingam C
2019-02-04 14:28   ` Shankar, Uma
2019-01-31  6:59 ` [PATCH v10 14/40] drm/i915: Handle HDCP2.2 downstream topology change Ramalingam C
2019-02-04 14:31   ` Shankar, Uma
2019-01-31  6:59 ` [PATCH v10 15/40] drm: removing the DP Errata msg and its msg id Ramalingam C
2019-01-31  8:02   ` Daniel Vetter
2019-02-04 14:35   ` Shankar, Uma
2019-01-31  6:59 ` [PATCH v10 16/40] drm/i915: Implement the HDCP2.2 support for DP Ramalingam C
2019-02-04 16:02   ` Shankar, Uma
2019-01-31  6:59 ` [PATCH v10 17/40] drm/i915: Implement the HDCP2.2 support for HDMI Ramalingam C
2019-02-04 16:03   ` Shankar, Uma
2019-01-31  6:59 ` [PATCH v10 18/40] drm/i915: CP_IRQ handling for DP HDCP2.2 msgs Ramalingam C
2019-01-31  8:08   ` Daniel Vetter
2019-01-31 12:50     ` Daniel Vetter
2019-01-31  6:59 ` [PATCH v10 19/40] drm/i915: Add HDCP2.2 support for DP connectors Ramalingam C
2019-02-04 16:08   ` Winkler, Tomas
2019-01-31  6:59 ` [PATCH v10 20/40] drm/i915: Add HDCP2.2 support for HDMI connectors Ramalingam C
2019-02-04 16:04   ` Winkler, Tomas
2019-02-04 16:11     ` C, Ramalingam
2019-01-31  6:59 ` [PATCH v10 21/40] mei: bus: whitelist hdcp client Ramalingam C
2019-01-31  6:59 ` [PATCH v10 22/40] mei: bus: export to_mei_cl_device for mei client device drivers Ramalingam C
2019-01-31  6:59 ` [PATCH v10 23/40] misc/mei/hdcp: Client driver for HDCP application Ramalingam C
2019-02-05 12:33   ` Winkler, Tomas
2019-01-31  6:59 ` [PATCH v10 24/40] misc/mei/hdcp: Define ME FW interface for HDCP2.2 Ramalingam C
2019-02-04 16:07   ` Shankar, Uma
2019-02-05 13:01     ` Winkler, Tomas
2019-01-31  6:59 ` [PATCH v10 25/40] misc/mei/hdcp: Initiate Wired HDCP2.2 Tx Session Ramalingam C
2019-02-04 16:09   ` Shankar, Uma
2019-02-05 13:09     ` Winkler, Tomas
2019-02-05 14:13       ` C, Ramalingam
2019-02-06 10:27       ` Winkler, Tomas
2019-02-06 21:14         ` C, Ramalingam
2019-01-31  6:59 ` [PATCH v10 26/40] misc/mei/hdcp: Verify Receiver Cert and prepare km Ramalingam C
2019-02-04 16:10   ` Shankar, Uma
2019-02-06  8:28     ` Winkler, Tomas
2019-01-31  6:59 ` [PATCH v10 27/40] misc/mei/hdcp: Verify H_prime Ramalingam C
2019-02-04 16:11   ` Shankar, Uma
2019-01-31  6:59 ` [PATCH v10 28/40] misc/mei/hdcp: Store the HDCP Pairing info Ramalingam C
2019-02-04 16:13   ` Shankar, Uma
2019-01-31  6:59 ` [PATCH v10 29/40] misc/mei/hdcp: Initiate Locality check Ramalingam C
2019-02-04 16:16   ` Shankar, Uma
2019-01-31  6:59 ` [PATCH v10 30/40] misc/mei/hdcp: Verify L_prime Ramalingam C
2019-02-04 16:16   ` Shankar, Uma
2019-01-31  6:59 ` [PATCH v10 31/40] misc/mei/hdcp: Prepare Session Key Ramalingam C
2019-02-04 16:17   ` Shankar, Uma
2019-01-31  6:59 ` [PATCH v10 32/40] misc/mei/hdcp: Repeater topology verification and ack Ramalingam C
2019-02-04 16:17   ` Shankar, Uma
2019-01-31  6:59 ` [PATCH v10 33/40] misc/mei/hdcp: Verify M_prime Ramalingam C
2019-02-04 16:18   ` Shankar, Uma
2019-01-31  6:59 ` [PATCH v10 34/40] misc/mei/hdcp: Enabling the HDCP authentication Ramalingam C
2019-02-04 16:19   ` Shankar, Uma
2019-01-31  6:59 ` [PATCH v10 35/40] misc/mei/hdcp: Closing wired HDCP2.2 Tx Session Ramalingam C
2019-02-04 16:20   ` Shankar, Uma
2019-01-31  6:59 ` [PATCH v10 36/40] misc/mei/hdcp: Component framework for I915 Interface Ramalingam C
2019-01-31  8:23   ` Daniel Vetter
2019-02-04 16:27   ` Shankar, Uma
2019-01-31  6:59 ` [PATCH v10 37/40] drm/i915: Commit CP without modeset Ramalingam C
2019-01-31  8:32   ` Daniel Vetter
2019-02-04  8:39     ` C, Ramalingam
2019-01-31  6:59 ` [PATCH v10 38/40] drm/i915: Fix KBL HDCP2.2 encrypt status signalling Ramalingam C
2019-02-04 15:32   ` C, Ramalingam
2019-02-05  8:54     ` Daniel Vetter
2019-02-04 16:35   ` Shankar, Uma
2019-01-31  6:59 ` [PATCH v10 39/40] FOR_TEST: i915/Kconfig: Select mei_hdcp by I915 Ramalingam C
2019-01-31  6:59 ` [PATCH v10 40/40] FOR_TESTING_ONLY: debugfs: Excluding the LSPCon for HDCP1.4 Ramalingam C
2019-01-31  7:38 ` ✗ Fi.CI.CHECKPATCH: warning for drm/i915: Implement HDCP2.2 (rev13) Patchwork
2019-01-31  8:16 ` ✓ Fi.CI.BAT: success " Patchwork
2019-01-31 18:42 ` ✓ Fi.CI.IGT: " 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.