Discussion:
[Intel-gfx] [PATCH v3 00/40] drm/i915: Implement HDCP2.2
Ramalingam C
2018-04-03 13:57:13 UTC
Permalink
The sequence for HDCP2.2 authentication and encryption is implemented
in I915. 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.

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 v3:
- Few patches are squashed in mei related code [Tomas]
- Kernel Notifier is used for sync between mei_hdcp driver and I915 [Tomas]
- mei_cl_device is passed to mei_hdcp driver as an arg [Tomas]
- dropped double check of cl_device [Tomas]
- Used the Dual Licenses and SPDX Notation for new files and drivers [Tomas]
- wait_queue is used instead of completion for CP_IRQ [Chris Wilson]
- mei_cl_device reference is removed from i915_dev_private
- notification of mei_cldev change is handled for each connector

Ramalingam C (39):
drm: hdcp2.2 authentication msg definitions
drm: HDMI and DP specific HDCP2.2 defines
misc/mei/hdcp: Client driver for HDCP application
misc/mei/hdcp: Notifier chain for mei cldev state change
misc/mei/hdcp: Define ME FW interface for HDCP2.2
linux/mei: Header for mei_hdcp driver interface
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 verifcation and ack
misc/mei/hdcp: Verify M_prime
misc/mei/hdcp: Enabling the HDCP authentication
misc/mei/hdcp: Closing wired HDCP2.2 Tx Session
drm/i915: wrapping all hdcp var into intel_hdcp
drm/i915: Define HDCP2.2 related variables
drm/i915: Define Intel HDCP2.2 registers
drm/i915: Wrappers for mei HDCP2.2 services
drm/i915: Implement HDCP2.2 receiver authentication
drm/i915: Implement HDCP2.2 repeater authentication
drm/i915: Enable and Disable HDCP2.2 port encryption
drm/i915: Implement HDCP2.2 En/Dis-able
drm/i915: Implement HDCP2.2 link integrity check
drm/i915: Handle HDCP2.2 downstream topology change
drm/i915: Pullout the bksv read and validation
drm/i915: Initialize HDCP2.2 and its MEI interface
drm/i915: Schedule hdcp_check_link in _intel_hdcp_enable
drm/i915: Enable superior HDCP ver that is capable
drm/i915: Enable HDCP1.4 incase of HDCP2.2 failure
drm/i915: hdcp_check_link only on CP_IRQ
drm/i915: Check HDCP 1.4 and 2.2 link on CP_IRQ
drm/i915: Implement gmbus burst read
drm/i915: Implement the HDCP2.2 support for DP
drm/i915: Implement the HDCP2.2 support for HDMI
drm/i915: Add HDCP2.2 support for DP connectors
drm/i915: Add HDCP2.2 support for HDMI connectors

Tomas Winkler (1):
mei: bus: whitelist hdcp client

drivers/gpu/drm/i915/i915_drv.h | 2 +
drivers/gpu/drm/i915/i915_reg.h | 35 ++
drivers/gpu/drm/i915/intel_display.c | 7 +-
drivers/gpu/drm/i915/intel_dp.c | 364 +++++++++++-
drivers/gpu/drm/i915/intel_drv.h | 88 ++-
drivers/gpu/drm/i915/intel_hdcp.c | 1090 ++++++++++++++++++++++++++++++++--
drivers/gpu/drm/i915/intel_hdmi.c | 206 ++++++-
drivers/gpu/drm/i915/intel_i2c.c | 124 +++-
drivers/misc/mei/Kconfig | 6 +
drivers/misc/mei/Makefile | 2 +
drivers/misc/mei/bus-fixup.c | 16 +
drivers/misc/mei/hdcp/Makefile | 6 +
drivers/misc/mei/hdcp/mei_hdcp.c | 809 +++++++++++++++++++++++++
drivers/misc/mei/hdcp/mei_hdcp.h | 415 +++++++++++++
include/drm/drm_dp_helper.h | 54 ++
include/drm/drm_hdcp.h | 220 +++++++
include/linux/mei_hdcp.h | 227 +++++++
17 files changed, 3573 insertions(+), 98 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/linux/mei_hdcp.h
--
2.7.4
Ramalingam C
2018-04-03 13:57:14 UTC
Permalink
This patch defines the hdcp2.2 protocol messages for the
HDCP2.2 authentication.

v2:
bit_fields are removed. Instead bitmasking used. [Tomas and Jani]
prefix HDCP_2_2_ is added to the macros. [Tomas]
v3:
No Changes.

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

diff --git a/include/drm/drm_hdcp.h b/include/drm/drm_hdcp.h
index 562fa7df2637..5e0a5ed1a08e 100644
--- a/include/drm/drm_hdcp.h
+++ b/include/drm/drm_hdcp.h
@@ -38,4 +38,187 @@
#define DRM_HDCP_DDC_BSTATUS 0x41
#define DRM_HDCP_DDC_KSV_FIFO 0x43

+#define DRM_HDCP_1_4_SRM_ID 0x8
+#define DRM_HDCP_1_4_VRL_LENGTH_SIZE 3
+#define DRM_HDCP_1_4_DCP_SIG_SIZE 40
+
+/**
+ * Protocol message definition for HDCP2.2 specification
+ */
+
+#define HDCP_STREAM_TYPE0 0x00
+#define HDCP_STREAM_TYPE1 0x01
+
+/* HDCP2.2 Msg IDs */
+#define HDCP_2_2_NULL_MSG 1
+#define HDCP_2_2_AKE_INIT 2
+#define HDCP_2_2_AKE_SEND_CERT 3
+#define HDCP_2_2_AKE_NO_STORED_KM 4
+#define HDCP_2_2_AKE_STORED_KM 5
+#define HDCP_2_2_AKE_SEND_HPRIME 7
+#define HDCP_2_2_AKE_SEND_PARING_INFO 8
+#define HDCP_2_2_LC_INIT 9
+#define HDCP_2_2_LC_SEND_LPRIME 10
+#define HDCP_2_2_SKE_SEND_EKS 11
+#define HDCP_2_2_REP_SEND_RECVID_LIST 12
+#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
+
+#define HDCP_2_2_K_PUB_RX_MOD_N_LEN 128
+#define HDCP_2_2_K_PUB_RX_EXP_E_LEN 3
+#define HDCP_2_2_K_PUB_RX_LEN (HDCP_2_2_K_PUB_RX_MOD_N_LEN + \
+ HDCP_2_2_K_PUB_RX_EXP_E_LEN)
+
+#define HDCP_2_2_DCP_LLC_SIG_LEN 384
+
+#define HDCP_2_2_E_KPUB_KM_LEN 128
+#define HDCP_2_2_E_KH_KM_M_LEN (16 + 16)
+#define HDCP_2_2_H_PRIME_LEN 32
+#define HDCP_2_2_E_KH_KM_LEN 16
+#define HDCP_2_2_RN_LEN 8
+#define HDCP_2_2_L_PRIME_LEN 32
+#define HDCP_2_2_E_DKEY_KS_LEN 16
+#define HDCP_2_2_RIV_LEN 8
+#define HDCP_2_2_SEQ_NUM_LEN 3
+#define HDCP_2_2_LPRIME_HALF_LEN (HDCP_2_2_L_PRIME_LEN / 2)
+#define HDCP_2_2_RECEIVER_ID_LEN DRM_HDCP_KSV_LEN
+#define HDCP_2_2_MAX_DEVICE_COUNT 31
+#define HDCP_2_2_RECEIVER_IDS_MAX_LEN (HDCP_2_2_RECEIVER_ID_LEN * \
+ HDCP_2_2_MAX_DEVICE_COUNT)
+#define HDCP_2_2_MPRIME_LEN 32
+
+/**
+ * TODO: This has to be changed for DP MST, as multiple stream on
+ * same port is possible.
+ * For HDCP2.2 on HDMI and DP SST this value is always 1.
+ */
+#define HDCP_2_2_MAX_CONTENT_STREAMS_CNT 1
+#define HDCP_2_2_TXCAP_MASK_LEN 2
+#define HDCP_2_2_RXCAPS_LEN 3
+#define HDCP_2_2_RX_REPEATER(x) (x & BIT(0))
+#define HDCP_2_2_DP_HDCP_CAPABLE(x) (x & BIT(1))
+#define HDCP_2_2_RXINFO_LEN 2
+
+/* HDCP1.x compliant device in downstream */
+#define HDCP_2_2_HDCP1_DEVICE_CONNECTED(x) (x & BIT(0))
+
+/* HDCP2.0 Compliant repeater in downstream */
+#define HDCP_2_2_HDCP_2_0_REP_CONNECTED(x) (x & BIT(1))
+#define HDCP_2_2_MAX_CASCADE_EXCEEDED(x) (x & BIT(2))
+#define HDCP_2_2_MAX_DEVS_EXCEEDED(x) (x & BIT(3))
+#define HDCP_2_2_DEV_COUNT_LO(x) ((x & (0xF << 4)) >> 4)
+#define HDCP_2_2_DEV_COUNT_HI(x) (x & BIT(0))
+#define HDCP_2_2_DEPTH(x) ((x & (0x7 << 1)) >> 1)
+
+struct hdcp2_cert_rx {
+ uint8_t receiver_id[HDCP_2_2_RECEIVER_ID_LEN];
+ uint8_t kpub_rx[HDCP_2_2_K_PUB_RX_LEN];
+ uint8_t reserved[2];
+ uint8_t dcp_signature[HDCP_2_2_DCP_LLC_SIG_LEN];
+} __packed;
+
+struct hdcp2_streamid_type {
+ uint8_t stream_id;
+ uint8_t stream_type;
+} __packed;
+
+/**
+ * The TxCaps field specified in the HDCP HDMI, DP specs
+ * This field is big endian as specified in the errata.
+ */
+struct hdcp2_tx_caps {
+ /* Transmitter must set this to 0x2 */
+ uint8_t version;
+
+ /* Reserved for HDCP and DP Spec. Read as Zero */
+ uint8_t tx_cap_mask[HDCP_2_2_TXCAP_MASK_LEN];
+} __packed;
+
+/*
+ * Main structures for HDCP2.2 protocol communication
+ */
+struct hdcp2_ake_init {
+ uint8_t msg_id;
+ uint8_t r_tx[HDCP_2_2_RTX_LEN];
+ struct hdcp2_tx_caps tx_caps;
+} __packed;
+
+struct hdcp2_ake_send_cert {
+ uint8_t msg_id;
+ struct hdcp2_cert_rx cert_rx;
+ uint8_t r_rx[HDCP_2_2_RRX_LEN];
+ uint8_t rx_caps[HDCP_2_2_RXCAPS_LEN];
+} __packed;
+
+struct hdcp2_ake_no_stored_km {
+ uint8_t msg_id;
+ uint8_t e_kpub_km[HDCP_2_2_E_KPUB_KM_LEN];
+} __packed;
+
+struct hdcp2_ake_stored_km {
+ uint8_t msg_id;
+ uint8_t e_kh_km_m[HDCP_2_2_E_KH_KM_M_LEN];
+} __packed;
+
+struct hdcp2_ake_send_hprime {
+ uint8_t msg_id;
+ uint8_t h_prime[HDCP_2_2_H_PRIME_LEN];
+} __packed;
+
+struct hdcp2_ake_send_pairing_info {
+ uint8_t msg_id;
+ uint8_t e_kh_km[HDCP_2_2_E_KH_KM_LEN];
+} __packed;
+
+struct hdcp2_lc_init {
+ uint8_t msg_id;
+ uint8_t r_n[HDCP_2_2_RN_LEN];
+} __packed;
+
+struct hdcp2_lc_send_lprime {
+ uint8_t msg_id;
+ uint8_t l_prime[HDCP_2_2_L_PRIME_LEN];
+} __packed;
+
+struct hdcp2_ske_send_eks {
+ uint8_t msg_id;
+ uint8_t e_dkey_ks[HDCP_2_2_E_DKEY_KS_LEN];
+ uint8_t riv[HDCP_2_2_RIV_LEN];
+} __packed;
+
+struct hdcp2_rep_send_receiverid_list {
+ uint8_t msg_id;
+ uint8_t rx_info[HDCP_2_2_RXINFO_LEN];
+ uint8_t seq_num_v[HDCP_2_2_SEQ_NUM_LEN];
+ uint8_t v_prime[HDCP_2_2_LPRIME_HALF_LEN];
+ uint8_t receiver_ids[HDCP_2_2_RECEIVER_IDS_MAX_LEN];
+} __packed;
+
+struct hdcp2_rep_send_ack {
+ uint8_t msg_id;
+ uint8_t v[HDCP_2_2_LPRIME_HALF_LEN];
+} __packed;
+
+struct hdcp2_rep_stream_manage {
+ uint8_t msg_id;
+ uint8_t seq_num_m[HDCP_2_2_SEQ_NUM_LEN];
+ __be16 k;
+ struct hdcp2_streamid_type streams[HDCP_2_2_MAX_CONTENT_STREAMS_CNT];
+} __packed;
+
+struct hdcp2_rep_stream_ready {
+ uint8_t msg_id;
+ uint8_t m_prime[HDCP_2_2_MPRIME_LEN];
+} __packed;
+
+struct hdcp2_dp_errata_stream_type {
+ uint8_t msg_id;
+ uint8_t stream_type;
+} __packed;
+
#endif
--
2.7.4
Shankar, Uma
2018-05-09 10:01:35 UTC
Permalink
-----Original Message-----
Ramalingam C
Sent: Tuesday, April 3, 2018 7:27 PM
Subject: [Intel-gfx] [PATCH v3 01/40] drm: hdcp2.2 authentication msg definitions
This patch defines the hdcp2.2 protocol messages for the
Drop redundant "the" and one of the hdcp2.2. Not required.
HDCP2.2 authentication.
bit_fields are removed. Instead bitmasking used. [Tomas and Jani]
prefix HDCP_2_2_ is added to the macros. [Tomas]
No Changes.
---
include/drm/drm_hdcp.h | 183
+++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 183 insertions(+)
diff --git a/include/drm/drm_hdcp.h b/include/drm/drm_hdcp.h index
562fa7df2637..5e0a5ed1a08e 100644
--- a/include/drm/drm_hdcp.h
+++ b/include/drm/drm_hdcp.h
@@ -38,4 +38,187 @@
#define DRM_HDCP_DDC_BSTATUS 0x41
#define DRM_HDCP_DDC_KSV_FIFO 0x43
+#define DRM_HDCP_1_4_SRM_ID 0x8
+#define DRM_HDCP_1_4_VRL_LENGTH_SIZE 3
+#define DRM_HDCP_1_4_DCP_SIG_SIZE 40
+
+/**
+ * Protocol message definition for HDCP2.2 specification */
Multi Line comment style not needed here.
+
+#define HDCP_STREAM_TYPE0 0x00
+#define HDCP_STREAM_TYPE1 0x01
+
+/* HDCP2.2 Msg IDs */
+#define HDCP_2_2_NULL_MSG 1
+#define HDCP_2_2_AKE_INIT 2
+#define HDCP_2_2_AKE_SEND_CERT 3
+#define HDCP_2_2_AKE_NO_STORED_KM 4
+#define HDCP_2_2_AKE_STORED_KM 5
+#define HDCP_2_2_AKE_SEND_HPRIME 7
+#define HDCP_2_2_AKE_SEND_PARING_INFO 8
Typo in Pairing
+#define HDCP_2_2_LC_INIT 9
+#define HDCP_2_2_LC_SEND_LPRIME 10
+#define HDCP_2_2_SKE_SEND_EKS 11
+#define HDCP_2_2_REP_SEND_RECVID_LIST 12
+#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
+
+#define HDCP_2_2_K_PUB_RX_MOD_N_LEN 128
+#define HDCP_2_2_K_PUB_RX_EXP_E_LEN 3
+#define HDCP_2_2_K_PUB_RX_LEN
(HDCP_2_2_K_PUB_RX_MOD_N_LEN + \
+
HDCP_2_2_K_PUB_RX_EXP_E_LEN)
+
+#define HDCP_2_2_DCP_LLC_SIG_LEN 384
+
+#define HDCP_2_2_E_KPUB_KM_LEN 128
+#define HDCP_2_2_E_KH_KM_M_LEN (16 + 16)
+#define HDCP_2_2_H_PRIME_LEN 32
+#define HDCP_2_2_E_KH_KM_LEN 16
+#define HDCP_2_2_RN_LEN 8
+#define HDCP_2_2_L_PRIME_LEN 32
+#define HDCP_2_2_E_DKEY_KS_LEN 16
+#define HDCP_2_2_RIV_LEN 8
+#define HDCP_2_2_SEQ_NUM_LEN 3
+#define HDCP_2_2_LPRIME_HALF_LEN (HDCP_2_2_L_PRIME_LEN / 2)
+#define HDCP_2_2_RECEIVER_ID_LEN DRM_HDCP_KSV_LEN
+#define HDCP_2_2_MAX_DEVICE_COUNT 31
+#define HDCP_2_2_RECEIVER_IDS_MAX_LEN
(HDCP_2_2_RECEIVER_ID_LEN * \
+
HDCP_2_2_MAX_DEVICE_COUNT)
+#define HDCP_2_2_MPRIME_LEN 32
+
+/**
Remove an extra "*".
+ * TODO: This has to be changed for DP MST, as multiple stream on
+ * same port is possible.
+ * For HDCP2.2 on HDMI and DP SST this value is always 1.
+ */
+#define HDCP_2_2_MAX_CONTENT_STREAMS_CNT 1
+#define HDCP_2_2_TXCAP_MASK_LEN 2
+#define HDCP_2_2_RXCAPS_LEN 3
+#define HDCP_2_2_RX_REPEATER(x) (x & BIT(0))
+#define HDCP_2_2_DP_HDCP_CAPABLE(x) (x & BIT(1))
+#define HDCP_2_2_RXINFO_LEN 2
+
+/* HDCP1.x compliant device in downstream */
+#define HDCP_2_2_HDCP1_DEVICE_CONNECTED(x) (x & BIT(0))
+
+/* HDCP2.0 Compliant repeater in downstream */
+#define HDCP_2_2_HDCP_2_0_REP_CONNECTED(x) (x & BIT(1))
+#define HDCP_2_2_MAX_CASCADE_EXCEEDED(x) (x & BIT(2))
+#define HDCP_2_2_MAX_DEVS_EXCEEDED(x) (x & BIT(3))
+#define HDCP_2_2_DEV_COUNT_LO(x) ((x & (0xF << 4)) >> 4)
+#define HDCP_2_2_DEV_COUNT_HI(x) (x & BIT(0))
As per 2.2 spec this is a 5 bit field and no mention of HI and LO is there for dev count.
A comment explaining why this masking style is chosen will be helpful since it doesn't
match exactly with spec.
+#define HDCP_2_2_DEPTH(x) ((x & (0x7 << 1)) >> 1)
Same here, may be add a generic comment explaining the logic for
all the relevant macro definitions.
+
+struct hdcp2_cert_rx {
+ uint8_t receiver_id[HDCP_2_2_RECEIVER_ID_LEN];
+ uint8_t kpub_rx[HDCP_2_2_K_PUB_RX_LEN];
+ uint8_t reserved[2];
+ uint8_t dcp_signature[HDCP_2_2_DCP_LLC_SIG_LEN];
+} __packed;
+
+struct hdcp2_streamid_type {
+ uint8_t stream_id;
+ uint8_t stream_type;
+} __packed;
+
+/**
Drop the extra "*".
+ * The TxCaps field specified in the HDCP HDMI, DP specs
+ * This field is big endian as specified in the errata.
+ */
+struct hdcp2_tx_caps {
+ /* Transmitter must set this to 0x2 */
+ uint8_t version;
+
+ /* Reserved for HDCP and DP Spec. Read as Zero */
+ uint8_t tx_cap_mask[HDCP_2_2_TXCAP_MASK_LEN];
Drop extra tabs here.
+} __packed;
+
+/*
+ * Main structures for HDCP2.2 protocol communication */ struct
No need of multi-line comment style.
+hdcp2_ake_init {
+ uint8_t msg_id;
+ uint8_t r_tx[HDCP_2_2_RTX_LEN];
+ struct hdcp2_tx_caps tx_caps;
+} __packed;
+
+struct hdcp2_ake_send_cert {
+ uint8_t msg_id;
+ struct hdcp2_cert_rx cert_rx;
+ uint8_t r_rx[HDCP_2_2_RRX_LEN];
+ uint8_t rx_caps[HDCP_2_2_RXCAPS_LEN];
+} __packed;
+
+struct hdcp2_ake_no_stored_km {
+ uint8_t msg_id;
+ uint8_t e_kpub_km[HDCP_2_2_E_KPUB_KM_LEN];
Drop extra tabs. Do it universally in all structure definitions.
+} __packed;
+
+struct hdcp2_ake_stored_km {
+ uint8_t msg_id;
+ uint8_t e_kh_km_m[HDCP_2_2_E_KH_KM_M_LEN];
+} __packed;
+
+struct hdcp2_ake_send_hprime {
+ uint8_t msg_id;
+ uint8_t h_prime[HDCP_2_2_H_PRIME_LEN];
+} __packed;
+
+struct hdcp2_ake_send_pairing_info {
+ uint8_t msg_id;
+ uint8_t e_kh_km[HDCP_2_2_E_KH_KM_LEN];
+} __packed;
+
+struct hdcp2_lc_init {
+ uint8_t msg_id;
+ uint8_t r_n[HDCP_2_2_RN_LEN];
+} __packed;
+
+struct hdcp2_lc_send_lprime {
+ uint8_t msg_id;
+ uint8_t l_prime[HDCP_2_2_L_PRIME_LEN];
+} __packed;
+
+struct hdcp2_ske_send_eks {
+ uint8_t msg_id;
+ uint8_t e_dkey_ks[HDCP_2_2_E_DKEY_KS_LEN];
+ uint8_t riv[HDCP_2_2_RIV_LEN];
+} __packed;
+
+struct hdcp2_rep_send_receiverid_list {
+ uint8_t msg_id;
+ uint8_t rx_info[HDCP_2_2_RXINFO_LEN];
+ uint8_t seq_num_v[HDCP_2_2_SEQ_NUM_LEN];
+ uint8_t v_prime[HDCP_2_2_LPRIME_HALF_LEN];
+ uint8_t
receiver_ids[HDCP_2_2_RECEIVER_IDS_MAX_LEN];
+} __packed;
+
+struct hdcp2_rep_send_ack {
+ uint8_t msg_id;
+ uint8_t v[HDCP_2_2_LPRIME_HALF_LEN];
+} __packed;
+
+struct hdcp2_rep_stream_manage {
+ uint8_t msg_id;
+ uint8_t seq_num_m[HDCP_2_2_SEQ_NUM_LEN];
+ __be16 k;
+ struct hdcp2_streamid_type
streams[HDCP_2_2_MAX_CONTENT_STREAMS_CNT];
+} __packed;
+
+struct hdcp2_rep_stream_ready {
+ uint8_t msg_id;
+ uint8_t m_prime[HDCP_2_2_MPRIME_LEN];
+} __packed;
+
+struct hdcp2_dp_errata_stream_type {
+ uint8_t msg_id;
+ uint8_t stream_type;
+} __packed;
+
#endif
--
2.7.4
_______________________________________________
Intel-gfx mailing list
https://lists.freedesktop.org/mailman/listinfo/intel-gfx
Ramalingam C
2018-05-14 15:23:53 UTC
Permalink
Thank you for the review comments Uma Shankar!
Post by Shankar, Uma
-----Original Message-----
Ramalingam C
Sent: Tuesday, April 3, 2018 7:27 PM
Subject: [Intel-gfx] [PATCH v3 01/40] drm: hdcp2.2 authentication msg definitions
This patch defines the hdcp2.2 protocol messages for the
Drop redundant "the" and one of the hdcp2.2. Not required.
ok
Post by Shankar, Uma
HDCP2.2 authentication.
bit_fields are removed. Instead bitmasking used. [Tomas and Jani]
prefix HDCP_2_2_ is added to the macros. [Tomas]
No Changes.
---
include/drm/drm_hdcp.h | 183
+++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 183 insertions(+)
diff --git a/include/drm/drm_hdcp.h b/include/drm/drm_hdcp.h index
562fa7df2637..5e0a5ed1a08e 100644
--- a/include/drm/drm_hdcp.h
+++ b/include/drm/drm_hdcp.h
@@ -38,4 +38,187 @@
#define DRM_HDCP_DDC_BSTATUS 0x41
#define DRM_HDCP_DDC_KSV_FIFO 0x43
+#define DRM_HDCP_1_4_SRM_ID 0x8
+#define DRM_HDCP_1_4_VRL_LENGTH_SIZE 3
+#define DRM_HDCP_1_4_DCP_SIG_SIZE 40
+
+/**
+ * Protocol message definition for HDCP2.2 specification */
Multi Line comment style not needed here.
Ok
Post by Shankar, Uma
+
+#define HDCP_STREAM_TYPE0 0x00
+#define HDCP_STREAM_TYPE1 0x01
+
+/* HDCP2.2 Msg IDs */
+#define HDCP_2_2_NULL_MSG 1
+#define HDCP_2_2_AKE_INIT 2
+#define HDCP_2_2_AKE_SEND_CERT 3
+#define HDCP_2_2_AKE_NO_STORED_KM 4
+#define HDCP_2_2_AKE_STORED_KM 5
+#define HDCP_2_2_AKE_SEND_HPRIME 7
+#define HDCP_2_2_AKE_SEND_PARING_INFO 8
Typo in Pairing
Fixed
Post by Shankar, Uma
+#define HDCP_2_2_LC_INIT 9
+#define HDCP_2_2_LC_SEND_LPRIME 10
+#define HDCP_2_2_SKE_SEND_EKS 11
+#define HDCP_2_2_REP_SEND_RECVID_LIST 12
+#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
+
+#define HDCP_2_2_K_PUB_RX_MOD_N_LEN 128
+#define HDCP_2_2_K_PUB_RX_EXP_E_LEN 3
+#define HDCP_2_2_K_PUB_RX_LEN
(HDCP_2_2_K_PUB_RX_MOD_N_LEN + \
+
HDCP_2_2_K_PUB_RX_EXP_E_LEN)
+
+#define HDCP_2_2_DCP_LLC_SIG_LEN 384
+
+#define HDCP_2_2_E_KPUB_KM_LEN 128
+#define HDCP_2_2_E_KH_KM_M_LEN (16 + 16)
+#define HDCP_2_2_H_PRIME_LEN 32
+#define HDCP_2_2_E_KH_KM_LEN 16
+#define HDCP_2_2_RN_LEN 8
+#define HDCP_2_2_L_PRIME_LEN 32
+#define HDCP_2_2_E_DKEY_KS_LEN 16
+#define HDCP_2_2_RIV_LEN 8
+#define HDCP_2_2_SEQ_NUM_LEN 3
+#define HDCP_2_2_LPRIME_HALF_LEN (HDCP_2_2_L_PRIME_LEN / 2)
+#define HDCP_2_2_RECEIVER_ID_LEN DRM_HDCP_KSV_LEN
+#define HDCP_2_2_MAX_DEVICE_COUNT 31
+#define HDCP_2_2_RECEIVER_IDS_MAX_LEN
(HDCP_2_2_RECEIVER_ID_LEN * \
+
HDCP_2_2_MAX_DEVICE_COUNT)
+#define HDCP_2_2_MPRIME_LEN 32
+
+/**
Remove an extra "*".
+ * TODO: This has to be changed for DP MST, as multiple stream on
+ * same port is possible.
+ * For HDCP2.2 on HDMI and DP SST this value is always 1.
+ */
+#define HDCP_2_2_MAX_CONTENT_STREAMS_CNT 1
+#define HDCP_2_2_TXCAP_MASK_LEN 2
+#define HDCP_2_2_RXCAPS_LEN 3
+#define HDCP_2_2_RX_REPEATER(x) (x & BIT(0))
+#define HDCP_2_2_DP_HDCP_CAPABLE(x) (x & BIT(1))
+#define HDCP_2_2_RXINFO_LEN 2
+
+/* HDCP1.x compliant device in downstream */
+#define HDCP_2_2_HDCP1_DEVICE_CONNECTED(x) (x & BIT(0))
+
+/* HDCP2.0 Compliant repeater in downstream */
+#define HDCP_2_2_HDCP_2_0_REP_CONNECTED(x) (x & BIT(1))
+#define HDCP_2_2_MAX_CASCADE_EXCEEDED(x) (x & BIT(2))
+#define HDCP_2_2_MAX_DEVS_EXCEEDED(x) (x & BIT(3))
+#define HDCP_2_2_DEV_COUNT_LO(x) ((x & (0xF << 4)) >> 4)
+#define HDCP_2_2_DEV_COUNT_HI(x) (x & BIT(0))
As per 2.2 spec this is a 5 bit field and no mention of HI and LO is there for dev count.
A comment explaining why this masking style is chosen will be helpful since it doesn't
match exactly with spec.
dev count is spread across multi byte value. And these macros are processing
the each byte separately. Agreed that a comment would help here.
Post by Shankar, Uma
+#define HDCP_2_2_DEPTH(x) ((x & (0x7 << 1)) >> 1)
Same here, may be add a generic comment explaining the logic for
all the relevant macro definitions.
+
+struct hdcp2_cert_rx {
+ uint8_t receiver_id[HDCP_2_2_RECEIVER_ID_LEN];
+ uint8_t kpub_rx[HDCP_2_2_K_PUB_RX_LEN];
+ uint8_t reserved[2];
+ uint8_t dcp_signature[HDCP_2_2_DCP_LLC_SIG_LEN];
+} __packed;
+
+struct hdcp2_streamid_type {
+ uint8_t stream_id;
+ uint8_t stream_type;
+} __packed;
+
+/**
Drop the extra "*".
Fixed.
Post by Shankar, Uma
+ * The TxCaps field specified in the HDCP HDMI, DP specs
+ * This field is big endian as specified in the errata.
+ */
+struct hdcp2_tx_caps {
+ /* Transmitter must set this to 0x2 */
+ uint8_t version;
+
+ /* Reserved for HDCP and DP Spec. Read as Zero */
+ uint8_t tx_cap_mask[HDCP_2_2_TXCAP_MASK_LEN];
Drop extra tabs here.
Keeping the extra tabs for the uniformity. If it is ok, I would like to
keep it as it is now.
Post by Shankar, Uma
+} __packed;
+
+/*
+ * Main structures for HDCP2.2 protocol communication */ struct
No need of multi-line comment style.
+hdcp2_ake_init {
+ uint8_t msg_id;
+ uint8_t r_tx[HDCP_2_2_RTX_LEN];
+ struct hdcp2_tx_caps tx_caps;
+} __packed;
+
+struct hdcp2_ake_send_cert {
+ uint8_t msg_id;
+ struct hdcp2_cert_rx cert_rx;
+ uint8_t r_rx[HDCP_2_2_RRX_LEN];
+ uint8_t rx_caps[HDCP_2_2_RXCAPS_LEN];
+} __packed;
+
+struct hdcp2_ake_no_stored_km {
+ uint8_t msg_id;
+ uint8_t e_kpub_km[HDCP_2_2_E_KPUB_KM_LEN];
Drop extra tabs. Do it universally in all structure definitions.
+} __packed;
+
+struct hdcp2_ake_stored_km {
+ uint8_t msg_id;
+ uint8_t e_kh_km_m[HDCP_2_2_E_KH_KM_M_LEN];
+} __packed;
+
+struct hdcp2_ake_send_hprime {
+ uint8_t msg_id;
+ uint8_t h_prime[HDCP_2_2_H_PRIME_LEN];
+} __packed;
+
+struct hdcp2_ake_send_pairing_info {
+ uint8_t msg_id;
+ uint8_t e_kh_km[HDCP_2_2_E_KH_KM_LEN];
+} __packed;
+
+struct hdcp2_lc_init {
+ uint8_t msg_id;
+ uint8_t r_n[HDCP_2_2_RN_LEN];
+} __packed;
+
+struct hdcp2_lc_send_lprime {
+ uint8_t msg_id;
+ uint8_t l_prime[HDCP_2_2_L_PRIME_LEN];
+} __packed;
+
+struct hdcp2_ske_send_eks {
+ uint8_t msg_id;
+ uint8_t e_dkey_ks[HDCP_2_2_E_DKEY_KS_LEN];
+ uint8_t riv[HDCP_2_2_RIV_LEN];
+} __packed;
+
+struct hdcp2_rep_send_receiverid_list {
+ uint8_t msg_id;
+ uint8_t rx_info[HDCP_2_2_RXINFO_LEN];
+ uint8_t seq_num_v[HDCP_2_2_SEQ_NUM_LEN];
+ uint8_t v_prime[HDCP_2_2_LPRIME_HALF_LEN];
+ uint8_t
receiver_ids[HDCP_2_2_RECEIVER_IDS_MAX_LEN];
+} __packed;
+
+struct hdcp2_rep_send_ack {
+ uint8_t msg_id;
+ uint8_t v[HDCP_2_2_LPRIME_HALF_LEN];
+} __packed;
+
+struct hdcp2_rep_stream_manage {
+ uint8_t msg_id;
+ uint8_t seq_num_m[HDCP_2_2_SEQ_NUM_LEN];
+ __be16 k;
+ struct hdcp2_streamid_type
streams[HDCP_2_2_MAX_CONTENT_STREAMS_CNT];
+} __packed;
+
+struct hdcp2_rep_stream_ready {
+ uint8_t msg_id;
+ uint8_t m_prime[HDCP_2_2_MPRIME_LEN];
+} __packed;
+
+struct hdcp2_dp_errata_stream_type {
+ uint8_t msg_id;
+ uint8_t stream_type;
+} __packed;
+
#endif
--
2.7.4
_______________________________________________
Intel-gfx mailing list
https://lists.freedesktop.org/mailman/listinfo/intel-gfx
Ramalingam C
2018-04-03 13:57:16 UTC
Permalink
From: Tomas Winkler <***@intel.com>

Whitelist HDCP client for in kernel drm use

v2:
Rebased.
v3:
No changes.

Signed-off-by: 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 0208c4b027c5..3df2a69fddfb 100644
--- a/drivers/misc/mei/bus-fixup.c
+++ b/drivers/misc/mei/bus-fixup.c
@@ -41,6 +41,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

/**
@@ -72,6 +75,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;
@@ -399,6 +414,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
Ramalingam C
2018-04-03 13:57:15 UTC
Permalink
In preparation for implementing HDCP2.2 in I915, this patch adds
HDCP register definitions for HDMI and DP HDCP adaptations.

HDMI specific HDCP2.2 register definitions are added into drm_hdcp.h,
where are HDCP2.2 register offsets in DPCD offsets are defined at
drm_dp_helper.h.

v2:
bit_field definitions are replaced by macros. [Tomas and Jany]
v3:
No Changes.

Signed-off-by: Ramalingam C <***@intel.com>
---
include/drm/drm_dp_helper.h | 54 +++++++++++++++++++++++++++++++++++++++++++++
include/drm/drm_hdcp.h | 29 ++++++++++++++++++++++++
2 files changed, 83 insertions(+)

diff --git a/include/drm/drm_dp_helper.h b/include/drm/drm_dp_helper.h
index 4de97e94ef9d..2185b3a88911 100644
--- a/include/drm/drm_dp_helper.h
+++ b/include/drm/drm_dp_helper.h
@@ -887,6 +887,60 @@
#define DP_AUX_HDCP_KSV_FIFO 0x6802C
#define DP_AUX_HDCP_AINFO 0x6803B

+/**
+ * DP HDCP2.2 parameter offsets in DPCD address space
+ */
+#define DP_HDCP_2_2_REG_RTX_OFFSET 0x69000
+#define DP_HDCP_2_2_REG_TXCAPS_OFFSET 0x69008
+#define DP_HDCP_2_2_REG_CERT_RX_OFFSET 0x6900B
+#define DP_HDCP_2_2_REG_RRX_OFFSET 0x69215
+#define DP_HDCP_2_2_REG_RX_CAPS_OFFSET 0x6921D
+#define DP_HDCP_2_2_REG_EKPUB_KM_OFFSET 0x69220
+#define DP_HDCP_2_2_REG_EKH_KM_OFFSET 0x692A0
+#define DP_HDCP_2_2_REG_M_OFFSET 0x692B0
+#define DP_HDCP_2_2_REG_HPRIME_OFFSET 0x692C0
+#define DP_HDCP_2_2_REG_EKH_KM_RD_OFFSET 0x692E0
+#define DP_HDCP_2_2_REG_RN_OFFSET 0x692F0
+#define DP_HDCP_2_2_REG_LPRIME_OFFSET 0x692F8
+#define DP_HDCP_2_2_REG_EDKEY_KS_OFFSET 0x69318
+#define DP_HDCP_2_2_REG_RIV_OFFSET 0x69328
+#define DP_HDCP_2_2_REG_RXINFO_OFFSET 0x69330
+#define DP_HDCP_2_2_REG_SEQ_NUM_V_OFFSET 0x69332
+#define DP_HDCP_2_2_REG_VPRIME_OFFSET 0x69335
+#define DP_HDCP_2_2_REG_RECV_ID_LIST_OFFSET 0x69345
+#define DP_HDCP_2_2_REG_V_OFFSET 0x693E0
+#define DP_HDCP_2_2_REG_SEQ_NUM_M_OFFSET 0x693F0
+#define DP_HDCP_2_2_REG_K_OFFSET 0x693F3
+#define DP_HDCP_2_2_REG_STREAM_ID_TYPE_OFFSET 0x693F5
+#define DP_HDCP_2_2_REG_MPRIME_OFFSET 0x69473
+#define DP_HDCP_2_2_REG_RXSTATUS_OFFSET 0x69493
+#define DP_HDCP_2_2_REG_STREAM_TYPE_OFFSET 0x69494
+#define DP_HDCP_2_2_REG_DBG_OFFSET 0x69518
+
+/**
+ * DP HDCP message start offsets in DPCD address space
+ */
+#define DP_HDCP_2_2_AKE_INIT_OFFSET DP_HDCP_2_2_REG_RTX_OFFSET
+#define DP_HDCP_2_2_AKE_SEND_CERT_OFFSET DP_HDCP_2_2_REG_CERT_RX_OFFSET
+#define DP_HDCP_2_2_AKE_NO_STORED_KM_OFFSET DP_HDCP_2_2_REG_EKPUB_KM_OFFSET
+#define DP_HDCP_2_2_AKE_STORED_KM_OFFSET DP_HDCP_2_2_REG_EKH_KM_OFFSET
+#define DP_HDCP_2_2_AKE_SEND_HPRIME_OFFSET DP_HDCP_2_2_REG_HPRIME_OFFSET
+#define DP_HDCP_2_2_AKE_SEND_PARING_INFO_OFFSET DP_HDCP_2_2_REG_EKH_KM_RD_OFFSET
+#define DP_HDCP_2_2_LC_INIT_OFFSET DP_HDCP_2_2_REG_RN_OFFSET
+#define DP_HDCP_2_2_LC_SEND_LPRIME_OFFSET DP_HDCP_2_2_REG_LPRIME_OFFSET
+#define DP_HDCP_2_2_SKE_SEND_EKS_OFFSET DP_HDCP_2_2_REG_EDKEY_KS_OFFSET
+#define DP_HDCP_2_2_REP_SEND_RECVID_LIST_OFFSET DP_HDCP_2_2_REG_RXINFO_OFFSET
+#define DP_HDCP_2_2_REP_SEND_ACK_OFFSET DP_HDCP_2_2_REG_V_OFFSET
+#define DP_HDCP_2_2_REP_STREAM_MANAGE_OFFSET DP_HDCP_2_2_REG_SEQ_NUM_M_OFFSET
+#define DP_HDCP_2_2_REP_STREAM_READY_OFFSET DP_HDCP_2_2_REG_MPRIME_OFFSET
+
+#define HDCP_2_2_DP_RXSTATUS_LEN 1
+#define HDCP_2_2_DP_RXSTATUS_READY(x) (x & BIT(0))
+#define HDCP_2_2_DP_RXSTATUS_H_PRIME(x) (x & BIT(1))
+#define HDCP_2_2_DP_RXSTATUS_PAIRING(x) (x & BIT(2))
+#define HDCP_2_2_DP_RXSTATUS_REAUTH_REQ(x) (x & BIT(3))
+#define HDCP_2_2_DP_RXSTATUS_LINK_FAILED(x) (x & BIT(4))
+
/* DP 1.2 Sideband message defines */
/* peer device type - DP 1.2a Table 2-92 */
#define DP_PEER_DEVICE_NONE 0x0
diff --git a/include/drm/drm_hdcp.h b/include/drm/drm_hdcp.h
index 5e0a5ed1a08e..f3f28414b189 100644
--- a/include/drm/drm_hdcp.h
+++ b/include/drm/drm_hdcp.h
@@ -221,4 +221,33 @@ struct hdcp2_dp_errata_stream_type {
uint8_t stream_type;
} __packed;

+/* HDCP2.2 TIMEOUTs in mSec */
+#define HDCP_2_2_CERT_TIMEOUT 100
+#define HDCP_2_2_HPRIME_NO_PAIRED_TIMEOUT 1000
+#define HDCP_2_2_HPRIME_PAIRED_TIMEOUT 200
+#define HDCP_2_2_PAIRING_TIMEOUT 200
+#define HDCP_2_2_HDMI_LPRIME_TIMEOUT 20
+#define HDCP_2_2_DP_LPRIME_TIMEOUT 7
+#define HDCP_2_2_RECVID_LIST_TIMEOUT 3000
+#define HDCP_2_2_STREAM_READY_TIMEOUT 100
+
+/* HDMI HDCP2.2 Register Offsets */
+#define HDCP_2_2_HDMI_REG_VER_OFFSET 0x50
+#define HDCP_2_2_HDMI_REG_WR_MSG_OFFSET 0x60
+#define HDCP_2_2_HDMI_REG_RXSTATUS_OFFSET 0x70
+#define HDCP_2_2_HDMI_REG_RD_MSG_OFFSET 0x80
+#define HDCP_2_2_HDMI_REG_DBG_OFFSET 0xC0
+
+#define HDCP_2_2_HDMI_SUPPORT_MASK BIT(2)
+#define HDCP_2_2_RXCAPS_VERSION_VAL 0x2
+
+#define HDCP_2_2_RX_CAPS_VERSION_VAL 0x02
+#define HDCP_2_2_SEQ_NUM_MAX 0xFFFFFF
+#define HDCP_2_2_DELAY_BEFORE_ENCRYPTION_EN 200
+
+#define HDCP_2_2_HDMI_RXSTATUS_LEN 2
+#define HDCP_2_2_HDMI_RXSTATUS_MSG_SZ_HI(x) (x & 0x3)
+#define HDCP_2_2_HDMI_RXSTATUS_READY(x) (x & BIT(2))
+#define HDCP_2_2_HDMI_RXSTATUS_REAUTH_REQ(x) (x & BIT(3))
+
#endif
--
2.7.4
Shankar, Uma
2018-05-09 10:06:22 UTC
Permalink
-----Original Message-----
Ramalingam C
Sent: Tuesday, April 3, 2018 7:27 PM
Subject: [PATCH v3 02/40] drm: HDMI and DP specific HDCP2.2 defines
In preparation for implementing HDCP2.2 in I915, this patch adds HDCP register
definitions for HDMI and DP HDCP adaptations.
I believe we can just keep this message generic at drm layer, instead of calling out
i915 specifically. Currently it may be enabled for i915, but it will used for other
drivers as well in future.
HDMI specific HDCP2.2 register definitions are added into drm_hdcp.h, where are
Make it "where as".
HDCP2.2 register offsets in DPCD offsets are defined at drm_dp_helper.h.
bit_field definitions are replaced by macros. [Tomas and Jany]
Typo in "Jani's" name.
No Changes.
---
include/drm/drm_dp_helper.h | 54
+++++++++++++++++++++++++++++++++++++++++++++
include/drm/drm_hdcp.h | 29 ++++++++++++++++++++++++
2 files changed, 83 insertions(+)
diff --git a/include/drm/drm_dp_helper.h b/include/drm/drm_dp_helper.h index
4de97e94ef9d..2185b3a88911 100644
--- a/include/drm/drm_dp_helper.h
+++ b/include/drm/drm_dp_helper.h
@@ -887,6 +887,60 @@
#define DP_AUX_HDCP_KSV_FIFO 0x6802C
#define DP_AUX_HDCP_AINFO 0x6803B
+/**
+ * DP HDCP2.2 parameter offsets in DPCD address space */
Rectify the comment style
+#define DP_HDCP_2_2_REG_RTX_OFFSET 0x69000
+#define DP_HDCP_2_2_REG_TXCAPS_OFFSET 0x69008
+#define DP_HDCP_2_2_REG_CERT_RX_OFFSET 0x6900B
+#define DP_HDCP_2_2_REG_RRX_OFFSET 0x69215
+#define DP_HDCP_2_2_REG_RX_CAPS_OFFSET 0x6921D
+#define DP_HDCP_2_2_REG_EKPUB_KM_OFFSET 0x69220
+#define DP_HDCP_2_2_REG_EKH_KM_OFFSET 0x692A0
+#define DP_HDCP_2_2_REG_M_OFFSET 0x692B0
+#define DP_HDCP_2_2_REG_HPRIME_OFFSET 0x692C0
+#define DP_HDCP_2_2_REG_EKH_KM_RD_OFFSET 0x692E0
+#define DP_HDCP_2_2_REG_RN_OFFSET 0x692F0
+#define DP_HDCP_2_2_REG_LPRIME_OFFSET 0x692F8
+#define DP_HDCP_2_2_REG_EDKEY_KS_OFFSET 0x69318
+#define DP_HDCP_2_2_REG_RIV_OFFSET 0x69328
+#define DP_HDCP_2_2_REG_RXINFO_OFFSET 0x69330
+#define DP_HDCP_2_2_REG_SEQ_NUM_V_OFFSET 0x69332
+#define DP_HDCP_2_2_REG_VPRIME_OFFSET 0x69335
+#define DP_HDCP_2_2_REG_RECV_ID_LIST_OFFSET 0x69345
+#define DP_HDCP_2_2_REG_V_OFFSET 0x693E0
+#define DP_HDCP_2_2_REG_SEQ_NUM_M_OFFSET 0x693F0
+#define DP_HDCP_2_2_REG_K_OFFSET 0x693F3
+#define DP_HDCP_2_2_REG_STREAM_ID_TYPE_OFFSET 0x693F5
+#define DP_HDCP_2_2_REG_MPRIME_OFFSET 0x69473
+#define DP_HDCP_2_2_REG_RXSTATUS_OFFSET 0x69493
+#define DP_HDCP_2_2_REG_STREAM_TYPE_OFFSET 0x69494
This is not matching to the spec. Seems reserved in spec.
+#define DP_HDCP_2_2_REG_DBG_OFFSET 0x69518
+
+/**
+ * DP HDCP message start offsets in DPCD address space */
Rectify comment style
+#define DP_HDCP_2_2_AKE_INIT_OFFSET
DP_HDCP_2_2_REG_RTX_OFFSET
+#define DP_HDCP_2_2_AKE_SEND_CERT_OFFSET
DP_HDCP_2_2_REG_CERT_RX_OFFSET
+#define DP_HDCP_2_2_AKE_NO_STORED_KM_OFFSET
DP_HDCP_2_2_REG_EKPUB_KM_OFFSET
+#define DP_HDCP_2_2_AKE_STORED_KM_OFFSET
DP_HDCP_2_2_REG_EKH_KM_OFFSET
+#define DP_HDCP_2_2_AKE_SEND_HPRIME_OFFSET
DP_HDCP_2_2_REG_HPRIME_OFFSET
+#define DP_HDCP_2_2_AKE_SEND_PARING_INFO_OFFSET
Typo in pairing
DP_HDCP_2_2_REG_EKH_KM_RD_OFFSET
+#define DP_HDCP_2_2_LC_INIT_OFFSET
DP_HDCP_2_2_REG_RN_OFFSET
+#define DP_HDCP_2_2_LC_SEND_LPRIME_OFFSET
DP_HDCP_2_2_REG_LPRIME_OFFSET
+#define DP_HDCP_2_2_SKE_SEND_EKS_OFFSET
DP_HDCP_2_2_REG_EDKEY_KS_OFFSET
+#define DP_HDCP_2_2_REP_SEND_RECVID_LIST_OFFSET
DP_HDCP_2_2_REG_RXINFO_OFFSET
+#define DP_HDCP_2_2_REP_SEND_ACK_OFFSET
DP_HDCP_2_2_REG_V_OFFSET
+#define DP_HDCP_2_2_REP_STREAM_MANAGE_OFFSET
DP_HDCP_2_2_REG_SEQ_NUM_M_OFFSET
+#define DP_HDCP_2_2_REP_STREAM_READY_OFFSET
DP_HDCP_2_2_REG_MPRIME_OFFSET
+
+#define HDCP_2_2_DP_RXSTATUS_LEN 1
+#define HDCP_2_2_DP_RXSTATUS_READY(x) (x & BIT(0))
+#define HDCP_2_2_DP_RXSTATUS_H_PRIME(x) (x & BIT(1))
+#define HDCP_2_2_DP_RXSTATUS_PAIRING(x) (x & BIT(2))
+#define HDCP_2_2_DP_RXSTATUS_REAUTH_REQ(x) (x & BIT(3))
+#define HDCP_2_2_DP_RXSTATUS_LINK_FAILED(x) (x & BIT(4))
+
/* DP 1.2 Sideband message defines */
/* peer device type - DP 1.2a Table 2-92 */
Make it multi line comment.
#define DP_PEER_DEVICE_NONE 0x0
diff --git a/include/drm/drm_hdcp.h b/include/drm/drm_hdcp.h index
5e0a5ed1a08e..f3f28414b189 100644
--- a/include/drm/drm_hdcp.h
+++ b/include/drm/drm_hdcp.h
@@ -221,4 +221,33 @@ struct hdcp2_dp_errata_stream_type {
uint8_t stream_type;
} __packed;
+/* HDCP2.2 TIMEOUTs in mSec */
+#define HDCP_2_2_CERT_TIMEOUT 100
+#define HDCP_2_2_HPRIME_NO_PAIRED_TIMEOUT 1000
+#define HDCP_2_2_HPRIME_PAIRED_TIMEOUT 200
+#define HDCP_2_2_PAIRING_TIMEOUT 200
+#define HDCP_2_2_HDMI_LPRIME_TIMEOUT 20
+#define HDCP_2_2_DP_LPRIME_TIMEOUT 7
+#define HDCP_2_2_RECVID_LIST_TIMEOUT 3000
+#define HDCP_2_2_STREAM_READY_TIMEOUT 100
+
+/* HDMI HDCP2.2 Register Offsets */
+#define HDCP_2_2_HDMI_REG_VER_OFFSET 0x50
+#define HDCP_2_2_HDMI_REG_WR_MSG_OFFSET 0x60
+#define HDCP_2_2_HDMI_REG_RXSTATUS_OFFSET 0x70
+#define HDCP_2_2_HDMI_REG_RD_MSG_OFFSET 0x80
+#define HDCP_2_2_HDMI_REG_DBG_OFFSET 0xC0
+
+#define HDCP_2_2_HDMI_SUPPORT_MASK BIT(2)
+#define HDCP_2_2_RXCAPS_VERSION_VAL 0x2
+
+#define HDCP_2_2_RX_CAPS_VERSION_VAL 0x02
+#define HDCP_2_2_SEQ_NUM_MAX 0xFFFFFF
+#define HDCP_2_2_DELAY_BEFORE_ENCRYPTION_EN 200
+
+#define HDCP_2_2_HDMI_RXSTATUS_LEN 2
+#define HDCP_2_2_HDMI_RXSTATUS_MSG_SZ_HI(x) (x & 0x3)
This seems to be a 10 bit field. Please check or am I missing something ?
+#define HDCP_2_2_HDMI_RXSTATUS_READY(x) (x & BIT(2))
It should be bit 10. Add a comment to explain so that it gets easier to match to spec.
+#define HDCP_2_2_HDMI_RXSTATUS_REAUTH_REQ(x) (x & BIT(3))
Same as above. May be add a generic comment.
+
#endif
--
2.7.4
_______________________________________________
dri-devel mailing list
https://lists.freedesktop.org/mailman/listinfo/dri-devel
Ramalingam C
2018-05-14 16:01:41 UTC
Permalink
Post by Shankar, Uma
-----Original Message-----
Ramalingam C
Sent: Tuesday, April 3, 2018 7:27 PM
Subject: [PATCH v3 02/40] drm: HDMI and DP specific HDCP2.2 defines
In preparation for implementing HDCP2.2 in I915, this patch adds HDCP register
definitions for HDMI and DP HDCP adaptations.
I believe we can just keep this message generic at drm layer, instead of calling out
i915 specifically. Currently it may be enabled for i915, but it will used for other
drivers as well in future.
ok
Post by Shankar, Uma
HDMI specific HDCP2.2 register definitions are added into drm_hdcp.h, where are
Make it "where as".
ok
Post by Shankar, Uma
HDCP2.2 register offsets in DPCD offsets are defined at drm_dp_helper.h.
bit_field definitions are replaced by macros. [Tomas and Jany]
Typo in "Jani's" name.
Sorry Jani.
Post by Shankar, Uma
No Changes.
---
include/drm/drm_dp_helper.h | 54
+++++++++++++++++++++++++++++++++++++++++++++
include/drm/drm_hdcp.h | 29 ++++++++++++++++++++++++
2 files changed, 83 insertions(+)
diff --git a/include/drm/drm_dp_helper.h b/include/drm/drm_dp_helper.h index
4de97e94ef9d..2185b3a88911 100644
--- a/include/drm/drm_dp_helper.h
+++ b/include/drm/drm_dp_helper.h
@@ -887,6 +887,60 @@
#define DP_AUX_HDCP_KSV_FIFO 0x6802C
#define DP_AUX_HDCP_AINFO 0x6803B
+/**
+ * DP HDCP2.2 parameter offsets in DPCD address space */
Rectify the comment style
ok
Post by Shankar, Uma
+#define DP_HDCP_2_2_REG_RTX_OFFSET 0x69000
+#define DP_HDCP_2_2_REG_TXCAPS_OFFSET 0x69008
+#define DP_HDCP_2_2_REG_CERT_RX_OFFSET 0x6900B
+#define DP_HDCP_2_2_REG_RRX_OFFSET 0x69215
+#define DP_HDCP_2_2_REG_RX_CAPS_OFFSET 0x6921D
+#define DP_HDCP_2_2_REG_EKPUB_KM_OFFSET 0x69220
+#define DP_HDCP_2_2_REG_EKH_KM_OFFSET 0x692A0
+#define DP_HDCP_2_2_REG_M_OFFSET 0x692B0
+#define DP_HDCP_2_2_REG_HPRIME_OFFSET 0x692C0
+#define DP_HDCP_2_2_REG_EKH_KM_RD_OFFSET 0x692E0
+#define DP_HDCP_2_2_REG_RN_OFFSET 0x692F0
+#define DP_HDCP_2_2_REG_LPRIME_OFFSET 0x692F8
+#define DP_HDCP_2_2_REG_EDKEY_KS_OFFSET 0x69318
+#define DP_HDCP_2_2_REG_RIV_OFFSET 0x69328
+#define DP_HDCP_2_2_REG_RXINFO_OFFSET 0x69330
+#define DP_HDCP_2_2_REG_SEQ_NUM_V_OFFSET 0x69332
+#define DP_HDCP_2_2_REG_VPRIME_OFFSET 0x69335
+#define DP_HDCP_2_2_REG_RECV_ID_LIST_OFFSET 0x69345
+#define DP_HDCP_2_2_REG_V_OFFSET 0x693E0
+#define DP_HDCP_2_2_REG_SEQ_NUM_M_OFFSET 0x693F0
+#define DP_HDCP_2_2_REG_K_OFFSET 0x693F3
+#define DP_HDCP_2_2_REG_STREAM_ID_TYPE_OFFSET 0x693F5
+#define DP_HDCP_2_2_REG_MPRIME_OFFSET 0x69473
+#define DP_HDCP_2_2_REG_RXSTATUS_OFFSET 0x69493
+#define DP_HDCP_2_2_REG_STREAM_TYPE_OFFSET 0x69494
This is not matching to the spec. Seems reserved in spec.
Not really. Register is defined in the DP HDCP2.2 Spec.
Post by Shankar, Uma
+#define DP_HDCP_2_2_REG_DBG_OFFSET 0x69518
+
+/**
+ * DP HDCP message start offsets in DPCD address space */
Rectify comment style
+#define DP_HDCP_2_2_AKE_INIT_OFFSET
DP_HDCP_2_2_REG_RTX_OFFSET
+#define DP_HDCP_2_2_AKE_SEND_CERT_OFFSET
DP_HDCP_2_2_REG_CERT_RX_OFFSET
+#define DP_HDCP_2_2_AKE_NO_STORED_KM_OFFSET
DP_HDCP_2_2_REG_EKPUB_KM_OFFSET
+#define DP_HDCP_2_2_AKE_STORED_KM_OFFSET
DP_HDCP_2_2_REG_EKH_KM_OFFSET
+#define DP_HDCP_2_2_AKE_SEND_HPRIME_OFFSET
DP_HDCP_2_2_REG_HPRIME_OFFSET
+#define DP_HDCP_2_2_AKE_SEND_PARING_INFO_OFFSET
Typo in pairing
Fixed.
Post by Shankar, Uma
DP_HDCP_2_2_REG_EKH_KM_RD_OFFSET
+#define DP_HDCP_2_2_LC_INIT_OFFSET
DP_HDCP_2_2_REG_RN_OFFSET
+#define DP_HDCP_2_2_LC_SEND_LPRIME_OFFSET
DP_HDCP_2_2_REG_LPRIME_OFFSET
+#define DP_HDCP_2_2_SKE_SEND_EKS_OFFSET
DP_HDCP_2_2_REG_EDKEY_KS_OFFSET
+#define DP_HDCP_2_2_REP_SEND_RECVID_LIST_OFFSET
DP_HDCP_2_2_REG_RXINFO_OFFSET
+#define DP_HDCP_2_2_REP_SEND_ACK_OFFSET
DP_HDCP_2_2_REG_V_OFFSET
+#define DP_HDCP_2_2_REP_STREAM_MANAGE_OFFSET
DP_HDCP_2_2_REG_SEQ_NUM_M_OFFSET
+#define DP_HDCP_2_2_REP_STREAM_READY_OFFSET
DP_HDCP_2_2_REG_MPRIME_OFFSET
+
+#define HDCP_2_2_DP_RXSTATUS_LEN 1
+#define HDCP_2_2_DP_RXSTATUS_READY(x) (x & BIT(0))
+#define HDCP_2_2_DP_RXSTATUS_H_PRIME(x) (x & BIT(1))
+#define HDCP_2_2_DP_RXSTATUS_PAIRING(x) (x & BIT(2))
+#define HDCP_2_2_DP_RXSTATUS_REAUTH_REQ(x) (x & BIT(3))
+#define HDCP_2_2_DP_RXSTATUS_LINK_FAILED(x) (x & BIT(4))
+
/* DP 1.2 Sideband message defines */
/* peer device type - DP 1.2a Table 2-92 */
Make it multi line comment.
This is not part of this patch. Already existing lines.
Post by Shankar, Uma
#define DP_PEER_DEVICE_NONE 0x0
diff --git a/include/drm/drm_hdcp.h b/include/drm/drm_hdcp.h index
5e0a5ed1a08e..f3f28414b189 100644
--- a/include/drm/drm_hdcp.h
+++ b/include/drm/drm_hdcp.h
@@ -221,4 +221,33 @@ struct hdcp2_dp_errata_stream_type {
uint8_t stream_type;
} __packed;
+/* HDCP2.2 TIMEOUTs in mSec */
+#define HDCP_2_2_CERT_TIMEOUT 100
+#define HDCP_2_2_HPRIME_NO_PAIRED_TIMEOUT 1000
+#define HDCP_2_2_HPRIME_PAIRED_TIMEOUT 200
+#define HDCP_2_2_PAIRING_TIMEOUT 200
+#define HDCP_2_2_HDMI_LPRIME_TIMEOUT 20
+#define HDCP_2_2_DP_LPRIME_TIMEOUT 7
+#define HDCP_2_2_RECVID_LIST_TIMEOUT 3000
+#define HDCP_2_2_STREAM_READY_TIMEOUT 100
+
+/* HDMI HDCP2.2 Register Offsets */
+#define HDCP_2_2_HDMI_REG_VER_OFFSET 0x50
+#define HDCP_2_2_HDMI_REG_WR_MSG_OFFSET 0x60
+#define HDCP_2_2_HDMI_REG_RXSTATUS_OFFSET 0x70
+#define HDCP_2_2_HDMI_REG_RD_MSG_OFFSET 0x80
+#define HDCP_2_2_HDMI_REG_DBG_OFFSET 0xC0
+
+#define HDCP_2_2_HDMI_SUPPORT_MASK BIT(2)
+#define HDCP_2_2_RXCAPS_VERSION_VAL 0x2
+
+#define HDCP_2_2_RX_CAPS_VERSION_VAL 0x02
+#define HDCP_2_2_SEQ_NUM_MAX 0xFFFFFF
+#define HDCP_2_2_DELAY_BEFORE_ENCRYPTION_EN 200
+
+#define HDCP_2_2_HDMI_RXSTATUS_LEN 2
+#define HDCP_2_2_HDMI_RXSTATUS_MSG_SZ_HI(x) (x & 0x3)
This seems to be a 10 bit field. Please check or am I missing something ?
Yes. Only high 2bits need to be parsed from a byte. LSB is read as it is.
Post by Shankar, Uma
+#define HDCP_2_2_HDMI_RXSTATUS_READY(x) (x & BIT(2))
It should be bit 10. Add a comment to explain so that it gets easier to match to spec.
+#define HDCP_2_2_HDMI_RXSTATUS_REAUTH_REQ(x) (x & BIT(3))
Same as above. May be add a generic comment.
Comment is added.
Post by Shankar, Uma
+
#endif
--
2.7.4
_______________________________________________
dri-devel mailing list
https://lists.freedesktop.org/mailman/listinfo/dri-devel
Ramalingam C
2018-04-03 13:57:17 UTC
Permalink
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]

Signed-off-by: Ramalingam C <***@intel.com>
Signed-off-by: Tomas Winkler <***@intel.com>
---
drivers/misc/mei/Kconfig | 6 ++++
drivers/misc/mei/Makefile | 2 ++
drivers/misc/mei/hdcp/Makefile | 6 ++++
drivers/misc/mei/hdcp/mei_hdcp.c | 74 ++++++++++++++++++++++++++++++++++++++++
4 files changed, 88 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..90977132d1e2 100644
--- a/drivers/misc/mei/Kconfig
+++ b/drivers/misc/mei/Kconfig
@@ -43,3 +43,9 @@ config INTEL_MEI_TXE

Supported SoCs:
Intel Bay Trail
+
+config INTEL_MEI_HDCP
+ tristate "Intel HDCP2.2 services of ME Interface"
+ depends on INTEL_MEI && DRM_I915
+ help
+ MEI Support for HDCP2.2 Services on Intel SoCs.
diff --git a/drivers/misc/mei/Makefile b/drivers/misc/mei/Makefile
index cd6825afa8e1..e64d1212fb85 100644
--- a/drivers/misc/mei/Makefile
+++ b/drivers/misc/mei/Makefile
@@ -23,3 +23,5 @@ mei-txe-objs += hw-txe.o

mei-$(CONFIG_EVENT_TRACING) += mei-trace.o
CFLAGS_mei-trace.o = -I$(src)
+
+obj-$(CONFIG_INTEL_MEI_HDCP) += hdcp/
diff --git a/drivers/misc/mei/hdcp/Makefile b/drivers/misc/mei/hdcp/Makefile
new file mode 100644
index 000000000000..75ac50203223
--- /dev/null
+++ b/drivers/misc/mei/hdcp/Makefile
@@ -0,0 +1,6 @@
+# SPDX-License-Identifier: GPL-2.0
+#
+# Makefile - HDCP client driver for Intel MEI Bus Driver.
+# Copyright (c) 2010-2014, Intel Corporation.
+#
+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..b334615728a7
--- /dev/null
+++ b/drivers/misc/mei/hdcp/mei_hdcp.c
@@ -0,0 +1,74 @@
+/* SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) */
+/*
+ * Copyright © 2017-2018 Intel Corporation
+ *
+ * Mei_hdcp.c: HDCP client driver for mei bus
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ * Ramalingam C <***@intel.com>
+ */
+
+#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)
+{
+ mei_cldev_set_drvdata(cldev, NULL);
+ return mei_cldev_disable(cldev);
+}
+
+#define MEI_UUID_HDCP UUID_LE(0xB638AB7E, 0x94E2, 0x4EA2, 0xA5, \
+ 0x52, 0xD1, 0xC5, 0x4B, \
+ 0x62, 0x7F, 0x04)
+
+static struct mei_cl_device_id mei_hdcp_tbl[] = {
+ { .uuid = MEI_UUID_HDCP, .version = MEI_CL_VERSION_ANY },
+ { }
+};
+MODULE_DEVICE_TABLE(mei, mei_hdcp_tbl);
+
+static struct mei_cl_driver mei_hdcp_driver = {
+ .id_table = mei_hdcp_tbl,
+ .name = KBUILD_MODNAME,
+ .probe = mei_hdcp_probe,
+ .remove = mei_hdcp_remove,
+};
+
+module_mei_cl_driver(mei_hdcp_driver);
+
+MODULE_AUTHOR("Intel Corporation");
+MODULE_LICENSE("Dual BSD/GPL");
+MODULE_DESCRIPTION("HDCP");
--
2.7.4
Shankar, Uma
2018-05-09 10:07:31 UTC
Permalink
-----Original Message-----
Ramalingam C
Sent: Tuesday, April 3, 2018 7:27 PM
Subject: [PATCH v3 04/40] misc/mei/hdcp: Client driver for HDCP application
ME FW is contributes a vital role in HDCP2.2 authentication.
Remove "is".
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
Drop "and HDCP2.2" here.
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
Drop "HDCP2.". Its implicit, no need to call multiple times.
verification.
Once All the steps of HDCP2.2 authentications are complete on driver's request
Change "All to all". Drop "s" from authentication. Add a "," after complete.
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.
hdcp files are moved to drivers/misc/mei/hdcp/ [Tomas]
Squashed the Kbuild support [Tomas]
UUID renamed and Module License is modified [Tomas]
drv_data is set to null at remove [Tomas]
---
drivers/misc/mei/Kconfig | 6 ++++
drivers/misc/mei/Makefile | 2 ++
drivers/misc/mei/hdcp/Makefile | 6 ++++
drivers/misc/mei/hdcp/mei_hdcp.c | 74
++++++++++++++++++++++++++++++++++++++++
4 files changed, 88 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..90977132d1e2 100644
--- a/drivers/misc/mei/Kconfig
+++ b/drivers/misc/mei/Kconfig
@@ -43,3 +43,9 @@ config INTEL_MEI_TXE
Intel Bay Trail
+
+config INTEL_MEI_HDCP
+ tristate "Intel HDCP2.2 services of ME Interface"
+ depends on INTEL_MEI && DRM_I915
+ help
+ MEI Support for HDCP2.2 Services on Intel SoCs.
diff --git a/drivers/misc/mei/Makefile b/drivers/misc/mei/Makefile index
cd6825afa8e1..e64d1212fb85 100644
--- a/drivers/misc/mei/Makefile
+++ b/drivers/misc/mei/Makefile
@@ -23,3 +23,5 @@ mei-txe-objs += hw-txe.o
mei-$(CONFIG_EVENT_TRACING) += mei-trace.o CFLAGS_mei-trace.o = -I$(src)
+
+obj-$(CONFIG_INTEL_MEI_HDCP) += hdcp/
diff --git a/drivers/misc/mei/hdcp/Makefile b/drivers/misc/mei/hdcp/Makefile
new file mode 100644 index 000000000000..75ac50203223
--- /dev/null
+++ b/drivers/misc/mei/hdcp/Makefile
@@ -0,0 +1,6 @@
+# SPDX-License-Identifier: GPL-2.0
+#
+# Makefile - HDCP client driver for Intel MEI Bus Driver.
+# Copyright (c) 2010-2014, Intel Corporation.
+#
+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..b334615728a7
--- /dev/null
+++ b/drivers/misc/mei/hdcp/mei_hdcp.c
@@ -0,0 +1,74 @@
+/* SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) */
+/*
+ * Copyright © 2017-2018 Intel Corporation
+ *
+ * Mei_hdcp.c: HDCP client driver for mei bus
+ *
+ * Permission is hereby granted, free of charge, to any person
+obtaining a
+ * copy of this software and associated documentation files (the
+"Software"),
+ * to deal in the Software without restriction, including without
+limitation
+ * the rights to use, copy, modify, merge, publish, distribute,
+sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom
+the
+ *
+ * The above copyright notice and this permission notice (including the
+next
+ * paragraph) shall be included in all copies or substantial portions
+of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO
EVENT
+SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
DAMAGES OR
+OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ */
+
+#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) {
+ mei_cldev_set_drvdata(cldev, NULL);
+ return mei_cldev_disable(cldev);
+}
+
+#define MEI_UUID_HDCP UUID_LE(0xB638AB7E, 0x94E2, 0x4EA2,
0xA5, \
+ 0x52, 0xD1, 0xC5, 0x4B, \
+ 0x62, 0x7F, 0x04)
+
+static struct mei_cl_device_id mei_hdcp_tbl[] = {
+ { .uuid = MEI_UUID_HDCP, .version = MEI_CL_VERSION_ANY },
+ { }
+};
+MODULE_DEVICE_TABLE(mei, mei_hdcp_tbl);
+
+static struct mei_cl_driver mei_hdcp_driver = {
+ .id_table = mei_hdcp_tbl,
+ .name = KBUILD_MODNAME,
+ .probe = mei_hdcp_probe,
+ .remove = mei_hdcp_remove,
+};
+
+module_mei_cl_driver(mei_hdcp_driver);
+
+MODULE_AUTHOR("Intel Corporation");
+MODULE_LICENSE("Dual BSD/GPL");
+MODULE_DESCRIPTION("HDCP");
--
2.7.4
_______________________________________________
dri-devel mailing list
https://lists.freedesktop.org/mailman/listinfo/dri-devel
Ramalingam C
2018-04-03 13:57:21 UTC
Permalink
Request ME FW to start the HDCP2.2 session for a intel port.
Prepares payloads for command WIRED_INITIATE_HDCP2_SESSION and sent
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]

Signed-off-by: Ramalingam C <***@intel.com>
---
drivers/misc/mei/hdcp/mei_hdcp.c | 68 ++++++++++++++++++++++++++++++++++++++++
include/linux/mei_hdcp.h | 11 +++++++
2 files changed, 79 insertions(+)

diff --git a/drivers/misc/mei/hdcp/mei_hdcp.c b/drivers/misc/mei/hdcp/mei_hdcp.c
index 2811a25f8c57..7caee0947761 100644
--- a/drivers/misc/mei/hdcp/mei_hdcp.c
+++ b/drivers/misc/mei/hdcp/mei_hdcp.c
@@ -33,9 +33,77 @@
#include <linux/mei_cl_bus.h>
#include <linux/notifier.h>
#include <linux/mei_hdcp.h>
+#include <drm/drm_connector.h>
+
+#include "mei_hdcp.h"

static BLOCKING_NOTIFIER_HEAD(mei_cldev_notifier_list);

+/**
+ * mei_initiate_hdcp2_session:
+ * Function to start a Wired HDCP2.2 Tx Session with ME FW
+ *
+ * @cldev : Pointer for mei client device
+ * @data : Intel HW specific Data
+ * @ake_data : ptr to store AKE_Init
+ *
+ * Returns 0 on Success, <0 on Failure.
+ */
+int mei_initiate_hdcp2_session(struct mei_cl_device *cldev,
+ struct mei_hdcp_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 device *dev;
+ ssize_t byte;
+
+ if (!data || !ake_data)
+ return -EINVAL;
+
+ dev = &cldev->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 = data->port;
+ session_init_in.protocol = (uint8_t)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. %d\n", (int)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. %d\n", (int)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 -1;
+ }
+
+ 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,
+ sizeof(session_init_out.r_tx));
+
+ return 0;
+}
+EXPORT_SYMBOL(mei_initiate_hdcp2_session);
+
void mei_cldev_state_notify_clients(struct mei_cl_device *cldev, bool enabled)
{
if (enabled)
diff --git a/include/linux/mei_hdcp.h b/include/linux/mei_hdcp.h
index 634c1a5bdf1e..bb4f27d3abcb 100644
--- a/include/linux/mei_hdcp.h
+++ b/include/linux/mei_hdcp.h
@@ -28,6 +28,7 @@
#define _LINUX_MEI_HDCP_H

#include <linux/mei_cl_bus.h>
+#include <drm/drm_hdcp.h>

enum mei_cldev_state {
MEI_CLDEV_DISABLED,
@@ -105,6 +106,9 @@ struct mei_hdcp_data {
#ifdef CONFIG_INTEL_MEI_HDCP
int mei_cldev_register_notify(struct notifier_block *nb);
int mei_cldev_unregister_notify(struct notifier_block *nb);
+int mei_initiate_hdcp2_session(struct mei_cl_device *cldev,
+ struct mei_hdcp_data *data,
+ struct hdcp2_ake_init *ake_data);
#else
static int mei_cldev_register_notify(struct notifier_block *nb)
{
@@ -114,5 +118,12 @@ static int mei_cldev_unregister_notify(struct notifier_block *nb)
{
return -ENODEV;
}
+static inline
+int mei_initiate_hdcp2_session(struct mei_cl_device *cldev,
+ struct mei_hdcp_data *data,
+ struct hdcp2_ake_init *ake_data)
+{
+ return -ENODEV;
+}
#endif /* defined (CONFIG_INTEL_MEI_HDCP) */
#endif /* defined (_LINUX_MEI_HDCP_H) */
--
2.7.4
kbuild test robot
2018-04-03 21:20:33 UTC
Permalink
Hi Ramalingam,

Thank you for the patch! Yet something to improve:

[auto build test ERROR on drm-intel/for-linux-next]
[also build test ERROR on next-20180403]
[cannot apply to v4.16]
[if your patch is applied to the wrong git tree, please drop us a note to help improve the system]

url: https://github.com/0day-ci/linux/commits/Ramalingam-C/drm-i915-Implement-HDCP2-2/20180404-031743
base: git://anongit.freedesktop.org/drm-intel for-linux-next
config: i386-allmodconfig (attached as .config)
compiler: gcc-7 (Debian 7.3.0-1) 7.3.0
reproduce:
# save the attached .config to linux build tree
make ARCH=i386
drivers/misc/mei/hdcp/mei_hdcp.c:52:5: error: redefinition of 'mei_initiate_hdcp2_session'
int mei_initiate_hdcp2_session(struct mei_cl_device *cldev,
^~~~~~~~~~~~~~~~~~~~~~~~~~
In file included from drivers/misc/mei/hdcp/mei_hdcp.c:35:0:
include/linux/mei_hdcp.h:122:5: note: previous definition of 'mei_initiate_hdcp2_session' was here
int mei_initiate_hdcp2_session(struct mei_cl_device *cldev,
^~~~~~~~~~~~~~~~~~~~~~~~~~
drivers/misc/mei/hdcp/mei_hdcp.c:117:5: error: redefinition of 'mei_cldev_register_notify'
int mei_cldev_register_notify(struct notifier_block *nb)
^~~~~~~~~~~~~~~~~~~~~~~~~
In file included from drivers/misc/mei/hdcp/mei_hdcp.c:35:0:
include/linux/mei_hdcp.h:113:12: note: previous definition of 'mei_cldev_register_notify' was here
static int mei_cldev_register_notify(struct notifier_block *nb)
^~~~~~~~~~~~~~~~~~~~~~~~~
drivers/misc/mei/hdcp/mei_hdcp.c:123:5: error: redefinition of 'mei_cldev_unregister_notify'
int mei_cldev_unregister_notify(struct notifier_block *nb)
^~~~~~~~~~~~~~~~~~~~~~~~~~~
In file included from drivers/misc/mei/hdcp/mei_hdcp.c:35:0:
include/linux/mei_hdcp.h:117:12: note: previous definition of 'mei_cldev_unregister_notify' was here
static int mei_cldev_unregister_notify(struct notifier_block *nb)
^~~~~~~~~~~~~~~~~~~~~~~~~~~
include/linux/mei_hdcp.h:117:12: warning: 'mei_cldev_unregister_notify' defined but not used [-Wunused-function]
include/linux/mei_hdcp.h:113:12: warning: 'mei_cldev_register_notify' defined but not used [-Wunused-function]
static int mei_cldev_register_notify(struct notifier_block *nb)
^~~~~~~~~~~~~~~~~~~~~~~~~

vim +/mei_initiate_hdcp2_session +52 drivers/misc/mei/hdcp/mei_hdcp.c

41
42 /**
43 * mei_initiate_hdcp2_session:
44 * Function to start a Wired HDCP2.2 Tx Session with ME FW
45 *
46 * @cldev : Pointer for mei client device
47 * @data : Intel HW specific Data
48 * @ake_data : ptr to store AKE_Init
49 *
50 * Returns 0 on Success, <0 on Failure.
51 */
52 int mei_initiate_hdcp2_session(struct mei_cl_device *cldev,
53 struct mei_hdcp_data *data,
54 struct hdcp2_ake_init *ake_data)
55 {
56 struct wired_cmd_initiate_hdcp2_session_in session_init_in = { { 0 } };
57 struct wired_cmd_initiate_hdcp2_session_out
58 session_init_out = { { 0 } };
59 struct device *dev;
60 ssize_t byte;
61
62 if (!data || !ake_data)
63 return -EINVAL;
64
65 dev = &cldev->dev;
66
67 session_init_in.header.api_version = HDCP_API_VERSION;
68 session_init_in.header.command_id = WIRED_INITIATE_HDCP2_SESSION;
69 session_init_in.header.status = ME_HDCP_STATUS_SUCCESS;
70 session_init_in.header.buffer_len =
71 WIRED_CMD_BUF_LEN_INITIATE_HDCP2_SESSION_IN;
72
73 session_init_in.port.integrated_port_type = data->port_type;
74 session_init_in.port.physical_port = data->port;
75 session_init_in.protocol = (uint8_t)data->protocol;
76
77 byte = mei_cldev_send(cldev, (u8 *)&session_init_in,
78 sizeof(session_init_in));
79 if (byte < 0) {
80 dev_dbg(dev, "mei_cldev_send failed. %d\n", (int)byte);
81 return byte;
82 }
83
84 byte = mei_cldev_recv(cldev, (u8 *)&session_init_out,
85 sizeof(session_init_out));
86 if (byte < 0) {
87 dev_dbg(dev, "mei_cldev_recv failed. %d\n", (int)byte);
88 return byte;
89 }
90
91 if (session_init_out.header.status != ME_HDCP_STATUS_SUCCESS) {
92 dev_dbg(dev, "ME cmd 0x%08X Failed. Status: 0x%X\n",
93 WIRED_INITIATE_HDCP2_SESSION,
94 session_init_out.header.status);
95 return -1;
96 }
97
98 ake_data->msg_id = HDCP_2_2_AKE_INIT;
99 ake_data->tx_caps = session_init_out.tx_caps;
100 memcpy(ake_data->r_tx, session_init_out.r_tx,
101 sizeof(session_init_out.r_tx));
102
103 return 0;
104 }
105 EXPORT_SYMBOL(mei_initiate_hdcp2_session);
106

---
0-DAY kernel test infrastructure Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all Intel Corporation
Usyskin, Alexander
2018-04-04 06:45:42 UTC
Permalink
-----Original Message-----
From: C, Ramalingam
Sent: Tuesday, April 03, 2018 16:57
Subject: [PATCH v3 08/40] misc/mei/hdcp: Initiate Wired HDCP2.2 Tx Session
Request ME FW to start the HDCP2.2 session for a intel port.
Prepares payloads for command WIRED_INITIATE_HDCP2_SESSION and sent
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.
Rebased.
cldev is add as a separate parameter [Tomas]
Redundant comment and typecast are removed [Tomas]
---
drivers/misc/mei/hdcp/mei_hdcp.c | 68
++++++++++++++++++++++++++++++++++++++++
include/linux/mei_hdcp.h | 11 +++++++
2 files changed, 79 insertions(+)
diff --git a/drivers/misc/mei/hdcp/mei_hdcp.c
b/drivers/misc/mei/hdcp/mei_hdcp.c
index 2811a25f8c57..7caee0947761 100644
--- a/drivers/misc/mei/hdcp/mei_hdcp.c
+++ b/drivers/misc/mei/hdcp/mei_hdcp.c
@@ -33,9 +33,77 @@
#include <linux/mei_cl_bus.h>
#include <linux/notifier.h>
#include <linux/mei_hdcp.h>
+#include <drm/drm_connector.h>
+
+#include "mei_hdcp.h"
static BLOCKING_NOTIFIER_HEAD(mei_cldev_notifier_list);
+/**
+ * Function to start a Wired HDCP2.2 Tx Session with ME FW
+ *
+ *
+ * Returns 0 on Success, <0 on Failure.
+ */
+int mei_initiate_hdcp2_session(struct mei_cl_device *cldev,
+ struct mei_hdcp_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 device *dev;
+ ssize_t byte;
+
+ if (!data || !ake_data)
+ return -EINVAL;
+
+ dev = &cldev->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 = data->port;
+ session_init_in.protocol = (uint8_t)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. %d\n", (int)byte);
%zd don't require (int)
+ 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. %d\n", (int)byte);
%zd don't require (int)
+ 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 -1;
It will be better to return some meaningful error code here.
+ }
+
+ 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,
+ sizeof(session_init_out.r_tx));
+
+ return 0;
+}
+EXPORT_SYMBOL(mei_initiate_hdcp2_session);
+
void mei_cldev_state_notify_clients(struct mei_cl_device *cldev, bool enabled)
{
if (enabled)
diff --git a/include/linux/mei_hdcp.h b/include/linux/mei_hdcp.h
index 634c1a5bdf1e..bb4f27d3abcb 100644
--- a/include/linux/mei_hdcp.h
+++ b/include/linux/mei_hdcp.h
@@ -28,6 +28,7 @@
#define _LINUX_MEI_HDCP_H
#include <linux/mei_cl_bus.h>
+#include <drm/drm_hdcp.h>
enum mei_cldev_state {
MEI_CLDEV_DISABLED,
@@ -105,6 +106,9 @@ struct mei_hdcp_data {
#ifdef CONFIG_INTEL_MEI_HDCP
int mei_cldev_register_notify(struct notifier_block *nb);
int mei_cldev_unregister_notify(struct notifier_block *nb);
+int mei_initiate_hdcp2_session(struct mei_cl_device *cldev,
+ struct mei_hdcp_data *data,
+ struct hdcp2_ake_init *ake_data);
#else
static int mei_cldev_register_notify(struct notifier_block *nb)
{
@@ -114,5 +118,12 @@ static int mei_cldev_unregister_notify(struct notifier_block *nb)
{
return -ENODEV;
}
+static inline
+int mei_initiate_hdcp2_session(struct mei_cl_device *cldev,
+ struct mei_hdcp_data *data,
+ struct hdcp2_ake_init *ake_data)
+{
+ return -ENODEV;
+}
#endif /* defined (CONFIG_INTEL_MEI_HDCP) */
#endif /* defined (_LINUX_MEI_HDCP_H) */
--
2.7.4
Ramalingam C
2018-05-16 15:19:31 UTC
Permalink
Post by Usyskin, Alexander
-----Original Message-----
From: C, Ramalingam
Sent: Tuesday, April 03, 2018 16:57
Subject: [PATCH v3 08/40] misc/mei/hdcp: Initiate Wired HDCP2.2 Tx Session
Request ME FW to start the HDCP2.2 session for a intel port.
Prepares payloads for command WIRED_INITIATE_HDCP2_SESSION and sent
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.
Rebased.
cldev is add as a separate parameter [Tomas]
Redundant comment and typecast are removed [Tomas]
---
drivers/misc/mei/hdcp/mei_hdcp.c | 68
++++++++++++++++++++++++++++++++++++++++
include/linux/mei_hdcp.h | 11 +++++++
2 files changed, 79 insertions(+)
diff --git a/drivers/misc/mei/hdcp/mei_hdcp.c
b/drivers/misc/mei/hdcp/mei_hdcp.c
index 2811a25f8c57..7caee0947761 100644
--- a/drivers/misc/mei/hdcp/mei_hdcp.c
+++ b/drivers/misc/mei/hdcp/mei_hdcp.c
@@ -33,9 +33,77 @@
#include <linux/mei_cl_bus.h>
#include <linux/notifier.h>
#include <linux/mei_hdcp.h>
+#include <drm/drm_connector.h>
+
+#include "mei_hdcp.h"
static BLOCKING_NOTIFIER_HEAD(mei_cldev_notifier_list);
+/**
+ * Function to start a Wired HDCP2.2 Tx Session with ME FW
+ *
+ *
+ * Returns 0 on Success, <0 on Failure.
+ */
+int mei_initiate_hdcp2_session(struct mei_cl_device *cldev,
+ struct mei_hdcp_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 device *dev;
+ ssize_t byte;
+
+ if (!data || !ake_data)
+ return -EINVAL;
+
+ dev = &cldev->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 = data->port;
+ session_init_in.protocol = (uint8_t)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. %d\n", (int)byte);
%zd don't require (int)
Sure. Thanks
Post by Usyskin, Alexander
+ 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. %d\n", (int)byte);
%zd don't require (int)
+ 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 -1;
It will be better to return some meaningful error code here.
I dont think default error codes will match here. And at present other
side I915 doesn't expect the reason but the failure state.
May be we could do something like -(session_init_out.header.status). But
error codes of ME FW is not known to I915.

So may be as of now lets keep it as some -ve return value -1?

--Ram
Post by Usyskin, Alexander
+ }
+
+ 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,
+ sizeof(session_init_out.r_tx));
+
+ return 0;
+}
+EXPORT_SYMBOL(mei_initiate_hdcp2_session);
+
void mei_cldev_state_notify_clients(struct mei_cl_device *cldev, bool enabled)
{
if (enabled)
diff --git a/include/linux/mei_hdcp.h b/include/linux/mei_hdcp.h
index 634c1a5bdf1e..bb4f27d3abcb 100644
--- a/include/linux/mei_hdcp.h
+++ b/include/linux/mei_hdcp.h
@@ -28,6 +28,7 @@
#define _LINUX_MEI_HDCP_H
#include <linux/mei_cl_bus.h>
+#include <drm/drm_hdcp.h>
enum mei_cldev_state {
MEI_CLDEV_DISABLED,
@@ -105,6 +106,9 @@ struct mei_hdcp_data {
#ifdef CONFIG_INTEL_MEI_HDCP
int mei_cldev_register_notify(struct notifier_block *nb);
int mei_cldev_unregister_notify(struct notifier_block *nb);
+int mei_initiate_hdcp2_session(struct mei_cl_device *cldev,
+ struct mei_hdcp_data *data,
+ struct hdcp2_ake_init *ake_data);
#else
static int mei_cldev_register_notify(struct notifier_block *nb)
{
@@ -114,5 +118,12 @@ static int mei_cldev_unregister_notify(struct notifier_block *nb)
{
return -ENODEV;
}
+static inline
+int mei_initiate_hdcp2_session(struct mei_cl_device *cldev,
+ struct mei_hdcp_data *data,
+ struct hdcp2_ake_init *ake_data)
+{
+ return -ENODEV;
+}
#endif /* defined (CONFIG_INTEL_MEI_HDCP) */
#endif /* defined (_LINUX_MEI_HDCP_H) */
--
2.7.4
Shankar, Uma
2018-05-09 10:13:21 UTC
Permalink
-----Original Message-----
Ramalingam C
Sent: Tuesday, April 3, 2018 7:27 PM
Subject: [Intel-gfx] [PATCH v3 08/40] misc/mei/hdcp: Initiate Wired HDCP2.2 Tx
Session
Request ME FW to start the HDCP2.2 session for a intel port.
Change "a" to "an".
Prepares payloads for command WIRED_INITIATE_HDCP2_SESSION and sent to
"sent" to "sends"
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.
Rebased.
cldev is add as a separate parameter [Tomas]
Redundant comment and typecast are removed [Tomas]
---
drivers/misc/mei/hdcp/mei_hdcp.c | 68
++++++++++++++++++++++++++++++++++++++++
include/linux/mei_hdcp.h | 11 +++++++
2 files changed, 79 insertions(+)
diff --git a/drivers/misc/mei/hdcp/mei_hdcp.c
b/drivers/misc/mei/hdcp/mei_hdcp.c
index 2811a25f8c57..7caee0947761 100644
--- a/drivers/misc/mei/hdcp/mei_hdcp.c
+++ b/drivers/misc/mei/hdcp/mei_hdcp.c
@@ -33,9 +33,77 @@
#include <linux/mei_cl_bus.h>
#include <linux/notifier.h>
#include <linux/mei_hdcp.h>
+#include <drm/drm_connector.h>
+
+#include "mei_hdcp.h"
static BLOCKING_NOTIFIER_HEAD(mei_cldev_notifier_list);
+/**
+ * Function to start a Wired HDCP2.2 Tx Session with ME FW
+ *
+ *
+ * Returns 0 on Success, <0 on Failure.
+ */
+int mei_initiate_hdcp2_session(struct mei_cl_device *cldev,
+ struct mei_hdcp_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 device *dev;
+ ssize_t byte;
+
+ if (!data || !ake_data)
+ return -EINVAL;
+
+ dev = &cldev->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 = data->port;
+ session_init_in.protocol = (uint8_t)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. %d\n", (int)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. %d\n", (int)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 -1;
+ }
+
+ 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,
We should check for ake_data->r_tx for NULL as well before attempting this copy.
+ sizeof(session_init_out.r_tx));
+
+ return 0;
+}
+EXPORT_SYMBOL(mei_initiate_hdcp2_session);
+
void mei_cldev_state_notify_clients(struct mei_cl_device *cldev, bool enabled) {
if (enabled)
diff --git a/include/linux/mei_hdcp.h b/include/linux/mei_hdcp.h index
634c1a5bdf1e..bb4f27d3abcb 100644
--- a/include/linux/mei_hdcp.h
+++ b/include/linux/mei_hdcp.h
@@ -28,6 +28,7 @@
#define _LINUX_MEI_HDCP_H
#include <linux/mei_cl_bus.h>
+#include <drm/drm_hdcp.h>
enum mei_cldev_state {
MEI_CLDEV_DISABLED,
@@ -105,6 +106,9 @@ struct mei_hdcp_data { #ifdef
CONFIG_INTEL_MEI_HDCP int mei_cldev_register_notify(struct notifier_block
*nb); int mei_cldev_unregister_notify(struct notifier_block *nb);
+int mei_initiate_hdcp2_session(struct mei_cl_device *cldev,
+ struct mei_hdcp_data *data,
+ struct hdcp2_ake_init *ake_data);
#else
return -ENODEV;
}
+static inline
+int mei_initiate_hdcp2_session(struct mei_cl_device *cldev,
+ struct mei_hdcp_data *data,
+ struct hdcp2_ake_init *ake_data) {
+ return -ENODEV;
+}
#endif /* defined (CONFIG_INTEL_MEI_HDCP) */ #endif /* defined
(_LINUX_MEI_HDCP_H) */
--
2.7.4
_______________________________________________
Intel-gfx mailing list
https://lists.freedesktop.org/mailman/listinfo/intel-gfx
Ramalingam C
2018-05-16 15:26:28 UTC
Permalink
Post by Shankar, Uma
-----Original Message-----
Ramalingam C
Sent: Tuesday, April 3, 2018 7:27 PM
Subject: [Intel-gfx] [PATCH v3 08/40] misc/mei/hdcp: Initiate Wired HDCP2.2 Tx
Session
Request ME FW to start the HDCP2.2 session for a intel port.
Change "a" to "an".
Prepares payloads for command WIRED_INITIATE_HDCP2_SESSION and sent to
"sent" to "sends"
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.
Rebased.
cldev is add as a separate parameter [Tomas]
Redundant comment and typecast are removed [Tomas]
---
drivers/misc/mei/hdcp/mei_hdcp.c | 68
++++++++++++++++++++++++++++++++++++++++
include/linux/mei_hdcp.h | 11 +++++++
2 files changed, 79 insertions(+)
diff --git a/drivers/misc/mei/hdcp/mei_hdcp.c
b/drivers/misc/mei/hdcp/mei_hdcp.c
index 2811a25f8c57..7caee0947761 100644
--- a/drivers/misc/mei/hdcp/mei_hdcp.c
+++ b/drivers/misc/mei/hdcp/mei_hdcp.c
@@ -33,9 +33,77 @@
#include <linux/mei_cl_bus.h>
#include <linux/notifier.h>
#include <linux/mei_hdcp.h>
+#include <drm/drm_connector.h>
+
+#include "mei_hdcp.h"
static BLOCKING_NOTIFIER_HEAD(mei_cldev_notifier_list);
+/**
+ * Function to start a Wired HDCP2.2 Tx Session with ME FW
+ *
+ *
+ * Returns 0 on Success, <0 on Failure.
+ */
+int mei_initiate_hdcp2_session(struct mei_cl_device *cldev,
+ struct mei_hdcp_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 device *dev;
+ ssize_t byte;
+
+ if (!data || !ake_data)
+ return -EINVAL;
+
+ dev = &cldev->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 = data->port;
+ session_init_in.protocol = (uint8_t)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. %d\n", (int)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. %d\n", (int)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 -1;
+ }
+
+ 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,
We should check for ake_data->r_tx for NULL as well before attempting this copy.
r_tx is statically allocated array within struct ake_data. So I guess
once ptr ake_data is valid
we need not check for r_tx.

--Ram
Post by Shankar, Uma
+ sizeof(session_init_out.r_tx));
+
+ return 0;
+}
+EXPORT_SYMBOL(mei_initiate_hdcp2_session);
+
void mei_cldev_state_notify_clients(struct mei_cl_device *cldev, bool enabled) {
if (enabled)
diff --git a/include/linux/mei_hdcp.h b/include/linux/mei_hdcp.h index
634c1a5bdf1e..bb4f27d3abcb 100644
--- a/include/linux/mei_hdcp.h
+++ b/include/linux/mei_hdcp.h
@@ -28,6 +28,7 @@
#define _LINUX_MEI_HDCP_H
#include <linux/mei_cl_bus.h>
+#include <drm/drm_hdcp.h>
enum mei_cldev_state {
MEI_CLDEV_DISABLED,
@@ -105,6 +106,9 @@ struct mei_hdcp_data { #ifdef
CONFIG_INTEL_MEI_HDCP int mei_cldev_register_notify(struct notifier_block
*nb); int mei_cldev_unregister_notify(struct notifier_block *nb);
+int mei_initiate_hdcp2_session(struct mei_cl_device *cldev,
+ struct mei_hdcp_data *data,
+ struct hdcp2_ake_init *ake_data);
#else
return -ENODEV;
}
+static inline
+int mei_initiate_hdcp2_session(struct mei_cl_device *cldev,
+ struct mei_hdcp_data *data,
+ struct hdcp2_ake_init *ake_data) {
+ return -ENODEV;
+}
#endif /* defined (CONFIG_INTEL_MEI_HDCP) */ #endif /* defined
(_LINUX_MEI_HDCP_H) */
--
2.7.4
_______________________________________________
Intel-gfx mailing list
https://lists.freedesktop.org/mailman/listinfo/intel-gfx
Ramalingam C
2018-04-03 13:57:22 UTC
Permalink
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]

Signed-off-by: Ramalingam C <***@intel.com>
---
drivers/misc/mei/hdcp/mei_hdcp.c | 82 ++++++++++++++++++++++++++++++++++++++++
include/linux/mei_hdcp.h | 17 +++++++++
2 files changed, 99 insertions(+)

diff --git a/drivers/misc/mei/hdcp/mei_hdcp.c b/drivers/misc/mei/hdcp/mei_hdcp.c
index 7caee0947761..181994529058 100644
--- a/drivers/misc/mei/hdcp/mei_hdcp.c
+++ b/drivers/misc/mei/hdcp/mei_hdcp.c
@@ -104,6 +104,88 @@ int mei_initiate_hdcp2_session(struct mei_cl_device *cldev,
}
EXPORT_SYMBOL(mei_initiate_hdcp2_session);

+/**
+ * mei_verify_receiver_cert_prepare_km:
+ * Function to verify the Receiver Certificate AKE_Send_Cert
+ * and prepare AKE_Stored_Km or AKE_No_Stored_Km
+ *
+ * @cldev : Pointer for mei client device
+ * @data : Intel HW specific Data
+ * @rx_cert : Pointer for AKE_Send_Cert
+ * @km_stored : Pointer for pairing status flag
+ * @ek_pub_km : Pointer for output msg
+ * @msg_sz : Pointer for size of AKE_XXXXX_Km
+ *
+ * Returns 0 on Success, <0 on Failure
+ */
+int
+mei_verify_receiver_cert_prepare_km(struct mei_cl_device *cldev,
+ struct mei_hdcp_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 device *dev;
+ ssize_t byte;
+
+ if (!data || !rx_cert || !km_stored || !ek_pub_km || !msg_sz)
+ return -EINVAL;
+
+ dev = &cldev->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 = data->port;
+
+ memcpy(&verify_rxcert_in.cert_rx, &rx_cert->cert_rx,
+ sizeof(rx_cert->cert_rx));
+ memcpy(verify_rxcert_in.r_rx, &rx_cert->r_rx, sizeof(rx_cert->r_rx));
+ 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: %d\n", (int)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: %d\n", (int)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 -1;
+ }
+
+ *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;
+}
+EXPORT_SYMBOL(mei_verify_receiver_cert_prepare_km);
+
void mei_cldev_state_notify_clients(struct mei_cl_device *cldev, bool enabled)
{
if (enabled)
diff --git a/include/linux/mei_hdcp.h b/include/linux/mei_hdcp.h
index bb4f27d3abcb..314b15f6afc0 100644
--- a/include/linux/mei_hdcp.h
+++ b/include/linux/mei_hdcp.h
@@ -109,6 +109,13 @@ int mei_cldev_unregister_notify(struct notifier_block *nb);
int mei_initiate_hdcp2_session(struct mei_cl_device *cldev,
struct mei_hdcp_data *data,
struct hdcp2_ake_init *ake_data);
+int
+mei_verify_receiver_cert_prepare_km(struct mei_cl_device *cldev,
+ struct mei_hdcp_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);
#else
static int mei_cldev_register_notify(struct notifier_block *nb)
{
@@ -125,5 +132,15 @@ int mei_initiate_hdcp2_session(struct mei_cl_device *cldev,
{
return -ENODEV;
}
+static inline int
+mei_verify_receiver_cert_prepare_km(struct mei_cl_device *cldev,
+ struct mei_hdcp_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)
+{
+ return -ENODEV;
+}
#endif /* defined (CONFIG_INTEL_MEI_HDCP) */
#endif /* defined (_LINUX_MEI_HDCP_H) */
--
2.7.4
kbuild test robot
2018-04-03 21:44:49 UTC
Permalink
Hi Ramalingam,

Thank you for the patch! Yet something to improve:

[auto build test ERROR on drm-intel/for-linux-next]
[also build test ERROR on next-20180403]
[cannot apply to v4.16]
[if your patch is applied to the wrong git tree, please drop us a note to help improve the system]

url: https://github.com/0day-ci/linux/commits/Ramalingam-C/drm-i915-Implement-HDCP2-2/20180404-031743
base: git://anongit.freedesktop.org/drm-intel for-linux-next
config: i386-allmodconfig (attached as .config)
compiler: gcc-7 (Debian 7.3.0-1) 7.3.0
reproduce:
# save the attached .config to linux build tree
make ARCH=i386

All errors (new ones prefixed by >>):

drivers/misc/mei/hdcp/mei_hdcp.c:52:5: error: redefinition of 'mei_initiate_hdcp2_session'
int mei_initiate_hdcp2_session(struct mei_cl_device *cldev,
^~~~~~~~~~~~~~~~~~~~~~~~~~
In file included from drivers/misc/mei/hdcp/mei_hdcp.c:35:0:
include/linux/mei_hdcp.h:129:5: note: previous definition of 'mei_initiate_hdcp2_session' was here
int mei_initiate_hdcp2_session(struct mei_cl_device *cldev,
^~~~~~~~~~~~~~~~~~~~~~~~~~
drivers/misc/mei/hdcp/mei_hdcp.c:122:1: error: redefinition of 'mei_verify_receiver_cert_prepare_km'
mei_verify_receiver_cert_prepare_km(struct mei_cl_device *cldev,
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
In file included from drivers/misc/mei/hdcp/mei_hdcp.c:35:0:
include/linux/mei_hdcp.h:136:1: note: previous definition of 'mei_verify_receiver_cert_prepare_km' was here
mei_verify_receiver_cert_prepare_km(struct mei_cl_device *cldev,
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
drivers/misc/mei/hdcp/mei_hdcp.c:199:5: error: redefinition of 'mei_cldev_register_notify'
int mei_cldev_register_notify(struct notifier_block *nb)
^~~~~~~~~~~~~~~~~~~~~~~~~
In file included from drivers/misc/mei/hdcp/mei_hdcp.c:35:0:
include/linux/mei_hdcp.h:120:12: note: previous definition of 'mei_cldev_register_notify' was here
static int mei_cldev_register_notify(struct notifier_block *nb)
^~~~~~~~~~~~~~~~~~~~~~~~~
drivers/misc/mei/hdcp/mei_hdcp.c:205:5: error: redefinition of 'mei_cldev_unregister_notify'
int mei_cldev_unregister_notify(struct notifier_block *nb)
^~~~~~~~~~~~~~~~~~~~~~~~~~~
In file included from drivers/misc/mei/hdcp/mei_hdcp.c:35:0:
include/linux/mei_hdcp.h:124:12: note: previous definition of 'mei_cldev_unregister_notify' was here
static int mei_cldev_unregister_notify(struct notifier_block *nb)
^~~~~~~~~~~~~~~~~~~~~~~~~~~
include/linux/mei_hdcp.h:124:12: warning: 'mei_cldev_unregister_notify' defined but not used [-Wunused-function]
include/linux/mei_hdcp.h:120:12: warning: 'mei_cldev_register_notify' defined but not used [-Wunused-function]
static int mei_cldev_register_notify(struct notifier_block *nb)
^~~~~~~~~~~~~~~~~~~~~~~~~

vim +/mei_verify_receiver_cert_prepare_km +122 drivers/misc/mei/hdcp/mei_hdcp.c

41
42 /**
43 * mei_initiate_hdcp2_session:
44 * Function to start a Wired HDCP2.2 Tx Session with ME FW
45 *
46 * @cldev : Pointer for mei client device
47 * @data : Intel HW specific Data
48 * @ake_data : ptr to store AKE_Init
49 *
50 * Returns 0 on Success, <0 on Failure.
51 */
52 int mei_initiate_hdcp2_session(struct mei_cl_device *cldev,
53 struct mei_hdcp_data *data,
54 struct hdcp2_ake_init *ake_data)
55 {
56 struct wired_cmd_initiate_hdcp2_session_in session_init_in = { { 0 } };
57 struct wired_cmd_initiate_hdcp2_session_out
58 session_init_out = { { 0 } };
59 struct device *dev;
60 ssize_t byte;
61
62 if (!data || !ake_data)
63 return -EINVAL;
64
65 dev = &cldev->dev;
66
67 session_init_in.header.api_version = HDCP_API_VERSION;
68 session_init_in.header.command_id = WIRED_INITIATE_HDCP2_SESSION;
69 session_init_in.header.status = ME_HDCP_STATUS_SUCCESS;
70 session_init_in.header.buffer_len =
71 WIRED_CMD_BUF_LEN_INITIATE_HDCP2_SESSION_IN;
72
73 session_init_in.port.integrated_port_type = data->port_type;
74 session_init_in.port.physical_port = data->port;
75 session_init_in.protocol = (uint8_t)data->protocol;
76
77 byte = mei_cldev_send(cldev, (u8 *)&session_init_in,
78 sizeof(session_init_in));
79 if (byte < 0) {
80 dev_dbg(dev, "mei_cldev_send failed. %d\n", (int)byte);
81 return byte;
82 }
83
84 byte = mei_cldev_recv(cldev, (u8 *)&session_init_out,
85 sizeof(session_init_out));
86 if (byte < 0) {
87 dev_dbg(dev, "mei_cldev_recv failed. %d\n", (int)byte);
88 return byte;
89 }
90
91 if (session_init_out.header.status != ME_HDCP_STATUS_SUCCESS) {
92 dev_dbg(dev, "ME cmd 0x%08X Failed. Status: 0x%X\n",
93 WIRED_INITIATE_HDCP2_SESSION,
94 session_init_out.header.status);
95 return -1;
96 }
97
98 ake_data->msg_id = HDCP_2_2_AKE_INIT;
99 ake_data->tx_caps = session_init_out.tx_caps;
100 memcpy(ake_data->r_tx, session_init_out.r_tx,
101 sizeof(session_init_out.r_tx));
102
103 return 0;
104 }
105 EXPORT_SYMBOL(mei_initiate_hdcp2_session);
106
107 /**
108 * mei_verify_receiver_cert_prepare_km:
109 * Function to verify the Receiver Certificate AKE_Send_Cert
110 * and prepare AKE_Stored_Km or AKE_No_Stored_Km
111 *
112 * @cldev : Pointer for mei client device
113 * @data : Intel HW specific Data
114 * @rx_cert : Pointer for AKE_Send_Cert
115 * @km_stored : Pointer for pairing status flag
116 * @ek_pub_km : Pointer for output msg
117 * @msg_sz : Pointer for size of AKE_XXXXX_Km
118 *
119 * Returns 0 on Success, <0 on Failure
120 */
121 int
122 mei_verify_receiver_cert_prepare_km(struct mei_cl_device *cldev,
123 struct mei_hdcp_data *data,
124 struct hdcp2_ake_send_cert *rx_cert,
125 bool *km_stored,
126 struct hdcp2_ake_no_stored_km *ek_pub_km,
127 size_t *msg_sz)
128 {
129 struct wired_cmd_verify_receiver_cert_in verify_rxcert_in = { { 0 } };
130 struct wired_cmd_verify_receiver_cert_out verify_rxcert_out = { { 0 } };
131 struct device *dev;
132 ssize_t byte;
133
134 if (!data || !rx_cert || !km_stored || !ek_pub_km || !msg_sz)
135 return -EINVAL;
136
137 dev = &cldev->dev;
138
139 verify_rxcert_in.header.api_version = HDCP_API_VERSION;
140 verify_rxcert_in.header.command_id = WIRED_VERIFY_RECEIVER_CERT;
141 verify_rxcert_in.header.status = ME_HDCP_STATUS_SUCCESS;
142 verify_rxcert_in.header.buffer_len =
143 WIRED_CMD_BUF_LEN_VERIFY_RECEIVER_CERT_IN;
144
145 verify_rxcert_in.port.integrated_port_type = data->port_type;
146 verify_rxcert_in.port.physical_port = data->port;
147
148 memcpy(&verify_rxcert_in.cert_rx, &rx_cert->cert_rx,
149 sizeof(rx_cert->cert_rx));
150 memcpy(verify_rxcert_in.r_rx, &rx_cert->r_rx, sizeof(rx_cert->r_rx));
151 memcpy(verify_rxcert_in.rx_caps, rx_cert->rx_caps, HDCP_2_2_RXCAPS_LEN);
152
153 byte = mei_cldev_send(cldev, (u8 *)&verify_rxcert_in,
154 sizeof(verify_rxcert_in));
155 if (byte < 0) {
156 dev_dbg(dev, "mei_cldev_send failed: %d\n", (int)byte);
157 return byte;
158 }
159
160 byte = mei_cldev_recv(cldev, (u8 *)&verify_rxcert_out,
161 sizeof(verify_rxcert_out));
162 if (byte < 0) {
163 dev_dbg(dev, "mei_cldev_recv failed: %d\n", (int)byte);
164 return byte;
165 }
166
167 if (verify_rxcert_out.header.status != ME_HDCP_STATUS_SUCCESS) {
168 dev_dbg(dev, "ME cmd 0x%08X Failed. Status: 0x%X\n",
169 WIRED_VERIFY_RECEIVER_CERT,
170 verify_rxcert_out.header.status);
171 return -1;
172 }
173
174 *km_stored = verify_rxcert_out.km_stored;
175 if (verify_rxcert_out.km_stored) {
176 ek_pub_km->msg_id = HDCP_2_2_AKE_STORED_KM;
177 *msg_sz = sizeof(struct hdcp2_ake_stored_km);
178 } else {
179 ek_pub_km->msg_id = HDCP_2_2_AKE_NO_STORED_KM;
180 *msg_sz = sizeof(struct hdcp2_ake_no_stored_km);
181 }
182
183 memcpy(ek_pub_km->e_kpub_km, &verify_rxcert_out.ekm_buff,
184 sizeof(verify_rxcert_out.ekm_buff));
185 return 0;
186 }
187 EXPORT_SYMBOL(mei_verify_receiver_cert_prepare_km);
188

---
0-DAY kernel test infrastructure Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all Intel Corporation
Ramalingam C
2018-04-03 13:57:18 UTC
Permalink
Notifier Chain is defined to inform all its clients about the mei
client device state change. Routine is defined for the clients to
register and unregister for the notification on state change.

v2:
Rebased.
v3:
Notifier chain is adopted for cldev state update [Tomas]

Signed-off-by: Ramalingam C <***@intel.com>
---
drivers/misc/mei/hdcp/mei_hdcp.c | 36 +++++++++++++++++++++++++++---
include/linux/mei_hdcp.h | 48 ++++++++++++++++++++++++++++++++++++++++
2 files changed, 81 insertions(+), 3 deletions(-)
create mode 100644 include/linux/mei_hdcp.h

diff --git a/drivers/misc/mei/hdcp/mei_hdcp.c b/drivers/misc/mei/hdcp/mei_hdcp.c
index b334615728a7..2811a25f8c57 100644
--- a/drivers/misc/mei/hdcp/mei_hdcp.c
+++ b/drivers/misc/mei/hdcp/mei_hdcp.c
@@ -31,6 +31,32 @@
#include <linux/slab.h>
#include <linux/uuid.h>
#include <linux/mei_cl_bus.h>
+#include <linux/notifier.h>
+#include <linux/mei_hdcp.h>
+
+static BLOCKING_NOTIFIER_HEAD(mei_cldev_notifier_list);
+
+void mei_cldev_state_notify_clients(struct mei_cl_device *cldev, bool enabled)
+{
+ if (enabled)
+ blocking_notifier_call_chain(&mei_cldev_notifier_list,
+ MEI_CLDEV_ENABLED, cldev);
+ else
+ blocking_notifier_call_chain(&mei_cldev_notifier_list,
+ MEI_CLDEV_DISABLED, NULL);
+}
+
+int mei_cldev_register_notify(struct notifier_block *nb)
+{
+ return blocking_notifier_chain_register(&mei_cldev_notifier_list, nb);
+}
+EXPORT_SYMBOL_GPL(mei_cldev_register_notify);
+
+int mei_cldev_unregister_notify(struct notifier_block *nb)
+{
+ return blocking_notifier_chain_unregister(&mei_cldev_notifier_list, nb);
+}
+EXPORT_SYMBOL_GPL(mei_cldev_unregister_notify);

static int mei_hdcp_probe(struct mei_cl_device *cldev,
const struct mei_cl_device_id *id)
@@ -38,14 +64,18 @@ static int mei_hdcp_probe(struct mei_cl_device *cldev,
int ret;

ret = mei_cldev_enable(cldev);
- if (ret < 0)
+ if (ret < 0) {
dev_err(&cldev->dev, "mei_cldev_enable Failed. %d\n", ret);
+ return ret;
+ }

- return ret;
+ mei_cldev_state_notify_clients(cldev, true);
+ return 0;
}

static int mei_hdcp_remove(struct mei_cl_device *cldev)
{
+ mei_cldev_state_notify_clients(cldev, false);
mei_cldev_set_drvdata(cldev, NULL);
return mei_cldev_disable(cldev);
}
@@ -71,4 +101,4 @@ module_mei_cl_driver(mei_hdcp_driver);

MODULE_AUTHOR("Intel Corporation");
MODULE_LICENSE("Dual BSD/GPL");
-MODULE_DESCRIPTION("HDCP");
+MODULE_DESCRIPTION("MEI HDCP");
diff --git a/include/linux/mei_hdcp.h b/include/linux/mei_hdcp.h
new file mode 100644
index 000000000000..3b46bebde718
--- /dev/null
+++ b/include/linux/mei_hdcp.h
@@ -0,0 +1,48 @@
+/* SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) */
+/*
+ * Copyright © 2017-2018 Intel Corporation
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that copyright
+ * notice and this permission notice appear in supporting documentation, and
+ * that the name of the copyright holders not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission. The copyright holders make no representations
+ * about the suitability of this software for any purpose. It is provided "as
+ * is" without express or implied warranty.
+ *
+ * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
+ * OF THIS SOFTWARE.
+ *
+ * Authors:
+ * Ramalingam C <***@intel.com>
+ */
+
+#ifndef _LINUX_MEI_HDCP_H
+#define _LINUX_MEI_HDCP_H
+
+enum mei_cldev_state {
+ MEI_CLDEV_DISABLED,
+ MEI_CLDEV_ENABLED
+};
+
+#ifdef CONFIG_INTEL_MEI_HDCP
+int mei_cldev_register_notify(struct notifier_block *nb);
+int mei_cldev_unregister_notify(struct notifier_block *nb);
+#else
+static int mei_cldev_register_notify(struct notifier_block *nb)
+{
+ return -ENODEV;
+}
+static int mei_cldev_unregister_notify(struct notifier_block *nb)
+{
+ return -ENODEV;
+}
+#endif /* defined (CONFIG_INTEL_MEI_HDCP) */
+#endif /* defined (_LINUX_MEI_HDCP_H) */
--
2.7.4
Daniel Vetter
2018-04-03 15:30:42 UTC
Permalink
Post by Ramalingam C
Notifier Chain is defined to inform all its clients about the mei
client device state change. Routine is defined for the clients to
register and unregister for the notification on state change.
Rebased.
Notifier chain is adopted for cldev state update [Tomas]
For managing interactions between multiple drivers notifier chains are
fairly problematic. The main reason is the locking embedded in the
notifier chain. To make things safe, that lock must be held everytime we
add/remove any part of the link, and when calling any callback. Usually
that means you get a neat deadlock sooner or later, because the
load/unload code has inverse paths compared to normal operation.

Notifiers also not not provide a clean way to handle suspend/resume
ordering.

There's two parts to do this properly.

1. Finding the other driver. Multi-part drivers are assembled nowadays
using the component framework. We're using that already to manage the
interaction between drm/i915 and snd-hda. If not all components are ready
yet, then the driver load sequence must be aborted by returning
-EPROBE_DEFER. That's going to be lots of fun, since for the mei/i915
interaction it's probably going to be i915 that needs to abort and retry
the driver load. But we do CI test all the abort points in our driver
load, so should work well.

2. Handling the ordering restrictions for suspend/resume. For i915/snd-hda
we used a early_resume/late_suspend callback trickery, but that doesn't
really scale to multiple levels. Since we've done that device_link has
been added. As a bonus device_link can also ensure that not only
suspend/resume (including runtime suspend/resume) is ordered correctly,
but also that driver bind/unbind works correctly. Still needs the
component stuff and initial -EPROBE_DEFER, but will all least make sure
we' only reprobe once more. See device_link_add + docs in device_link.rst.

One thing I didn't check is whether we want the device linke to also
manage runtime pm for us. It would mean that we keep the ME awake as long
as anything is using the gpu (any display on or any rendering happening).
That might be too much, but could also be that it won't matter (and then
using DL_FLAG_PM_RUNTIME would simply our code).

We might also need to convert the i915/snd-hda interactions to device_link
first, since the early/late_resume/suspend hack probably doesn't interact
too well with proper device_links.

Cheers, Daniel
Post by Ramalingam C
---
drivers/misc/mei/hdcp/mei_hdcp.c | 36 +++++++++++++++++++++++++++---
include/linux/mei_hdcp.h | 48 ++++++++++++++++++++++++++++++++++++++++
2 files changed, 81 insertions(+), 3 deletions(-)
create mode 100644 include/linux/mei_hdcp.h
diff --git a/drivers/misc/mei/hdcp/mei_hdcp.c b/drivers/misc/mei/hdcp/mei_hdcp.c
index b334615728a7..2811a25f8c57 100644
--- a/drivers/misc/mei/hdcp/mei_hdcp.c
+++ b/drivers/misc/mei/hdcp/mei_hdcp.c
@@ -31,6 +31,32 @@
#include <linux/slab.h>
#include <linux/uuid.h>
#include <linux/mei_cl_bus.h>
+#include <linux/notifier.h>
+#include <linux/mei_hdcp.h>
+
+static BLOCKING_NOTIFIER_HEAD(mei_cldev_notifier_list);
+
+void mei_cldev_state_notify_clients(struct mei_cl_device *cldev, bool enabled)
+{
+ if (enabled)
+ blocking_notifier_call_chain(&mei_cldev_notifier_list,
+ MEI_CLDEV_ENABLED, cldev);
+ else
+ blocking_notifier_call_chain(&mei_cldev_notifier_list,
+ MEI_CLDEV_DISABLED, NULL);
+}
+
+int mei_cldev_register_notify(struct notifier_block *nb)
+{
+ return blocking_notifier_chain_register(&mei_cldev_notifier_list, nb);
+}
+EXPORT_SYMBOL_GPL(mei_cldev_register_notify);
+
+int mei_cldev_unregister_notify(struct notifier_block *nb)
+{
+ return blocking_notifier_chain_unregister(&mei_cldev_notifier_list, nb);
+}
+EXPORT_SYMBOL_GPL(mei_cldev_unregister_notify);
static int mei_hdcp_probe(struct mei_cl_device *cldev,
const struct mei_cl_device_id *id)
@@ -38,14 +64,18 @@ static int mei_hdcp_probe(struct mei_cl_device *cldev,
int ret;
ret = mei_cldev_enable(cldev);
- if (ret < 0)
+ if (ret < 0) {
dev_err(&cldev->dev, "mei_cldev_enable Failed. %d\n", ret);
+ return ret;
+ }
- return ret;
+ mei_cldev_state_notify_clients(cldev, true);
+ return 0;
}
static int mei_hdcp_remove(struct mei_cl_device *cldev)
{
+ mei_cldev_state_notify_clients(cldev, false);
mei_cldev_set_drvdata(cldev, NULL);
return mei_cldev_disable(cldev);
}
@@ -71,4 +101,4 @@ module_mei_cl_driver(mei_hdcp_driver);
MODULE_AUTHOR("Intel Corporation");
MODULE_LICENSE("Dual BSD/GPL");
-MODULE_DESCRIPTION("HDCP");
+MODULE_DESCRIPTION("MEI HDCP");
diff --git a/include/linux/mei_hdcp.h b/include/linux/mei_hdcp.h
new file mode 100644
index 000000000000..3b46bebde718
--- /dev/null
+++ b/include/linux/mei_hdcp.h
@@ -0,0 +1,48 @@
+/* SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) */
+/*
+ * Copyright © 2017-2018 Intel Corporation
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that copyright
+ * notice and this permission notice appear in supporting documentation, and
+ * that the name of the copyright holders not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission. The copyright holders make no representations
+ * about the suitability of this software for any purpose. It is provided "as
+ * is" without express or implied warranty.
+ *
+ * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
+ * OF THIS SOFTWARE.
+ *
+ */
+
+#ifndef _LINUX_MEI_HDCP_H
+#define _LINUX_MEI_HDCP_H
+
+enum mei_cldev_state {
+ MEI_CLDEV_DISABLED,
+ MEI_CLDEV_ENABLED
+};
+
+#ifdef CONFIG_INTEL_MEI_HDCP
+int mei_cldev_register_notify(struct notifier_block *nb);
+int mei_cldev_unregister_notify(struct notifier_block *nb);
+#else
+static int mei_cldev_register_notify(struct notifier_block *nb)
+{
+ return -ENODEV;
+}
+static int mei_cldev_unregister_notify(struct notifier_block *nb)
+{
+ return -ENODEV;
+}
+#endif /* defined (CONFIG_INTEL_MEI_HDCP) */
+#endif /* defined (_LINUX_MEI_HDCP_H) */
--
2.7.4
--
Daniel Vetter
Software Engineer, Intel Corporation
http://blog.ffwll.ch
Ramalingam C
2018-05-16 14:54:06 UTC
Permalink
Post by Daniel Vetter
Post by Ramalingam C
Notifier Chain is defined to inform all its clients about the mei
client device state change. Routine is defined for the clients to
register and unregister for the notification on state change.
Rebased.
Notifier chain is adopted for cldev state update [Tomas]
For managing interactions between multiple drivers notifier chains are
fairly problematic. The main reason is the locking embedded in the
notifier chain. To make things safe, that lock must be held everytime we
add/remove any part of the link, and when calling any callback. Usually
that means you get a neat deadlock sooner or later, because the
load/unload code has inverse paths compared to normal operation.
Notifiers also not not provide a clean way to handle suspend/resume
ordering.
Recording the IRC discussion here:

As Daniel Vetter suggested, with notifiers to mei client device binding
status, I have tested
the I915 and mei_hdcp modules as inbuild and as modules at suspend and
resume of them.

During the experiment, CONFIG_PROVE_LOCKING was enabled. No issue was
observed due to the
usecase of the notifier here. Notifier was used here just to inform the
I915 that mei client device is no more.
So that I915 will stop any ongoing HDCP2.2 protection and reject any
further request.

Hence Planning to continue with same shape of the patch on v4. If any
erroneous scenario is detected
we will work on the alternate solution.

--Ram
Post by Daniel Vetter
There's two parts to do this properly.
1. Finding the other driver. Multi-part drivers are assembled nowadays
using the component framework. We're using that already to manage the
interaction between drm/i915 and snd-hda. If not all components are ready
yet, then the driver load sequence must be aborted by returning
-EPROBE_DEFER. That's going to be lots of fun, since for the mei/i915
interaction it's probably going to be i915 that needs to abort and retry
the driver load. But we do CI test all the abort points in our driver
load, so should work well.
2. Handling the ordering restrictions for suspend/resume. For i915/snd-hda
we used a early_resume/late_suspend callback trickery, but that doesn't
really scale to multiple levels. Since we've done that device_link has
been added. As a bonus device_link can also ensure that not only
suspend/resume (including runtime suspend/resume) is ordered correctly,
but also that driver bind/unbind works correctly. Still needs the
component stuff and initial -EPROBE_DEFER, but will all least make sure
we' only reprobe once more. See device_link_add + docs in device_link.rst.
One thing I didn't check is whether we want the device linke to also
manage runtime pm for us. It would mean that we keep the ME awake as long
as anything is using the gpu (any display on or any rendering happening).
That might be too much, but could also be that it won't matter (and then
using DL_FLAG_PM_RUNTIME would simply our code).
We might also need to convert the i915/snd-hda interactions to device_link
first, since the early/late_resume/suspend hack probably doesn't interact
too well with proper device_links.
Cheers, Daniel
Post by Ramalingam C
---
drivers/misc/mei/hdcp/mei_hdcp.c | 36 +++++++++++++++++++++++++++---
include/linux/mei_hdcp.h | 48 ++++++++++++++++++++++++++++++++++++++++
2 files changed, 81 insertions(+), 3 deletions(-)
create mode 100644 include/linux/mei_hdcp.h
diff --git a/drivers/misc/mei/hdcp/mei_hdcp.c b/drivers/misc/mei/hdcp/mei_hdcp.c
index b334615728a7..2811a25f8c57 100644
--- a/drivers/misc/mei/hdcp/mei_hdcp.c
+++ b/drivers/misc/mei/hdcp/mei_hdcp.c
@@ -31,6 +31,32 @@
#include <linux/slab.h>
#include <linux/uuid.h>
#include <linux/mei_cl_bus.h>
+#include <linux/notifier.h>
+#include <linux/mei_hdcp.h>
+
+static BLOCKING_NOTIFIER_HEAD(mei_cldev_notifier_list);
+
+void mei_cldev_state_notify_clients(struct mei_cl_device *cldev, bool enabled)
+{
+ if (enabled)
+ blocking_notifier_call_chain(&mei_cldev_notifier_list,
+ MEI_CLDEV_ENABLED, cldev);
+ else
+ blocking_notifier_call_chain(&mei_cldev_notifier_list,
+ MEI_CLDEV_DISABLED, NULL);
+}
+
+int mei_cldev_register_notify(struct notifier_block *nb)
+{
+ return blocking_notifier_chain_register(&mei_cldev_notifier_list, nb);
+}
+EXPORT_SYMBOL_GPL(mei_cldev_register_notify);
+
+int mei_cldev_unregister_notify(struct notifier_block *nb)
+{
+ return blocking_notifier_chain_unregister(&mei_cldev_notifier_list, nb);
+}
+EXPORT_SYMBOL_GPL(mei_cldev_unregister_notify);
static int mei_hdcp_probe(struct mei_cl_device *cldev,
const struct mei_cl_device_id *id)
@@ -38,14 +64,18 @@ static int mei_hdcp_probe(struct mei_cl_device *cldev,
int ret;
ret = mei_cldev_enable(cldev);
- if (ret < 0)
+ if (ret < 0) {
dev_err(&cldev->dev, "mei_cldev_enable Failed. %d\n", ret);
+ return ret;
+ }
- return ret;
+ mei_cldev_state_notify_clients(cldev, true);
+ return 0;
}
static int mei_hdcp_remove(struct mei_cl_device *cldev)
{
+ mei_cldev_state_notify_clients(cldev, false);
mei_cldev_set_drvdata(cldev, NULL);
return mei_cldev_disable(cldev);
}
@@ -71,4 +101,4 @@ module_mei_cl_driver(mei_hdcp_driver);
MODULE_AUTHOR("Intel Corporation");
MODULE_LICENSE("Dual BSD/GPL");
-MODULE_DESCRIPTION("HDCP");
+MODULE_DESCRIPTION("MEI HDCP");
diff --git a/include/linux/mei_hdcp.h b/include/linux/mei_hdcp.h
new file mode 100644
index 000000000000..3b46bebde718
--- /dev/null
+++ b/include/linux/mei_hdcp.h
@@ -0,0 +1,48 @@
+/* SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) */
+/*
+ * Copyright © 2017-2018 Intel Corporation
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that copyright
+ * notice and this permission notice appear in supporting documentation, and
+ * that the name of the copyright holders not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission. The copyright holders make no representations
+ * about the suitability of this software for any purpose. It is provided "as
+ * is" without express or implied warranty.
+ *
+ * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
+ * OF THIS SOFTWARE.
+ *
+ */
+
+#ifndef _LINUX_MEI_HDCP_H
+#define _LINUX_MEI_HDCP_H
+
+enum mei_cldev_state {
+ MEI_CLDEV_DISABLED,
+ MEI_CLDEV_ENABLED
+};
+
+#ifdef CONFIG_INTEL_MEI_HDCP
+int mei_cldev_register_notify(struct notifier_block *nb);
+int mei_cldev_unregister_notify(struct notifier_block *nb);
+#else
+static int mei_cldev_register_notify(struct notifier_block *nb)
+{
+ return -ENODEV;
+}
+static int mei_cldev_unregister_notify(struct notifier_block *nb)
+{
+ return -ENODEV;
+}
+#endif /* defined (CONFIG_INTEL_MEI_HDCP) */
+#endif /* defined (_LINUX_MEI_HDCP_H) */
--
2.7.4
kbuild test robot
2018-04-03 20:53:12 UTC
Permalink
Hi Ramalingam,

Thank you for the patch! Yet something to improve:

[auto build test ERROR on drm-intel/for-linux-next]
[also build test ERROR on next-20180403]
[cannot apply to v4.16]
[if your patch is applied to the wrong git tree, please drop us a note to help improve the system]

url: https://github.com/0day-ci/linux/commits/Ramalingam-C/drm-i915-Implement-HDCP2-2/20180404-031743
base: git://anongit.freedesktop.org/drm-intel for-linux-next
config: i386-allmodconfig (attached as .config)
compiler: gcc-7 (Debian 7.3.0-1) 7.3.0
reproduce:
# save the attached .config to linux build tree
make ARCH=i386
drivers/misc/mei/hdcp/mei_hdcp.c:49:5: error: redefinition of 'mei_cldev_register_notify'
int mei_cldev_register_notify(struct notifier_block *nb)
^~~~~~~~~~~~~~~~~~~~~~~~~
In file included from drivers/misc/mei/hdcp/mei_hdcp.c:35:0:
include/linux/mei_hdcp.h:39:12: note: previous definition of 'mei_cldev_register_notify' was here
static int mei_cldev_register_notify(struct notifier_block *nb)
^~~~~~~~~~~~~~~~~~~~~~~~~
drivers/misc/mei/hdcp/mei_hdcp.c:55:5: error: redefinition of 'mei_cldev_unregister_notify'
int mei_cldev_unregister_notify(struct notifier_block *nb)
^~~~~~~~~~~~~~~~~~~~~~~~~~~
In file included from drivers/misc/mei/hdcp/mei_hdcp.c:35:0:
include/linux/mei_hdcp.h:43:12: note: previous definition of 'mei_cldev_unregister_notify' was here
static int mei_cldev_unregister_notify(struct notifier_block *nb)
^~~~~~~~~~~~~~~~~~~~~~~~~~~
include/linux/mei_hdcp.h:43:12: warning: 'mei_cldev_unregister_notify' defined but not used [-Wunused-function]
include/linux/mei_hdcp.h:39:12: warning: 'mei_cldev_register_notify' defined but not used [-Wunused-function]
static int mei_cldev_register_notify(struct notifier_block *nb)
^~~~~~~~~~~~~~~~~~~~~~~~~

vim +/mei_cldev_register_notify +49 drivers/misc/mei/hdcp/mei_hdcp.c

48
49 int mei_cldev_register_notify(struct notifier_block *nb)
50 {
51 return blocking_notifier_chain_register(&mei_cldev_notifier_list, nb);
52 }
53 EXPORT_SYMBOL_GPL(mei_cldev_register_notify);
54
55 int mei_cldev_unregister_notify(struct notifier_block *nb)
56 {
57 return blocking_notifier_chain_unregister(&mei_cldev_notifier_list, nb);
58 }
59 EXPORT_SYMBOL_GPL(mei_cldev_unregister_notify);
60

---
0-DAY kernel test infrastructure Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all Intel Corporation
kbuild test robot
2018-04-03 23:58:54 UTC
Permalink
Fixes: ca998fc3888e ("misc/mei/hdcp: Notifier chain for mei cldev state change")
Signed-off-by: Fengguang Wu <***@intel.com>
---
mei_hdcp.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/misc/mei/hdcp/mei_hdcp.c b/drivers/misc/mei/hdcp/mei_hdcp.c
index 2811a25..452e60d 100644
--- a/drivers/misc/mei/hdcp/mei_hdcp.c
+++ b/drivers/misc/mei/hdcp/mei_hdcp.c
@@ -36,7 +36,7 @@

static BLOCKING_NOTIFIER_HEAD(mei_cldev_notifier_list);

-void mei_cldev_state_notify_clients(struct mei_cl_device *cldev, bool enabled)
+static void mei_cldev_state_notify_clients(struct mei_cl_device *cldev, bool enabled)
{
if (enabled)
blocking_notifier_call_chain(&mei_cldev_notifier_list,
Usyskin, Alexander
2018-04-04 06:12:39 UTC
Permalink
-----Original Message-----
From: C, Ramalingam
Sent: Tuesday, April 03, 2018 16:57
Subject: [PATCH v3 05/40] misc/mei/hdcp: Notifier chain for mei cldev state
change
Notifier Chain is defined to inform all its clients about the mei
client device state change. Routine is defined for the clients to
register and unregister for the notification on state change.
Rebased.
Notifier chain is adopted for cldev state update [Tomas]
---
May be I miss something, but bus subsystem already has notifier chain. (BUS_NOTIFY_ADD_DEVICE etc.)
We only ought to make mei_cl_bus_type available in header.
drivers/misc/mei/hdcp/mei_hdcp.c | 36 +++++++++++++++++++++++++++---
include/linux/mei_hdcp.h | 48
++++++++++++++++++++++++++++++++++++++++
2 files changed, 81 insertions(+), 3 deletions(-)
create mode 100644 include/linux/mei_hdcp.h
diff --git a/drivers/misc/mei/hdcp/mei_hdcp.c
b/drivers/misc/mei/hdcp/mei_hdcp.c
index b334615728a7..2811a25f8c57 100644
--- a/drivers/misc/mei/hdcp/mei_hdcp.c
+++ b/drivers/misc/mei/hdcp/mei_hdcp.c
@@ -31,6 +31,32 @@
#include <linux/slab.h>
#include <linux/uuid.h>
#include <linux/mei_cl_bus.h>
+#include <linux/notifier.h>
+#include <linux/mei_hdcp.h>
+
+static BLOCKING_NOTIFIER_HEAD(mei_cldev_notifier_list);
+
+void mei_cldev_state_notify_clients(struct mei_cl_device *cldev, bool enabled)
+{
+ if (enabled)
+ blocking_notifier_call_chain(&mei_cldev_notifier_list,
+ MEI_CLDEV_ENABLED, cldev);
+ else
+ blocking_notifier_call_chain(&mei_cldev_notifier_list,
+ MEI_CLDEV_DISABLED, NULL);
+}
+
+int mei_cldev_register_notify(struct notifier_block *nb)
+{
+ return blocking_notifier_chain_register(&mei_cldev_notifier_list, nb);
+}
+EXPORT_SYMBOL_GPL(mei_cldev_register_notify);
+
+int mei_cldev_unregister_notify(struct notifier_block *nb)
+{
+ return blocking_notifier_chain_unregister(&mei_cldev_notifier_list, nb);
+}
+EXPORT_SYMBOL_GPL(mei_cldev_unregister_notify);
static int mei_hdcp_probe(struct mei_cl_device *cldev,
const struct mei_cl_device_id *id)
@@ -38,14 +64,18 @@ static int mei_hdcp_probe(struct mei_cl_device *cldev,
int ret;
ret = mei_cldev_enable(cldev);
- if (ret < 0)
+ if (ret < 0) {
dev_err(&cldev->dev, "mei_cldev_enable Failed. %d\n", ret);
+ return ret;
+ }
- return ret;
+ mei_cldev_state_notify_clients(cldev, true);
+ return 0;
}
static int mei_hdcp_remove(struct mei_cl_device *cldev)
{
+ mei_cldev_state_notify_clients(cldev, false);
mei_cldev_set_drvdata(cldev, NULL);
return mei_cldev_disable(cldev);
}
@@ -71,4 +101,4 @@ module_mei_cl_driver(mei_hdcp_driver);
MODULE_AUTHOR("Intel Corporation");
MODULE_LICENSE("Dual BSD/GPL");
-MODULE_DESCRIPTION("HDCP");
+MODULE_DESCRIPTION("MEI HDCP");
diff --git a/include/linux/mei_hdcp.h b/include/linux/mei_hdcp.h
new file mode 100644
index 000000000000..3b46bebde718
--- /dev/null
+++ b/include/linux/mei_hdcp.h
@@ -0,0 +1,48 @@
+/* SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) */
+/*
+ * Copyright © 2017-2018 Intel Corporation
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that copyright
+ * notice and this permission notice appear in supporting documentation, and
+ * that the name of the copyright holders not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission. The copyright holders make no representations
+ * about the suitability of this software for any purpose. It is provided "as
+ * is" without express or implied warranty.
+ *
+ * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
FITNESS, IN NO
+ * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING
FROM LOSS OF USE,
+ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
+ * OF THIS SOFTWARE.
+ *
+ */
+
+#ifndef _LINUX_MEI_HDCP_H
+#define _LINUX_MEI_HDCP_H
+
+enum mei_cldev_state {
+ MEI_CLDEV_DISABLED,
+ MEI_CLDEV_ENABLED
+};
+
+#ifdef CONFIG_INTEL_MEI_HDCP
+int mei_cldev_register_notify(struct notifier_block *nb);
+int mei_cldev_unregister_notify(struct notifier_block *nb);
+#else
+static int mei_cldev_register_notify(struct notifier_block *nb)
+{
+ return -ENODEV;
+}
+static int mei_cldev_unregister_notify(struct notifier_block *nb)
+{
+ return -ENODEV;
+}
+#endif /* defined (CONFIG_INTEL_MEI_HDCP) */
+#endif /* defined (_LINUX_MEI_HDCP_H) */
--
2.7.4
Ramalingam C
2018-05-16 13:04:33 UTC
Permalink
Thanks Alexander for the review. Sorry for the delay in addressing the
review comments
Post by Usyskin, Alexander
-----Original Message-----
From: C, Ramalingam
Sent: Tuesday, April 03, 2018 16:57
Subject: [PATCH v3 05/40] misc/mei/hdcp: Notifier chain for mei cldev state
change
Notifier Chain is defined to inform all its clients about the mei
client device state change. Routine is defined for the clients to
register and unregister for the notification on state change.
Rebased.
Notifier chain is adopted for cldev state update [Tomas]
---
May be I miss something, but bus subsystem already has notifier chain. (BUS_NOTIFY_ADD_DEVICE etc.)
We only ought to make mei_cl_bus_type available in header.
We need re notification incase of binding of the mei device happened
well before the I915 init.
This is the case if I915 and MEI HDCP are build as modules and loaded in
order.

So I prefer the separate notifier for mei_hdcp. Hope that is fine.

--Ram
Post by Usyskin, Alexander
drivers/misc/mei/hdcp/mei_hdcp.c | 36 +++++++++++++++++++++++++++---
include/linux/mei_hdcp.h | 48
++++++++++++++++++++++++++++++++++++++++
2 files changed, 81 insertions(+), 3 deletions(-)
create mode 100644 include/linux/mei_hdcp.h
diff --git a/drivers/misc/mei/hdcp/mei_hdcp.c
b/drivers/misc/mei/hdcp/mei_hdcp.c
index b334615728a7..2811a25f8c57 100644
--- a/drivers/misc/mei/hdcp/mei_hdcp.c
+++ b/drivers/misc/mei/hdcp/mei_hdcp.c
@@ -31,6 +31,32 @@
#include <linux/slab.h>
#include <linux/uuid.h>
#include <linux/mei_cl_bus.h>
+#include <linux/notifier.h>
+#include <linux/mei_hdcp.h>
+
+static BLOCKING_NOTIFIER_HEAD(mei_cldev_notifier_list);
+
+void mei_cldev_state_notify_clients(struct mei_cl_device *cldev, bool enabled)
+{
+ if (enabled)
+ blocking_notifier_call_chain(&mei_cldev_notifier_list,
+ MEI_CLDEV_ENABLED, cldev);
+ else
+ blocking_notifier_call_chain(&mei_cldev_notifier_list,
+ MEI_CLDEV_DISABLED, NULL);
+}
+
+int mei_cldev_register_notify(struct notifier_block *nb)
+{
+ return blocking_notifier_chain_register(&mei_cldev_notifier_list, nb);
+}
+EXPORT_SYMBOL_GPL(mei_cldev_register_notify);
+
+int mei_cldev_unregister_notify(struct notifier_block *nb)
+{
+ return blocking_notifier_chain_unregister(&mei_cldev_notifier_list, nb);
+}
+EXPORT_SYMBOL_GPL(mei_cldev_unregister_notify);
static int mei_hdcp_probe(struct mei_cl_device *cldev,
const struct mei_cl_device_id *id)
@@ -38,14 +64,18 @@ static int mei_hdcp_probe(struct mei_cl_device *cldev,
int ret;
ret = mei_cldev_enable(cldev);
- if (ret < 0)
+ if (ret < 0) {
dev_err(&cldev->dev, "mei_cldev_enable Failed. %d\n", ret);
+ return ret;
+ }
- return ret;
+ mei_cldev_state_notify_clients(cldev, true);
+ return 0;
}
static int mei_hdcp_remove(struct mei_cl_device *cldev)
{
+ mei_cldev_state_notify_clients(cldev, false);
mei_cldev_set_drvdata(cldev, NULL);
return mei_cldev_disable(cldev);
}
@@ -71,4 +101,4 @@ module_mei_cl_driver(mei_hdcp_driver);
MODULE_AUTHOR("Intel Corporation");
MODULE_LICENSE("Dual BSD/GPL");
-MODULE_DESCRIPTION("HDCP");
+MODULE_DESCRIPTION("MEI HDCP");
diff --git a/include/linux/mei_hdcp.h b/include/linux/mei_hdcp.h
new file mode 100644
index 000000000000..3b46bebde718
--- /dev/null
+++ b/include/linux/mei_hdcp.h
@@ -0,0 +1,48 @@
+/* SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) */
+/*
+ * Copyright © 2017-2018 Intel Corporation
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that copyright
+ * notice and this permission notice appear in supporting documentation, and
+ * that the name of the copyright holders not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission. The copyright holders make no representations
+ * about the suitability of this software for any purpose. It is provided "as
+ * is" without express or implied warranty.
+ *
+ * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
FITNESS, IN NO
+ * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING
FROM LOSS OF USE,
+ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
+ * OF THIS SOFTWARE.
+ *
+ */
+
+#ifndef _LINUX_MEI_HDCP_H
+#define _LINUX_MEI_HDCP_H
+
+enum mei_cldev_state {
+ MEI_CLDEV_DISABLED,
+ MEI_CLDEV_ENABLED
+};
+
+#ifdef CONFIG_INTEL_MEI_HDCP
+int mei_cldev_register_notify(struct notifier_block *nb);
+int mei_cldev_unregister_notify(struct notifier_block *nb);
+#else
+static int mei_cldev_register_notify(struct notifier_block *nb)
+{
+ return -ENODEV;
+}
+static int mei_cldev_unregister_notify(struct notifier_block *nb)
+{
+ return -ENODEV;
+}
+#endif /* defined (CONFIG_INTEL_MEI_HDCP) */
+#endif /* defined (_LINUX_MEI_HDCP_H) */
--
2.7.4
Ramalingam C
2018-04-03 13:57:19 UTC
Permalink
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.

Signed-off-by: Ramalingam C <***@intel.com>
---
drivers/misc/mei/hdcp/mei_hdcp.h | 415 +++++++++++++++++++++++++++++++++++++++
1 file changed, 415 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..59d8069a8586
--- /dev/null
+++ b/drivers/misc/mei/hdcp/mei_hdcp.h
@@ -0,0 +1,415 @@
+/* SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) */
+/*
+ * Copyright © 2017-2018 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ *
+ * Authors:
+ * 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 each CMD 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 {
+ uint8_t e_kpub_km[HDCP_2_2_E_KPUB_KM_LEN];
+ uint8_t e_kh_km_m[HDCP_2_2_E_KH_KM_M_LEN];
+ struct {
+ uint8_t e_kh_km[HDCP_KH_LEN];
+ uint8_t m[HDCP_M_LEN];
+ } __packed;
+};
+
+/**
+ * HDCP HECI message header. All header values are little endian.
+ */
+struct hdcp_cmd_header {
+ uint32_t api_version;
+ uint32_t command_id;
+ enum me_hdcp_status status;
+ /* Length of the HECI message (excluding the header) */
+ uint32_t 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 {
+ uint8_t integrated_port_type;
+ uint8_t physical_port;
+ uint16_t 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;
+ uint8_t protocol; /* for HDMI vs DP */
+} __packed;
+
+struct wired_cmd_initiate_hdcp2_session_out {
+ struct hdcp_cmd_header header;
+ struct hdcp_port_id port;
+ uint8_t 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;
+ uint8_t r_rx[HDCP_2_2_RRX_LEN];
+ uint8_t 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;
+ uint8_t km_stored;
+ uint8_t 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;
+ uint8_t 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;
+ uint8_t 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;
+ uint8_t 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;
+ uint8_t 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;
+ uint8_t e_dkey_ks[HDCP_2_2_E_DKEY_KS_LEN];
+ uint8_t 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;
+ uint8_t 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;
+ uint8_t rx_info[HDCP_2_2_RXINFO_LEN];
+ uint8_t seq_num_v[HDCP_2_2_SEQ_NUM_LEN];
+ uint8_t v_prime[HDCP_2_2_LPRIME_HALF_LEN];
+ uint8_t 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;
+ uint8_t content_type_supported;
+ uint8_t v[HDCP_2_2_LPRIME_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;
+ uint8_t seq_num_m[HDCP_2_2_SEQ_NUM_LEN];
+ uint8_t m_prime[HDCP_2_2_MPRIME_LEN];
+ uint16_t 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
Ramalingam C
2018-04-03 13:57:20 UTC
Permalink
Data structures and Enum for the I915-MEI_HDCP interface are defined
at <linux/mei_hdcp.h>

v2:
Rebased.
v3:
mei_cl_device is removed from mei_hdcp_data [Tomas]

Signed-off-by: Ramalingam C <***@intel.com>
---
include/linux/mei_hdcp.h | 70 ++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 70 insertions(+)

diff --git a/include/linux/mei_hdcp.h b/include/linux/mei_hdcp.h
index 3b46bebde718..634c1a5bdf1e 100644
--- a/include/linux/mei_hdcp.h
+++ b/include/linux/mei_hdcp.h
@@ -27,11 +27,81 @@
#ifndef _LINUX_MEI_HDCP_H
#define _LINUX_MEI_HDCP_H

+#include <linux/mei_cl_bus.h>
+
enum mei_cldev_state {
MEI_CLDEV_DISABLED,
MEI_CLDEV_ENABLED
};

+/*
+ * Enumeration of the physical DDI available on the platform
+ */
+enum hdcp_physical_port {
+ INVALID_PORT = 0x00, /* Not a valid port */
+
+ DDI_RANGE_BEGIN = 0x01, /* Beginning of the valid DDI port range */
+ DDI_B = 0x01, /* Port DDI B */
+ DDI_C = 0x02, /* Port DDI C */
+ DDI_D = 0x03, /* Port DDI D */
+ DDI_E = 0x04, /* Port DDI E */
+ DDI_F = 0x05, /* Port DDI F */
+ DDI_A = 0x07, /* Port DDI A */
+ DDI_RANGE_END = DDI_A,/* End of the valid DDI port range */
+};
+
+/* The types of HDCP 2.2 ports supported */
+enum hdcp_integrated_port_type {
+ HDCP_INVALID_TYPE = 0x00,
+
+ /* HDCP 2.x ports that are integrated into Intel HW */
+ INTEGRATED = 0x01,
+
+ /* HDCP2.2 discrete wired Tx port with LSPCON (HDMI 2.0) solution */
+ LSPCON = 0x02,
+
+ /* HDCP2.2 discrete wired Tx port using the CPDP (DP 1.3) solution */
+ CPDP = 0x03,
+};
+
+/**
+ * wired_protocol: Supported integrated wired HDCP protocol.
+ * Based on this value, Minor differenceneeded between wired specifications
+ * are handled.
+ */
+enum hdcp_protocol {
+ HDCP_PROTOCOL_INVALID,
+ HDCP_PROTOCOL_HDMI,
+ HDCP_PROTOCOL_DP
+};
+
+/**
+ * mei_hdcp_data: Input data to the mei_hdcp APIs.
+ */
+struct mei_hdcp_data {
+ enum hdcp_physical_port port;
+ enum hdcp_integrated_port_type port_type;
+ enum hdcp_protocol protocol;
+
+ /*
+ * No of streams transmitted on a port.
+ * In case of HDMI & DP SST, single stream will be
+ * transmitted on a port.
+ */
+ uint16_t k;
+
+ /*
+ * 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.
+ */
+ uint32_t seq_num_m;
+
+ /* k(No of Streams per port) x structure of wired_streamid_type */
+ struct hdcp2_streamid_type *streams;
+};
+
#ifdef CONFIG_INTEL_MEI_HDCP
int mei_cldev_register_notify(struct notifier_block *nb);
int mei_cldev_unregister_notify(struct notifier_block *nb);
--
2.7.4
Shankar, Uma
2018-05-09 10:08:46 UTC
Permalink
-----Original Message-----
Ramalingam C
Sent: Tuesday, April 3, 2018 7:27 PM
Subject: [PATCH v3 07/40] linux/mei: Header for mei_hdcp driver interface
Data structures and Enum for the I915-MEI_HDCP interface are defined at
<linux/mei_hdcp.h>
Rebased.
mei_cl_device is removed from mei_hdcp_data [Tomas]
---
include/linux/mei_hdcp.h | 70
++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 70 insertions(+)
diff --git a/include/linux/mei_hdcp.h b/include/linux/mei_hdcp.h index
3b46bebde718..634c1a5bdf1e 100644
--- a/include/linux/mei_hdcp.h
+++ b/include/linux/mei_hdcp.h
@@ -27,11 +27,81 @@
#ifndef _LINUX_MEI_HDCP_H
#define _LINUX_MEI_HDCP_H
+#include <linux/mei_cl_bus.h>
+
enum mei_cldev_state {
MEI_CLDEV_DISABLED,
MEI_CLDEV_ENABLED
};
+/*
+ * Enumeration of the physical DDI available on the platform */ enum
+hdcp_physical_port {
+ INVALID_PORT = 0x00, /* Not a valid port */
+
+ DDI_RANGE_BEGIN = 0x01, /* Beginning of the valid DDI port range */
+ DDI_B = 0x01, /* Port DDI B */
+ DDI_C = 0x02, /* Port DDI C */
+ DDI_D = 0x03, /* Port DDI D */
+ DDI_E = 0x04, /* Port DDI E */
+ DDI_F = 0x05, /* Port DDI F */
+ DDI_A = 0x07, /* Port DDI A */
Why A is made as 0x7. In I915, enum port defines A as 0. Any special reason to
deviate from that ?
+ DDI_RANGE_END = DDI_A,/* End of the valid DDI port range */
+};
+
+/* The types of HDCP 2.2 ports supported */ enum
+hdcp_integrated_port_type {
+ HDCP_INVALID_TYPE = 0x00,
+
+ /* HDCP 2.x ports that are integrated into Intel HW */
+ INTEGRATED = 0x01,
+
+ /* HDCP2.2 discrete wired Tx port with LSPCON (HDMI 2.0) solution */
+ LSPCON = 0x02,
+
+ /* HDCP2.2 discrete wired Tx port using the CPDP (DP 1.3) solution */
+ CPDP = 0x03,
+};
+
+/**
Drop an extra *
+ * wired_protocol: Supported integrated wired HDCP protocol.
+ * Based on this value, Minor differenceneeded between wired
"Add space after differences"
+specifications
+ * are handled.
+ */
+enum hdcp_protocol {
+ HDCP_PROTOCOL_INVALID,
+ HDCP_PROTOCOL_HDMI,
+ HDCP_PROTOCOL_DP
+};
+
+/**
+ * mei_hdcp_data: Input data to the mei_hdcp APIs.
+ */
+struct mei_hdcp_data {
+ enum hdcp_physical_port port;
+ enum hdcp_integrated_port_type port_type;
+ enum hdcp_protocol protocol;
+
+ /*
+ * No of streams transmitted on a port.
+ * In case of HDMI & DP SST, single stream will be
+ * transmitted on a port.
+ */
+ uint16_t k;
+
+ /*
+ * 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.
+ */
+ uint32_t seq_num_m;
+
+ /* k(No of Streams per port) x structure of wired_streamid_type */
+ struct hdcp2_streamid_type *streams;
+};
+
#ifdef CONFIG_INTEL_MEI_HDCP
int mei_cldev_register_notify(struct notifier_block *nb); int
mei_cldev_unregister_notify(struct notifier_block *nb);
--
2.7.4
_______________________________________________
dri-devel mailing list
https://lists.freedesktop.org/mailman/listinfo/dri-devel
Ramalingam C
2018-05-16 15:05:14 UTC
Permalink
Post by Shankar, Uma
-----Original Message-----
Ramalingam C
Sent: Tuesday, April 3, 2018 7:27 PM
Subject: [PATCH v3 07/40] linux/mei: Header for mei_hdcp driver interface
Data structures and Enum for the I915-MEI_HDCP interface are defined at
<linux/mei_hdcp.h>
Rebased.
mei_cl_device is removed from mei_hdcp_data [Tomas]
---
include/linux/mei_hdcp.h | 70
++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 70 insertions(+)
diff --git a/include/linux/mei_hdcp.h b/include/linux/mei_hdcp.h index
3b46bebde718..634c1a5bdf1e 100644
--- a/include/linux/mei_hdcp.h
+++ b/include/linux/mei_hdcp.h
@@ -27,11 +27,81 @@
#ifndef _LINUX_MEI_HDCP_H
#define _LINUX_MEI_HDCP_H
+#include <linux/mei_cl_bus.h>
+
enum mei_cldev_state {
MEI_CLDEV_DISABLED,
MEI_CLDEV_ENABLED
};
+/*
+ * Enumeration of the physical DDI available on the platform */ enum
+hdcp_physical_port {
+ INVALID_PORT = 0x00, /* Not a valid port */
+
+ DDI_RANGE_BEGIN = 0x01, /* Beginning of the valid DDI port range */
+ DDI_B = 0x01, /* Port DDI B */
+ DDI_C = 0x02, /* Port DDI C */
+ DDI_D = 0x03, /* Port DDI D */
+ DDI_E = 0x04, /* Port DDI E */
+ DDI_F = 0x05, /* Port DDI F */
+ DDI_A = 0x07, /* Port DDI A */
Why A is made as 0x7. In I915, enum port defines A as 0. Any special reason to
deviate from that ?
ME FW represent the ports with similar enum. So we have no choice but
translate our port representation to this enum values.
Post by Shankar, Uma
+ DDI_RANGE_END = DDI_A,/* End of the valid DDI port range */
+};
+
+/* The types of HDCP 2.2 ports supported */ enum
+hdcp_integrated_port_type {
+ HDCP_INVALID_TYPE = 0x00,
+
+ /* HDCP 2.x ports that are integrated into Intel HW */
+ INTEGRATED = 0x01,
+
+ /* HDCP2.2 discrete wired Tx port with LSPCON (HDMI 2.0) solution */
+ LSPCON = 0x02,
+
+ /* HDCP2.2 discrete wired Tx port using the CPDP (DP 1.3) solution */
+ CPDP = 0x03,
+};
+
+/**
Drop an extra *
+ * wired_protocol: Supported integrated wired HDCP protocol.
+ * Based on this value, Minor differenceneeded between wired
"Add space after differences"
Sure.

--Ram
Post by Shankar, Uma
+specifications
+ * are handled.
+ */
+enum hdcp_protocol {
+ HDCP_PROTOCOL_INVALID,
+ HDCP_PROTOCOL_HDMI,
+ HDCP_PROTOCOL_DP
+};
+
+/**
+ * mei_hdcp_data: Input data to the mei_hdcp APIs.
+ */
+struct mei_hdcp_data {
+ enum hdcp_physical_port port;
+ enum hdcp_integrated_port_type port_type;
+ enum hdcp_protocol protocol;
+
+ /*
+ * No of streams transmitted on a port.
+ * In case of HDMI & DP SST, single stream will be
+ * transmitted on a port.
+ */
+ uint16_t k;
+
+ /*
+ * 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.
+ */
+ uint32_t seq_num_m;
+
+ /* k(No of Streams per port) x structure of wired_streamid_type */
+ struct hdcp2_streamid_type *streams;
+};
+
#ifdef CONFIG_INTEL_MEI_HDCP
int mei_cldev_register_notify(struct notifier_block *nb); int
mei_cldev_unregister_notify(struct notifier_block *nb);
--
2.7.4
_______________________________________________
dri-devel mailing list
https://lists.freedesktop.org/mailman/listinfo/dri-devel
Ramalingam C
2018-04-03 13:57:23 UTC
Permalink
Requests for the verifcation of AKE_Send_H_prime.

ME will calculation the H and comparing it with received H_Prime.
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]

Signed-off-by: Ramalingam C <***@intel.com>
---
drivers/misc/mei/hdcp/mei_hdcp.c | 58 ++++++++++++++++++++++++++++++++++++++++
include/linux/mei_hdcp.h | 8 ++++++
2 files changed, 66 insertions(+)

diff --git a/drivers/misc/mei/hdcp/mei_hdcp.c b/drivers/misc/mei/hdcp/mei_hdcp.c
index 181994529058..fa548310de7a 100644
--- a/drivers/misc/mei/hdcp/mei_hdcp.c
+++ b/drivers/misc/mei/hdcp/mei_hdcp.c
@@ -186,6 +186,64 @@ mei_verify_receiver_cert_prepare_km(struct mei_cl_device *cldev,
}
EXPORT_SYMBOL(mei_verify_receiver_cert_prepare_km);

+/**
+ * mei_verify_hprime:
+ * Function to verify AKE_Send_H_prime received
+ *
+ * @cldev : Pointer for mei client device
+ * @data : Intel HW specific Data
+ * @rx_hprime : Pointer for AKE_Send_H_prime
+ * @hprime_sz : Input buffer size
+ *
+ * Returns 0 on Success, <0 on Failure
+ */
+int mei_verify_hprime(struct mei_cl_device *cldev, struct mei_hdcp_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 device *dev;
+ ssize_t byte;
+
+ if (!data || !rx_hprime)
+ return -EINVAL;
+
+ dev = &cldev->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 = data->port;
+
+ memcpy(send_hprime_in.h_prime, rx_hprime->h_prime,
+ sizeof(rx_hprime->h_prime));
+
+ byte = mei_cldev_send(cldev, (u8 *)&send_hprime_in,
+ sizeof(send_hprime_in));
+ if (byte < 0) {
+ dev_dbg(dev, "mei_cldev_send failed. %d\n", (int)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. %d\n", (int)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 -1;
+ }
+ return 0;
+}
+EXPORT_SYMBOL(mei_verify_hprime);
+
void mei_cldev_state_notify_clients(struct mei_cl_device *cldev, bool enabled)
{
if (enabled)
diff --git a/include/linux/mei_hdcp.h b/include/linux/mei_hdcp.h
index 314b15f6afc0..00bfde251ba4 100644
--- a/include/linux/mei_hdcp.h
+++ b/include/linux/mei_hdcp.h
@@ -116,6 +116,8 @@ mei_verify_receiver_cert_prepare_km(struct mei_cl_device *cldev,
bool *km_stored,
struct hdcp2_ake_no_stored_km *ek_pub_km,
size_t *msg_sz);
+int mei_verify_hprime(struct mei_cl_device *cldev, struct mei_hdcp_data *data,
+ struct hdcp2_ake_send_hprime *rx_hprime);
#else
static int mei_cldev_register_notify(struct notifier_block *nb)
{
@@ -142,5 +144,11 @@ mei_verify_receiver_cert_prepare_km(struct mei_cl_device *cldev,
{
return -ENODEV;
}
+static inline
+int mei_verify_hprime(struct mei_cl_device *cldev, struct mei_hdcp_data *data,
+ struct hdcp2_ake_send_hprime *rx_hprime)
+{
+ return -ENODEV;
+}
#endif /* defined (CONFIG_INTEL_MEI_HDCP) */
#endif /* defined (_LINUX_MEI_HDCP_H) */
--
2.7.4
kbuild test robot
2018-04-03 22:12:21 UTC
Permalink
Hi Ramalingam,

Thank you for the patch! Yet something to improve:

[auto build test ERROR on drm-intel/for-linux-next]
[also build test ERROR on next-20180403]
[cannot apply to v4.16]
[if your patch is applied to the wrong git tree, please drop us a note to help improve the system]

url: https://github.com/0day-ci/linux/commits/Ramalingam-C/drm-i915-Implement-HDCP2-2/20180404-031743
base: git://anongit.freedesktop.org/drm-intel for-linux-next
config: i386-allmodconfig (attached as .config)
compiler: gcc-7 (Debian 7.3.0-1) 7.3.0
reproduce:
# save the attached .config to linux build tree
make ARCH=i386

All errors (new ones prefixed by >>):

drivers/misc/mei/hdcp/mei_hdcp.c:52:5: error: redefinition of 'mei_initiate_hdcp2_session'
int mei_initiate_hdcp2_session(struct mei_cl_device *cldev,
^~~~~~~~~~~~~~~~~~~~~~~~~~
In file included from drivers/misc/mei/hdcp/mei_hdcp.c:35:0:
include/linux/mei_hdcp.h:131:5: note: previous definition of 'mei_initiate_hdcp2_session' was here
int mei_initiate_hdcp2_session(struct mei_cl_device *cldev,
^~~~~~~~~~~~~~~~~~~~~~~~~~
drivers/misc/mei/hdcp/mei_hdcp.c:122:1: error: redefinition of 'mei_verify_receiver_cert_prepare_km'
mei_verify_receiver_cert_prepare_km(struct mei_cl_device *cldev,
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
In file included from drivers/misc/mei/hdcp/mei_hdcp.c:35:0:
include/linux/mei_hdcp.h:138:1: note: previous definition of 'mei_verify_receiver_cert_prepare_km' was here
mei_verify_receiver_cert_prepare_km(struct mei_cl_device *cldev,
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
drivers/misc/mei/hdcp/mei_hdcp.c:200:5: error: redefinition of 'mei_verify_hprime'
int mei_verify_hprime(struct mei_cl_device *cldev, struct mei_hdcp_data *data,
^~~~~~~~~~~~~~~~~
In file included from drivers/misc/mei/hdcp/mei_hdcp.c:35:0:
include/linux/mei_hdcp.h:148:5: note: previous definition of 'mei_verify_hprime' was here
int mei_verify_hprime(struct mei_cl_device *cldev, struct mei_hdcp_data *data,
^~~~~~~~~~~~~~~~~
drivers/misc/mei/hdcp/mei_hdcp.c:257:5: error: redefinition of 'mei_cldev_register_notify'
int mei_cldev_register_notify(struct notifier_block *nb)
^~~~~~~~~~~~~~~~~~~~~~~~~
In file included from drivers/misc/mei/hdcp/mei_hdcp.c:35:0:
include/linux/mei_hdcp.h:122:12: note: previous definition of 'mei_cldev_register_notify' was here
static int mei_cldev_register_notify(struct notifier_block *nb)
^~~~~~~~~~~~~~~~~~~~~~~~~
drivers/misc/mei/hdcp/mei_hdcp.c:263:5: error: redefinition of 'mei_cldev_unregister_notify'
int mei_cldev_unregister_notify(struct notifier_block *nb)
^~~~~~~~~~~~~~~~~~~~~~~~~~~
In file included from drivers/misc/mei/hdcp/mei_hdcp.c:35:0:
include/linux/mei_hdcp.h:126:12: note: previous definition of 'mei_cldev_unregister_notify' was here
static int mei_cldev_unregister_notify(struct notifier_block *nb)
^~~~~~~~~~~~~~~~~~~~~~~~~~~
include/linux/mei_hdcp.h:126:12: warning: 'mei_cldev_unregister_notify' defined but not used [-Wunused-function]
include/linux/mei_hdcp.h:122:12: warning: 'mei_cldev_register_notify' defined but not used [-Wunused-function]
static int mei_cldev_register_notify(struct notifier_block *nb)
^~~~~~~~~~~~~~~~~~~~~~~~~

vim +/mei_verify_hprime +200 drivers/misc/mei/hdcp/mei_hdcp.c

106
107 /**
108 * mei_verify_receiver_cert_prepare_km:
109 * Function to verify the Receiver Certificate AKE_Send_Cert
110 * and prepare AKE_Stored_Km or AKE_No_Stored_Km
111 *
112 * @cldev : Pointer for mei client device
113 * @data : Intel HW specific Data
114 * @rx_cert : Pointer for AKE_Send_Cert
115 * @km_stored : Pointer for pairing status flag
116 * @ek_pub_km : Pointer for output msg
117 * @msg_sz : Pointer for size of AKE_XXXXX_Km
118 *
119 * Returns 0 on Success, <0 on Failure
120 */
121 int
122 mei_verify_receiver_cert_prepare_km(struct mei_cl_device *cldev,
123 struct mei_hdcp_data *data,
124 struct hdcp2_ake_send_cert *rx_cert,
125 bool *km_stored,
126 struct hdcp2_ake_no_stored_km *ek_pub_km,
127 size_t *msg_sz)
128 {
129 struct wired_cmd_verify_receiver_cert_in verify_rxcert_in = { { 0 } };
130 struct wired_cmd_verify_receiver_cert_out verify_rxcert_out = { { 0 } };
131 struct device *dev;
132 ssize_t byte;
133
134 if (!data || !rx_cert || !km_stored || !ek_pub_km || !msg_sz)
135 return -EINVAL;
136
137 dev = &cldev->dev;
138
139 verify_rxcert_in.header.api_version = HDCP_API_VERSION;
140 verify_rxcert_in.header.command_id = WIRED_VERIFY_RECEIVER_CERT;
141 verify_rxcert_in.header.status = ME_HDCP_STATUS_SUCCESS;
142 verify_rxcert_in.header.buffer_len =
143 WIRED_CMD_BUF_LEN_VERIFY_RECEIVER_CERT_IN;
144
145 verify_rxcert_in.port.integrated_port_type = data->port_type;
146 verify_rxcert_in.port.physical_port = data->port;
147
148 memcpy(&verify_rxcert_in.cert_rx, &rx_cert->cert_rx,
149 sizeof(rx_cert->cert_rx));
150 memcpy(verify_rxcert_in.r_rx, &rx_cert->r_rx, sizeof(rx_cert->r_rx));
151 memcpy(verify_rxcert_in.rx_caps, rx_cert->rx_caps, HDCP_2_2_RXCAPS_LEN);
152
153 byte = mei_cldev_send(cldev, (u8 *)&verify_rxcert_in,
154 sizeof(verify_rxcert_in));
155 if (byte < 0) {
156 dev_dbg(dev, "mei_cldev_send failed: %d\n", (int)byte);
157 return byte;
158 }
159
160 byte = mei_cldev_recv(cldev, (u8 *)&verify_rxcert_out,
161 sizeof(verify_rxcert_out));
162 if (byte < 0) {
163 dev_dbg(dev, "mei_cldev_recv failed: %d\n", (int)byte);
164 return byte;
165 }
166
167 if (verify_rxcert_out.header.status != ME_HDCP_STATUS_SUCCESS) {
168 dev_dbg(dev, "ME cmd 0x%08X Failed. Status: 0x%X\n",
169 WIRED_VERIFY_RECEIVER_CERT,
170 verify_rxcert_out.header.status);
171 return -1;
172 }
173
174 *km_stored = verify_rxcert_out.km_stored;
175 if (verify_rxcert_out.km_stored) {
176 ek_pub_km->msg_id = HDCP_2_2_AKE_STORED_KM;
177 *msg_sz = sizeof(struct hdcp2_ake_stored_km);
178 } else {
179 ek_pub_km->msg_id = HDCP_2_2_AKE_NO_STORED_KM;
180 *msg_sz = sizeof(struct hdcp2_ake_no_stored_km);
181 }
182
183 memcpy(ek_pub_km->e_kpub_km, &verify_rxcert_out.ekm_buff,
184 sizeof(verify_rxcert_out.ekm_buff));
185 return 0;
186 }
187 EXPORT_SYMBOL(mei_verify_receiver_cert_prepare_km);
188
189 /**
190 * mei_verify_hprime:
191 * Function to verify AKE_Send_H_prime received
192 *
193 * @cldev : Pointer for mei client device
194 * @data : Intel HW specific Data
195 * @rx_hprime : Pointer for AKE_Send_H_prime
196 * @hprime_sz : Input buffer size
197 *
198 * Returns 0 on Success, <0 on Failure
199 */
200 int mei_verify_hprime(struct mei_cl_device *cldev, struct mei_hdcp_data *data,
201 struct hdcp2_ake_send_hprime *rx_hprime)
202 {
203 struct wired_cmd_ake_send_hprime_in send_hprime_in = { { 0 } };
204 struct wired_cmd_ake_send_hprime_out send_hprime_out = { { 0 } };
205 struct device *dev;
206 ssize_t byte;
207
208 if (!data || !rx_hprime)
209 return -EINVAL;
210
211 dev = &cldev->dev;
212
213 send_hprime_in.header.api_version = HDCP_API_VERSION;
214 send_hprime_in.header.command_id = WIRED_AKE_SEND_HPRIME;
215 send_hprime_in.header.status = ME_HDCP_STATUS_SUCCESS;
216 send_hprime_in.header.buffer_len = WIRED_CMD_BUF_LEN_AKE_SEND_HPRIME_IN;
217
218 send_hprime_in.port.integrated_port_type = data->port_type;
219 send_hprime_in.port.physical_port = data->port;
220
221 memcpy(send_hprime_in.h_prime, rx_hprime->h_prime,
222 sizeof(rx_hprime->h_prime));
223
224 byte = mei_cldev_send(cldev, (u8 *)&send_hprime_in,
225 sizeof(send_hprime_in));
226 if (byte < 0) {
227 dev_dbg(dev, "mei_cldev_send failed. %d\n", (int)byte);
228 return byte;
229 }
230
231 byte = mei_cldev_recv(cldev, (u8 *)&send_hprime_out,
232 sizeof(send_hprime_out));
233 if (byte < 0) {
234 dev_dbg(dev, "mei_cldev_recv failed. %d\n", (int)byte);
235 return byte;
236 }
237
238 if (send_hprime_out.header.status != ME_HDCP_STATUS_SUCCESS) {
239 dev_dbg(dev, "ME cmd 0x%08X Failed. Status: 0x%X\n",
240 WIRED_AKE_SEND_HPRIME, send_hprime_out.header.status);
241 return -1;
242 }
243 return 0;
244 }
245 EXPORT_SYMBOL(mei_verify_hprime);
246

---
0-DAY kernel test infrastructure Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all Intel Corporation
Shankar, Uma
2018-05-09 10:16:03 UTC
Permalink
-----Original Message-----
Ramalingam C
Sent: Tuesday, April 3, 2018 7:27 PM
Subject: [Intel-gfx] [PATCH v3 10/40] misc/mei/hdcp: Verify H_prime
Requests for the verifcation of AKE_Send_H_prime.
Typo in verification.
ME will calculation the H and comparing it with received H_Prime.
Change to "calculate". Also change "comparing" to "compares".
Here AKE_Send_H_prime is a HDCP2.2 Authentication msg.
Rebased.
cldev is passed as first parameter [Tomas]
Redundant comments and cast are removed [Tomas]
---
drivers/misc/mei/hdcp/mei_hdcp.c | 58
++++++++++++++++++++++++++++++++++++++++
include/linux/mei_hdcp.h | 8 ++++++
2 files changed, 66 insertions(+)
diff --git a/drivers/misc/mei/hdcp/mei_hdcp.c
b/drivers/misc/mei/hdcp/mei_hdcp.c
index 181994529058..fa548310de7a 100644
--- a/drivers/misc/mei/hdcp/mei_hdcp.c
+++ b/drivers/misc/mei/hdcp/mei_hdcp.c
@@ -186,6 +186,64 @@ mei_verify_receiver_cert_prepare_km(struct
mei_cl_device *cldev, }
EXPORT_SYMBOL(mei_verify_receiver_cert_prepare_km);
+/**
+ * Function to verify AKE_Send_H_prime received
+ *
+ *
+ * Returns 0 on Success, <0 on Failure
+ */
+int mei_verify_hprime(struct mei_cl_device *cldev, struct mei_hdcp_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 device *dev;
+ ssize_t byte;
+
+ if (!data || !rx_hprime)
+ return -EINVAL;
+
+ dev = &cldev->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 = data->port;
+
+ memcpy(send_hprime_in.h_prime, rx_hprime->h_prime,
Need to validate rx_hprime->h_prime for NULL.
+ sizeof(rx_hprime->h_prime));
+
+ byte = mei_cldev_send(cldev, (u8 *)&send_hprime_in,
+ sizeof(send_hprime_in));
+ if (byte < 0) {
+ dev_dbg(dev, "mei_cldev_send failed. %d\n", (int)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. %d\n", (int)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 -1;
+ }
Leave a blank line here.
+ return 0;
One clarification required - the h prime value sent and received are not compared here. So, whether
hw matches them and returns success only if they match or it just returns the H prime value
and driver should compare ?
+}
+EXPORT_SYMBOL(mei_verify_hprime);
+
void mei_cldev_state_notify_clients(struct mei_cl_device *cldev, bool enabled) {
if (enabled)
diff --git a/include/linux/mei_hdcp.h b/include/linux/mei_hdcp.h index
314b15f6afc0..00bfde251ba4 100644
--- a/include/linux/mei_hdcp.h
+++ b/include/linux/mei_hdcp.h
@@ -116,6 +116,8 @@ mei_verify_receiver_cert_prepare_km(struct
mei_cl_device *cldev,
bool *km_stored,
struct hdcp2_ake_no_stored_km
*ek_pub_km,
size_t *msg_sz);
+int mei_verify_hprime(struct mei_cl_device *cldev, struct mei_hdcp_data *data,
+ struct hdcp2_ake_send_hprime *rx_hprime);
#else
{
return -ENODEV;
}
+static inline
+int mei_verify_hprime(struct mei_cl_device *cldev, struct mei_hdcp_data *data,
+ struct hdcp2_ake_send_hprime *rx_hprime) {
+ return -ENODEV;
+}
#endif /* defined (CONFIG_INTEL_MEI_HDCP) */ #endif /* defined
(_LINUX_MEI_HDCP_H) */
--
2.7.4
_______________________________________________
Intel-gfx mailing list
https://lists.freedesktop.org/mailman/listinfo/intel-gfx
Ramalingam C
2018-05-16 15:43:27 UTC
Permalink
Post by Shankar, Uma
-----Original Message-----
Ramalingam C
Sent: Tuesday, April 3, 2018 7:27 PM
Subject: [Intel-gfx] [PATCH v3 10/40] misc/mei/hdcp: Verify H_prime
Requests for the verifcation of AKE_Send_H_prime.
Typo in verification.
thanks :)
Post by Shankar, Uma
ME will calculation the H and comparing it with received H_Prime.
Change to "calculate". Also change "comparing" to "compares".
Here AKE_Send_H_prime is a HDCP2.2 Authentication msg.
Rebased.
cldev is passed as first parameter [Tomas]
Redundant comments and cast are removed [Tomas]
---
drivers/misc/mei/hdcp/mei_hdcp.c | 58
++++++++++++++++++++++++++++++++++++++++
include/linux/mei_hdcp.h | 8 ++++++
2 files changed, 66 insertions(+)
diff --git a/drivers/misc/mei/hdcp/mei_hdcp.c
b/drivers/misc/mei/hdcp/mei_hdcp.c
index 181994529058..fa548310de7a 100644
--- a/drivers/misc/mei/hdcp/mei_hdcp.c
+++ b/drivers/misc/mei/hdcp/mei_hdcp.c
@@ -186,6 +186,64 @@ mei_verify_receiver_cert_prepare_km(struct
mei_cl_device *cldev, }
EXPORT_SYMBOL(mei_verify_receiver_cert_prepare_km);
+/**
+ * Function to verify AKE_Send_H_prime received
+ *
+ *
+ * Returns 0 on Success, <0 on Failure
+ */
+int mei_verify_hprime(struct mei_cl_device *cldev, struct mei_hdcp_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 device *dev;
+ ssize_t byte;
+
+ if (!data || !rx_hprime)
+ return -EINVAL;
+
+ dev = &cldev->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 = data->port;
+
+ memcpy(send_hprime_in.h_prime, rx_hprime->h_prime,
Need to validate rx_hprime->h_prime for NULL.
h_prime is statically allocated array within rx_hprime. So we need not
check .
Post by Shankar, Uma
+ sizeof(rx_hprime->h_prime));
+
+ byte = mei_cldev_send(cldev, (u8 *)&send_hprime_in,
+ sizeof(send_hprime_in));
+ if (byte < 0) {
+ dev_dbg(dev, "mei_cldev_send failed. %d\n", (int)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. %d\n", (int)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 -1;
+ }
Leave a blank line here.
Sure.
Post by Shankar, Uma
+ return 0;
One clarification required - the h prime value sent and received are not compared here. So, whether
hw matches them and returns success only if they match or it just returns the H prime value
and driver should compare ?
This shows that commit message need an edit :). Yes, ME FW calculate the
hprime and compare it with the received hprime.
Returns the comparition result at send_hprime_out.header.status.

--Ram
Post by Shankar, Uma
+}
+EXPORT_SYMBOL(mei_verify_hprime);
+
void mei_cldev_state_notify_clients(struct mei_cl_device *cldev, bool enabled) {
if (enabled)
diff --git a/include/linux/mei_hdcp.h b/include/linux/mei_hdcp.h index
314b15f6afc0..00bfde251ba4 100644
--- a/include/linux/mei_hdcp.h
+++ b/include/linux/mei_hdcp.h
@@ -116,6 +116,8 @@ mei_verify_receiver_cert_prepare_km(struct mei_cl_device *cldev,
bool *km_stored,
struct hdcp2_ake_no_stored_km
*ek_pub_km,
size_t *msg_sz);
+int mei_verify_hprime(struct mei_cl_device *cldev, struct mei_hdcp_data *data,
+ struct hdcp2_ake_send_hprime *rx_hprime);
#else
{
return -ENODEV;
}
+static inline
+int mei_verify_hprime(struct mei_cl_device *cldev, struct mei_hdcp_data *data,
+ struct hdcp2_ake_send_hprime *rx_hprime) {
+ return -ENODEV;
+}
#endif /* defined (CONFIG_INTEL_MEI_HDCP) */ #endif /* defined
(_LINUX_MEI_HDCP_H) */
--
2.7.4
_______________________________________________
Intel-gfx mailing list
https://lists.freedesktop.org/mailman/listinfo/intel-gfx
Ramalingam C
2018-04-03 13:57:24 UTC
Permalink
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]

Signed-off-by: Ramalingam C <***@intel.com>
---
drivers/misc/mei/hdcp/mei_hdcp.c | 61 ++++++++++++++++++++++++++++++++++++++++
include/linux/mei_hdcp.h | 10 +++++++
2 files changed, 71 insertions(+)

diff --git a/drivers/misc/mei/hdcp/mei_hdcp.c b/drivers/misc/mei/hdcp/mei_hdcp.c
index fa548310de7a..60afdd0cee79 100644
--- a/drivers/misc/mei/hdcp/mei_hdcp.c
+++ b/drivers/misc/mei/hdcp/mei_hdcp.c
@@ -244,6 +244,67 @@ int mei_verify_hprime(struct mei_cl_device *cldev, struct mei_hdcp_data *data,
}
EXPORT_SYMBOL(mei_verify_hprime);

+/**
+ * mei_store_pairing_info:
+ * Function to store pairing info received from panel
+ *
+ * @cldev : Pointer for mei client device
+ * @data : Intel HW specific Data
+ * @pairing_info : Pointer for AKE_Send_Pairing_Info
+ *
+ * Returns 0 on Success, <0 on Failure
+ */
+
+int mei_store_pairing_info(struct mei_cl_device *cldev,
+ struct mei_hdcp_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 device *dev;
+ ssize_t byte;
+
+ if (!data || !pairing_info)
+ return -EINVAL;
+
+ dev = &cldev->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 = data->port;
+
+ memcpy(pairing_info_in.e_kh_km, pairing_info->e_kh_km,
+ sizeof(pairing_info_in.e_kh_km));
+
+ byte = mei_cldev_send(cldev, (u8 *)&pairing_info_in,
+ sizeof(pairing_info_in));
+ if (byte < 0) {
+ dev_dbg(dev, "mei_cldev_send failed. %d\n", (int)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. %d\n", (int)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 -1;
+ }
+ return 0;
+}
+EXPORT_SYMBOL(mei_store_pairing_info);
+
void mei_cldev_state_notify_clients(struct mei_cl_device *cldev, bool enabled)
{
if (enabled)
diff --git a/include/linux/mei_hdcp.h b/include/linux/mei_hdcp.h
index 00bfde251ba4..be16e49d8018 100644
--- a/include/linux/mei_hdcp.h
+++ b/include/linux/mei_hdcp.h
@@ -118,6 +118,9 @@ mei_verify_receiver_cert_prepare_km(struct mei_cl_device *cldev,
size_t *msg_sz);
int mei_verify_hprime(struct mei_cl_device *cldev, struct mei_hdcp_data *data,
struct hdcp2_ake_send_hprime *rx_hprime);
+int mei_store_pairing_info(struct mei_cl_device *cldev,
+ struct mei_hdcp_data *data,
+ struct hdcp2_ake_send_pairing_info *pairing_info);
#else
static int mei_cldev_register_notify(struct notifier_block *nb)
{
@@ -150,5 +153,12 @@ int mei_verify_hprime(struct mei_cl_device *cldev, struct mei_hdcp_data *data,
{
return -ENODEV;
}
+static inline
+int mei_store_pairing_info(struct mei_cl_device *cldev,
+ struct mei_hdcp_data *data,
+ struct hdcp2_ake_send_pairing_info *pairing_info)
+{
+ return -ENODEV;
+}
#endif /* defined (CONFIG_INTEL_MEI_HDCP) */
#endif /* defined (_LINUX_MEI_HDCP_H) */
--
2.7.4
kbuild test robot
2018-04-03 22:34:41 UTC
Permalink
Hi Ramalingam,

Thank you for the patch! Yet something to improve:

[auto build test ERROR on drm-intel/for-linux-next]
[also build test ERROR on next-20180403]
[cannot apply to v4.16]
[if your patch is applied to the wrong git tree, please drop us a note to help improve the system]

url: https://github.com/0day-ci/linux/commits/Ramalingam-C/drm-i915-Implement-HDCP2-2/20180404-031743
base: git://anongit.freedesktop.org/drm-intel for-linux-next
config: i386-allmodconfig (attached as .config)
compiler: gcc-7 (Debian 7.3.0-1) 7.3.0
reproduce:
# save the attached .config to linux build tree
make ARCH=i386

All errors (new ones prefixed by >>):

drivers/misc/mei/hdcp/mei_hdcp.c:52:5: error: redefinition of 'mei_initiate_hdcp2_session'
int mei_initiate_hdcp2_session(struct mei_cl_device *cldev,
^~~~~~~~~~~~~~~~~~~~~~~~~~
In file included from drivers/misc/mei/hdcp/mei_hdcp.c:35:0:
include/linux/mei_hdcp.h:134:5: note: previous definition of 'mei_initiate_hdcp2_session' was here
int mei_initiate_hdcp2_session(struct mei_cl_device *cldev,
^~~~~~~~~~~~~~~~~~~~~~~~~~
drivers/misc/mei/hdcp/mei_hdcp.c:122:1: error: redefinition of 'mei_verify_receiver_cert_prepare_km'
mei_verify_receiver_cert_prepare_km(struct mei_cl_device *cldev,
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
In file included from drivers/misc/mei/hdcp/mei_hdcp.c:35:0:
include/linux/mei_hdcp.h:141:1: note: previous definition of 'mei_verify_receiver_cert_prepare_km' was here
mei_verify_receiver_cert_prepare_km(struct mei_cl_device *cldev,
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
drivers/misc/mei/hdcp/mei_hdcp.c:200:5: error: redefinition of 'mei_verify_hprime'
int mei_verify_hprime(struct mei_cl_device *cldev, struct mei_hdcp_data *data,
^~~~~~~~~~~~~~~~~
In file included from drivers/misc/mei/hdcp/mei_hdcp.c:35:0:
include/linux/mei_hdcp.h:151:5: note: previous definition of 'mei_verify_hprime' was here
int mei_verify_hprime(struct mei_cl_device *cldev, struct mei_hdcp_data *data,
^~~~~~~~~~~~~~~~~
drivers/misc/mei/hdcp/mei_hdcp.c:258:5: error: redefinition of 'mei_store_pairing_info'
int mei_store_pairing_info(struct mei_cl_device *cldev,
^~~~~~~~~~~~~~~~~~~~~~
In file included from drivers/misc/mei/hdcp/mei_hdcp.c:35:0:
include/linux/mei_hdcp.h:157:5: note: previous definition of 'mei_store_pairing_info' was here
int mei_store_pairing_info(struct mei_cl_device *cldev,
^~~~~~~~~~~~~~~~~~~~~~
drivers/misc/mei/hdcp/mei_hdcp.c:318:5: error: redefinition of 'mei_cldev_register_notify'
int mei_cldev_register_notify(struct notifier_block *nb)
^~~~~~~~~~~~~~~~~~~~~~~~~
In file included from drivers/misc/mei/hdcp/mei_hdcp.c:35:0:
include/linux/mei_hdcp.h:125:12: note: previous definition of 'mei_cldev_register_notify' was here
static int mei_cldev_register_notify(struct notifier_block *nb)
^~~~~~~~~~~~~~~~~~~~~~~~~
drivers/misc/mei/hdcp/mei_hdcp.c:324:5: error: redefinition of 'mei_cldev_unregister_notify'
int mei_cldev_unregister_notify(struct notifier_block *nb)
^~~~~~~~~~~~~~~~~~~~~~~~~~~
In file included from drivers/misc/mei/hdcp/mei_hdcp.c:35:0:
include/linux/mei_hdcp.h:129:12: note: previous definition of 'mei_cldev_unregister_notify' was here
static int mei_cldev_unregister_notify(struct notifier_block *nb)
^~~~~~~~~~~~~~~~~~~~~~~~~~~
include/linux/mei_hdcp.h:129:12: warning: 'mei_cldev_unregister_notify' defined but not used [-Wunused-function]
include/linux/mei_hdcp.h:125:12: warning: 'mei_cldev_register_notify' defined but not used [-Wunused-function]
static int mei_cldev_register_notify(struct notifier_block *nb)
^~~~~~~~~~~~~~~~~~~~~~~~~

vim +/mei_store_pairing_info +258 drivers/misc/mei/hdcp/mei_hdcp.c

188
189 /**
190 * mei_verify_hprime:
191 * Function to verify AKE_Send_H_prime received
192 *
193 * @cldev : Pointer for mei client device
194 * @data : Intel HW specific Data
195 * @rx_hprime : Pointer for AKE_Send_H_prime
196 * @hprime_sz : Input buffer size
197 *
198 * Returns 0 on Success, <0 on Failure
199 */
200 int mei_verify_hprime(struct mei_cl_device *cldev, struct mei_hdcp_data *data,
201 struct hdcp2_ake_send_hprime *rx_hprime)
202 {
203 struct wired_cmd_ake_send_hprime_in send_hprime_in = { { 0 } };
204 struct wired_cmd_ake_send_hprime_out send_hprime_out = { { 0 } };
205 struct device *dev;
206 ssize_t byte;
207
208 if (!data || !rx_hprime)
209 return -EINVAL;
210
211 dev = &cldev->dev;
212
213 send_hprime_in.header.api_version = HDCP_API_VERSION;
214 send_hprime_in.header.command_id = WIRED_AKE_SEND_HPRIME;
215 send_hprime_in.header.status = ME_HDCP_STATUS_SUCCESS;
216 send_hprime_in.header.buffer_len = WIRED_CMD_BUF_LEN_AKE_SEND_HPRIME_IN;
217
218 send_hprime_in.port.integrated_port_type = data->port_type;
219 send_hprime_in.port.physical_port = data->port;
220
221 memcpy(send_hprime_in.h_prime, rx_hprime->h_prime,
222 sizeof(rx_hprime->h_prime));
223
224 byte = mei_cldev_send(cldev, (u8 *)&send_hprime_in,
225 sizeof(send_hprime_in));
226 if (byte < 0) {
227 dev_dbg(dev, "mei_cldev_send failed. %d\n", (int)byte);
228 return byte;
229 }
230
231 byte = mei_cldev_recv(cldev, (u8 *)&send_hprime_out,
232 sizeof(send_hprime_out));
233 if (byte < 0) {
234 dev_dbg(dev, "mei_cldev_recv failed. %d\n", (int)byte);
235 return byte;
236 }
237
238 if (send_hprime_out.header.status != ME_HDCP_STATUS_SUCCESS) {
239 dev_dbg(dev, "ME cmd 0x%08X Failed. Status: 0x%X\n",
240 WIRED_AKE_SEND_HPRIME, send_hprime_out.header.status);
241 return -1;
242 }
243 return 0;
244 }
245 EXPORT_SYMBOL(mei_verify_hprime);
246
247 /**
248 * mei_store_pairing_info:
249 * Function to store pairing info received from panel
250 *
251 * @cldev : Pointer for mei client device
252 * @data : Intel HW specific Data
253 * @pairing_info : Pointer for AKE_Send_Pairing_Info
254 *
255 * Returns 0 on Success, <0 on Failure
256 */
257
258 int mei_store_pairing_info(struct mei_cl_device *cldev,
259 struct mei_hdcp_data *data,
260 struct hdcp2_ake_send_pairing_info *pairing_info)
261 {
262 struct wired_cmd_ake_send_pairing_info_in pairing_info_in = { { 0 } };
263 struct wired_cmd_ake_send_pairing_info_out pairing_info_out = { { 0 } };
264 struct device *dev;
265 ssize_t byte;
266
267 if (!data || !pairing_info)
268 return -EINVAL;
269
270 dev = &cldev->dev;
271
272 pairing_info_in.header.api_version = HDCP_API_VERSION;
273 pairing_info_in.header.command_id = WIRED_AKE_SEND_PAIRING_INFO;
274 pairing_info_in.header.status = ME_HDCP_STATUS_SUCCESS;
275 pairing_info_in.header.buffer_len =
276 WIRED_CMD_BUF_LEN_SEND_PAIRING_INFO_IN;
277
278 pairing_info_in.port.integrated_port_type = data->port_type;
279 pairing_info_in.port.physical_port = data->port;
280
281 memcpy(pairing_info_in.e_kh_km, pairing_info->e_kh_km,
282 sizeof(pairing_info_in.e_kh_km));
283
284 byte = mei_cldev_send(cldev, (u8 *)&pairing_info_in,
285 sizeof(pairing_info_in));
286 if (byte < 0) {
287 dev_dbg(dev, "mei_cldev_send failed. %d\n", (int)byte);
288 return byte;
289 }
290
291 byte = mei_cldev_recv(cldev, (u8 *)&pairing_info_out,
292 sizeof(pairing_info_out));
293 if (byte < 0) {
294 dev_dbg(dev, "mei_cldev_recv failed. %d\n", (int)byte);
295 return byte;
296 }
297
298 if (pairing_info_out.header.status != ME_HDCP_STATUS_SUCCESS) {
299 dev_dbg(dev, "ME cmd 0x%08X failed. Status: 0x%X\n",
300 WIRED_AKE_SEND_PAIRING_INFO,
301 pairing_info_out.header.status);
302 return -1;
303 }
304 return 0;
305 }
306 EXPORT_SYMBOL(mei_store_pairing_info);
307

---
0-DAY kernel test infrastructure Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all Intel Corporation
Shankar, Uma
2018-05-09 10:28:06 UTC
Permalink
-----Original Message-----
Ramalingam C
Sent: Tuesday, April 3, 2018 7:27 PM
Subject: [Intel-gfx] [PATCH v3 11/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.
Rebased.
cldev is passed as first parameter [Tomas]
Redundant comments and cast are removed [Tomas]
---
drivers/misc/mei/hdcp/mei_hdcp.c | 61
++++++++++++++++++++++++++++++++++++++++
include/linux/mei_hdcp.h | 10 +++++++
2 files changed, 71 insertions(+)
diff --git a/drivers/misc/mei/hdcp/mei_hdcp.c
b/drivers/misc/mei/hdcp/mei_hdcp.c
index fa548310de7a..60afdd0cee79 100644
--- a/drivers/misc/mei/hdcp/mei_hdcp.c
+++ b/drivers/misc/mei/hdcp/mei_hdcp.c
@@ -244,6 +244,67 @@ int mei_verify_hprime(struct mei_cl_device *cldev,
struct mei_hdcp_data *data, } EXPORT_SYMBOL(mei_verify_hprime);
+/**
Drop the extra *, unless you really love it :)
+ * Function to store pairing info received from panel
+ *
+ *
+ * Returns 0 on Success, <0 on Failure
+ */
+
+int mei_store_pairing_info(struct mei_cl_device *cldev,
+ struct mei_hdcp_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 device *dev;
+ ssize_t byte;
+
+ if (!data || !pairing_info)
+ return -EINVAL;
+
+ dev = &cldev->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 = data->port;
+
+ memcpy(pairing_info_in.e_kh_km, pairing_info->e_kh_km,
Validate pairing_info->e_kh_km for NULL.
+ sizeof(pairing_info_in.e_kh_km));
+
+ byte = mei_cldev_send(cldev, (u8 *)&pairing_info_in,
+ sizeof(pairing_info_in));
+ if (byte < 0) {
+ dev_dbg(dev, "mei_cldev_send failed. %d\n", (int)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. %d\n", (int)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 -1;
+ }
Leave a blank line here.
+ return 0;
+}
+EXPORT_SYMBOL(mei_store_pairing_info);
+
void mei_cldev_state_notify_clients(struct mei_cl_device *cldev, bool enabled) {
if (enabled)
diff --git a/include/linux/mei_hdcp.h b/include/linux/mei_hdcp.h index
00bfde251ba4..be16e49d8018 100644
--- a/include/linux/mei_hdcp.h
+++ b/include/linux/mei_hdcp.h
@@ -118,6 +118,9 @@ mei_verify_receiver_cert_prepare_km(struct
mei_cl_device *cldev,
size_t *msg_sz);
int mei_verify_hprime(struct mei_cl_device *cldev, struct mei_hdcp_data *data,
struct hdcp2_ake_send_hprime *rx_hprime);
+int mei_store_pairing_info(struct mei_cl_device *cldev,
+ struct mei_hdcp_data *data,
+ struct hdcp2_ake_send_pairing_info *pairing_info);
#else
mei_hdcp_data *data, {
return -ENODEV;
}
+static inline
+int mei_store_pairing_info(struct mei_cl_device *cldev,
+ struct mei_hdcp_data *data,
+ struct hdcp2_ake_send_pairing_info *pairing_info) {
+ return -ENODEV;
+}
#endif /* defined (CONFIG_INTEL_MEI_HDCP) */ #endif /* defined
(_LINUX_MEI_HDCP_H) */
--
2.7.4
_______________________________________________
Intel-gfx mailing list
https://lists.freedesktop.org/mailman/listinfo/intel-gfx
Ramalingam C
2018-05-16 15:53:23 UTC
Permalink
Post by Shankar, Uma
-----Original Message-----
Ramalingam C
Sent: Tuesday, April 3, 2018 7:27 PM
Subject: [Intel-gfx] [PATCH v3 11/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.
Rebased.
cldev is passed as first parameter [Tomas]
Redundant comments and cast are removed [Tomas]
---
drivers/misc/mei/hdcp/mei_hdcp.c | 61
++++++++++++++++++++++++++++++++++++++++
include/linux/mei_hdcp.h | 10 +++++++
2 files changed, 71 insertions(+)
diff --git a/drivers/misc/mei/hdcp/mei_hdcp.c
b/drivers/misc/mei/hdcp/mei_hdcp.c
index fa548310de7a..60afdd0cee79 100644
--- a/drivers/misc/mei/hdcp/mei_hdcp.c
+++ b/drivers/misc/mei/hdcp/mei_hdcp.c
@@ -244,6 +244,67 @@ int mei_verify_hprime(struct mei_cl_device *cldev,
struct mei_hdcp_data *data, } EXPORT_SYMBOL(mei_verify_hprime);
+/**
Drop the extra *, unless you really love it :)
ha ha. Actually I have added intentionally. But removing them across all
patches
as per your suggestions. :)
Post by Shankar, Uma
+ * Function to store pairing info received from panel
+ *
+ *
+ * Returns 0 on Success, <0 on Failure
+ */
+
+int mei_store_pairing_info(struct mei_cl_device *cldev,
+ struct mei_hdcp_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 device *dev;
+ ssize_t byte;
+
+ if (!data || !pairing_info)
+ return -EINVAL;
+
+ dev = &cldev->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 = data->port;
+
+ memcpy(pairing_info_in.e_kh_km, pairing_info->e_kh_km,
Validate pairing_info->e_kh_km for NULL.
As we discussed we need not check for null here.
Post by Shankar, Uma
+ sizeof(pairing_info_in.e_kh_km));
+
+ byte = mei_cldev_send(cldev, (u8 *)&pairing_info_in,
+ sizeof(pairing_info_in));
+ if (byte < 0) {
+ dev_dbg(dev, "mei_cldev_send failed. %d\n", (int)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. %d\n", (int)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 -1;
+ }
Leave a blank line here.
sure. I will do it in all patches. Thanks.

--Ram
Post by Shankar, Uma
+ return 0;
+}
+EXPORT_SYMBOL(mei_store_pairing_info);
+
void mei_cldev_state_notify_clients(struct mei_cl_device *cldev, bool enabled) {
if (enabled)
diff --git a/include/linux/mei_hdcp.h b/include/linux/mei_hdcp.h index
00bfde251ba4..be16e49d8018 100644
--- a/include/linux/mei_hdcp.h
+++ b/include/linux/mei_hdcp.h
@@ -118,6 +118,9 @@ mei_verify_receiver_cert_prepare_km(struct mei_cl_device *cldev,
size_t *msg_sz);
int mei_verify_hprime(struct mei_cl_device *cldev, struct mei_hdcp_data *data,
struct hdcp2_ake_send_hprime *rx_hprime);
+int mei_store_pairing_info(struct mei_cl_device *cldev,
+ struct mei_hdcp_data *data,
+ struct hdcp2_ake_send_pairing_info *pairing_info);
#else
mei_hdcp_data *data, {
return -ENODEV;
}
+static inline
+int mei_store_pairing_info(struct mei_cl_device *cldev,
+ struct mei_hdcp_data *data,
+ struct hdcp2_ake_send_pairing_info *pairing_info) {
+ return -ENODEV;
+}
#endif /* defined (CONFIG_INTEL_MEI_HDCP) */ #endif /* defined
(_LINUX_MEI_HDCP_H) */
--
2.7.4
_______________________________________________
Intel-gfx mailing list
https://lists.freedesktop.org/mailman/listinfo/intel-gfx
C, Ramalingam
2018-05-17 06:03:58 UTC
Permalink
-----Original Message-----
From: Usyskin, Alexander
Sent: Thursday, May 17, 2018 11:29 AM
Subject: RE: [Intel-gfx] [PATCH v3 11/40] misc/mei/hdcp: Store the HDCP Pairing
info
-----Original Message-----
From: C, Ramalingam
Sent: Wednesday, May 16, 2018 18:53
Subject: Re: [Intel-gfx] [PATCH v3 11/40] misc/mei/hdcp: Store the
HDCP Pairing info
Post by Shankar, Uma
-----Original Message-----
Behalf Of Ramalingam C
Sent: Tuesday, April 3, 2018 7:27 PM
Subject: [Intel-gfx] [PATCH v3 11/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.
Post by Shankar, Uma
Rebased.
cldev is passed as first parameter [Tomas]
Redundant comments and cast are removed [Tomas]
---
drivers/misc/mei/hdcp/mei_hdcp.c | 61
++++++++++++++++++++++++++++++++++++++++
include/linux/mei_hdcp.h | 10 +++++++
2 files changed, 71 insertions(+)
diff --git a/drivers/misc/mei/hdcp/mei_hdcp.c
b/drivers/misc/mei/hdcp/mei_hdcp.c
index fa548310de7a..60afdd0cee79 100644
--- a/drivers/misc/mei/hdcp/mei_hdcp.c
+++ b/drivers/misc/mei/hdcp/mei_hdcp.c
@@ -244,6 +244,67 @@ int mei_verify_hprime(struct mei_cl_device
*cldev, struct mei_hdcp_data *data, }
EXPORT_SYMBOL(mei_verify_hprime);
+/**
Drop the extra *, unless you really love it :)
ha ha. Actually I have added intentionally. But removing them across
all patches as per your suggestions. :)
/** is a syntax for KDoc, so if you want to receive automatic code
documentation you should use it and adhere to KDoc syntax
Thanks Alexander for the information. At present I am not adding the KDoc support, if it is not compulsory.
So I will remove the /**.

--Ram
Post by Shankar, Uma
+ * Function to store pairing info received from panel
+ *
+ *
+ * Returns 0 on Success, <0 on Failure */
+
+int mei_store_pairing_info(struct mei_cl_device *cldev,
+ struct mei_hdcp_data *data,
+ struct hdcp2_ake_send_pairing_info *pairing_info)
{
Post by Shankar, Uma
+ struct wired_cmd_ake_send_pairing_info_in pairing_info_in = { { 0
+}
};
Post by Shankar, Uma
+ struct wired_cmd_ake_send_pairing_info_out pairing_info_out = { {
0 } };
Post by Shankar, Uma
+ struct device *dev;
+ ssize_t byte;
+
+ if (!data || !pairing_info)
+ return -EINVAL;
+
+ dev = &cldev->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 = data->port;
+
+ memcpy(pairing_info_in.e_kh_km, pairing_info->e_kh_km,
Validate pairing_info->e_kh_km for NULL.
As we discussed we need not check for null here.
Post by Shankar, Uma
+ sizeof(pairing_info_in.e_kh_km));
+
+ byte = mei_cldev_send(cldev, (u8 *)&pairing_info_in,
+ sizeof(pairing_info_in));
+ if (byte < 0) {
+ dev_dbg(dev, "mei_cldev_send failed. %d\n", (int)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. %d\n", (int)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 -1;
+ }
Leave a blank line here.
sure. I will do it in all patches. Thanks.
--Ram
Post by Shankar, Uma
+ return 0;
+}
+EXPORT_SYMBOL(mei_store_pairing_info);
+
void mei_cldev_state_notify_clients(struct mei_cl_device *cldev,
bool
enabled) {
Post by Shankar, Uma
if (enabled)
diff --git a/include/linux/mei_hdcp.h b/include/linux/mei_hdcp.h index
00bfde251ba4..be16e49d8018 100644
--- a/include/linux/mei_hdcp.h
+++ b/include/linux/mei_hdcp.h
@@ -118,6 +118,9 @@ mei_verify_receiver_cert_prepare_km(struct
mei_cl_device *cldev,
size_t *msg_sz);
int mei_verify_hprime(struct mei_cl_device *cldev, struct
mei_hdcp_data
*data,
Post by Shankar, Uma
struct hdcp2_ake_send_hprime *rx_hprime);
+int mei_store_pairing_info(struct mei_cl_device *cldev,
+ struct mei_hdcp_data *data,
+ struct hdcp2_ake_send_pairing_info *pairing_info);
#else
static int mei_cldev_register_notify(struct notifier_block *nb) {
@@
-150,5
+struct
mei_hdcp_data *data, {
return -ENODEV;
}
+static inline
+int mei_store_pairing_info(struct mei_cl_device *cldev,
+ struct mei_hdcp_data *data,
+ struct hdcp2_ake_send_pairing_info *pairing_info)
{
Post by Shankar, Uma
+ return -ENODEV;
+}
#endif /* defined (CONFIG_INTEL_MEI_HDCP) */ #endif /* defined
(_LINUX_MEI_HDCP_H) */
--
2.7.4
_______________________________________________
Intel-gfx mailing list
https://lists.freedesktop.org/mailman/listinfo/intel-gfx
Ramalingam C
2018-04-03 13:57:27 UTC
Permalink
Request to ME to prepare the encrypted session key.

On Success, ME provides Encrypted session key. Functions 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]

Signed-off-by: Ramalingam C <***@intel.com>
---
drivers/misc/mei/hdcp/mei_hdcp.c | 58 ++++++++++++++++++++++++++++++++++++++++
include/linux/mei_hdcp.h | 8 ++++++
2 files changed, 66 insertions(+)

diff --git a/drivers/misc/mei/hdcp/mei_hdcp.c b/drivers/misc/mei/hdcp/mei_hdcp.c
index ea84177311b7..abfcc57863b8 100644
--- a/drivers/misc/mei/hdcp/mei_hdcp.c
+++ b/drivers/misc/mei/hdcp/mei_hdcp.c
@@ -420,6 +420,64 @@ int mei_verify_lprime(struct mei_cl_device *cldev, struct mei_hdcp_data *data,
}
EXPORT_SYMBOL(mei_verify_lprime);

+/**
+ * mei_get_session_key:
+ * Function to prepare SKE_Send_Eks.
+ *
+ * @cldev : Pointer for mei client device
+ * @data : Intel HW specific Data
+ * @ske_data : Pointer for SKE_Send_Eks.
+ *
+ * Returns 0 on Success, <0 on Failure
+ */
+int mei_get_session_key(struct mei_cl_device *cldev, struct mei_hdcp_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 device *dev;
+ ssize_t byte;
+
+ if (!data || !ske_data)
+ return -EINVAL;
+
+ dev = &cldev->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 = 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. %d\n", (int)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. %d\n", (int)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 -1;
+ }
+
+ 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;
+}
+EXPORT_SYMBOL(mei_get_session_key);
+
void mei_cldev_state_notify_clients(struct mei_cl_device *cldev, bool enabled)
{
if (enabled)
diff --git a/include/linux/mei_hdcp.h b/include/linux/mei_hdcp.h
index 792143563c46..534170d746af 100644
--- a/include/linux/mei_hdcp.h
+++ b/include/linux/mei_hdcp.h
@@ -126,6 +126,8 @@ int mei_initiate_locality_check(struct mei_cl_device *cldev,
struct hdcp2_lc_init *lc_init_data);
int mei_verify_lprime(struct mei_cl_device *cldev, struct mei_hdcp_data *data,
struct hdcp2_lc_send_lprime *rx_lprime);
+int mei_get_session_key(struct mei_cl_device *cldev, struct mei_hdcp_data *data,
+ struct hdcp2_ske_send_eks *ske_data);
#else
static int mei_cldev_register_notify(struct notifier_block *nb)
{
@@ -178,5 +180,11 @@ int mei_verify_lprime(struct mei_cl_device *cldev, struct mei_hdcp_data *data,
{
return -ENODEV;
}
+static inline
+int mei_get_session_key(struct mei_cl_device *cldev, struct mei_hdcp_data *data,
+ struct hdcp2_ske_send_eks *ske_data)
+{
+ return -ENODEV;
+}
#endif /* defined (CONFIG_INTEL_MEI_HDCP) */
#endif /* defined (_LINUX_MEI_HDCP_H) */
--
2.7.4
Shankar, Uma
2018-05-09 10:59:43 UTC
Permalink
-----Original Message-----
Ramalingam C
Sent: Tuesday, April 3, 2018 7:27 PM
Subject: [Intel-gfx] [PATCH v3 14/40] misc/mei/hdcp: Prepare Session Key
Request to ME to prepare the encrypted session key.
On Success, ME provides Encrypted session key. Functions populates the HDCP2.2
Drop "s" from function.
authentication msg SKE_Send_Eks.
Rebased.
cldev is passed as first parameter [Tomas]
Redundant comments and cast are removed [Tomas]
---
drivers/misc/mei/hdcp/mei_hdcp.c | 58
++++++++++++++++++++++++++++++++++++++++
include/linux/mei_hdcp.h | 8 ++++++
2 files changed, 66 insertions(+)
diff --git a/drivers/misc/mei/hdcp/mei_hdcp.c
b/drivers/misc/mei/hdcp/mei_hdcp.c
index ea84177311b7..abfcc57863b8 100644
--- a/drivers/misc/mei/hdcp/mei_hdcp.c
+++ b/drivers/misc/mei/hdcp/mei_hdcp.c
@@ -420,6 +420,64 @@ int mei_verify_lprime(struct mei_cl_device *cldev,
struct mei_hdcp_data *data, } EXPORT_SYMBOL(mei_verify_lprime);
+/**
+ * Function to prepare SKE_Send_Eks.
+ *
+ *
+ * Returns 0 on Success, <0 on Failure
+ */
+int mei_get_session_key(struct mei_cl_device *cldev, struct mei_hdcp_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 device *dev;
+ ssize_t byte;
+
+ if (!data || !ske_data)
+ return -EINVAL;
+
+ dev = &cldev->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 = 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. %d\n", (int)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. %d\n", (int)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 -1;
+ }
+
+ ske_data->msg_id = HDCP_2_2_SKE_SEND_EKS;
+ memcpy(ske_data->e_dkey_ks, get_skey_out.e_dkey_ks,
Check for validity of ske_data->e_dkey_ks.
+ HDCP_2_2_E_DKEY_KS_LEN);
+ memcpy(ske_data->riv, get_skey_out.r_iv, HDCP_2_2_RIV_LEN);
Again check for ske_data->riv. Also leave a blank line here.
+ return 0;
+}
+EXPORT_SYMBOL(mei_get_session_key);
+
void mei_cldev_state_notify_clients(struct mei_cl_device *cldev, bool enabled) {
if (enabled)
diff --git a/include/linux/mei_hdcp.h b/include/linux/mei_hdcp.h index
792143563c46..534170d746af 100644
--- a/include/linux/mei_hdcp.h
+++ b/include/linux/mei_hdcp.h
@@ -126,6 +126,8 @@ int mei_initiate_locality_check(struct mei_cl_device *cldev,
struct hdcp2_lc_init *lc_init_data); int
mei_verify_lprime(struct mei_cl_device *cldev, struct mei_hdcp_data *data,
struct hdcp2_lc_send_lprime *rx_lprime);
+int mei_get_session_key(struct mei_cl_device *cldev, struct mei_hdcp_data *data,
+ struct hdcp2_ske_send_eks *ske_data);
#else
mei_hdcp_data *data, {
return -ENODEV;
}
+static inline
+int mei_get_session_key(struct mei_cl_device *cldev, struct mei_hdcp_data *data,
+ struct hdcp2_ske_send_eks *ske_data) {
+ return -ENODEV;
+}
#endif /* defined (CONFIG_INTEL_MEI_HDCP) */ #endif /* defined
(_LINUX_MEI_HDCP_H) */
--
2.7.4
_______________________________________________
Intel-gfx mailing list
https://lists.freedesktop.org/mailman/listinfo/intel-gfx
Ramalingam C
2018-05-16 16:10:05 UTC
Permalink
Post by Shankar, Uma
-----Original Message-----
Ramalingam C
Sent: Tuesday, April 3, 2018 7:27 PM
Subject: [Intel-gfx] [PATCH v3 14/40] misc/mei/hdcp: Prepare Session Key
Request to ME to prepare the encrypted session key.
On Success, ME provides Encrypted session key. Functions populates the HDCP2.2
Drop "s" from function.
ok. Thanks.
Post by Shankar, Uma
authentication msg SKE_Send_Eks.
Rebased.
cldev is passed as first parameter [Tomas]
Redundant comments and cast are removed [Tomas]
---
drivers/misc/mei/hdcp/mei_hdcp.c | 58
++++++++++++++++++++++++++++++++++++++++
include/linux/mei_hdcp.h | 8 ++++++
2 files changed, 66 insertions(+)
diff --git a/drivers/misc/mei/hdcp/mei_hdcp.c
b/drivers/misc/mei/hdcp/mei_hdcp.c
index ea84177311b7..abfcc57863b8 100644
--- a/drivers/misc/mei/hdcp/mei_hdcp.c
+++ b/drivers/misc/mei/hdcp/mei_hdcp.c
@@ -420,6 +420,64 @@ int mei_verify_lprime(struct mei_cl_device *cldev,
struct mei_hdcp_data *data, } EXPORT_SYMBOL(mei_verify_lprime);
+/**
+ * Function to prepare SKE_Send_Eks.
+ *
+ *
+ * Returns 0 on Success, <0 on Failure
+ */
+int mei_get_session_key(struct mei_cl_device *cldev, struct mei_hdcp_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 device *dev;
+ ssize_t byte;
+
+ if (!data || !ske_data)
+ return -EINVAL;
+
+ dev = &cldev->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 = 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. %d\n", (int)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. %d\n", (int)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 -1;
+ }
+
+ ske_data->msg_id = HDCP_2_2_SKE_SEND_EKS;
+ memcpy(ske_data->e_dkey_ks, get_skey_out.e_dkey_ks,
Check for validity of ske_data->e_dkey_ks.
+ HDCP_2_2_E_DKEY_KS_LEN);
+ memcpy(ske_data->riv, get_skey_out.r_iv, HDCP_2_2_RIV_LEN);
Again check for ske_data->riv. Also leave a blank line here.
New line will be added

--Ram
Post by Shankar, Uma
+ return 0;
+}
+EXPORT_SYMBOL(mei_get_session_key);
+
void mei_cldev_state_notify_clients(struct mei_cl_device *cldev, bool enabled) {
if (enabled)
diff --git a/include/linux/mei_hdcp.h b/include/linux/mei_hdcp.h index
792143563c46..534170d746af 100644
--- a/include/linux/mei_hdcp.h
+++ b/include/linux/mei_hdcp.h
@@ -126,6 +126,8 @@ int mei_initiate_locality_check(struct mei_cl_device *cldev,
struct hdcp2_lc_init *lc_init_data); int
mei_verify_lprime(struct mei_cl_device *cldev, struct mei_hdcp_data *data,
struct hdcp2_lc_send_lprime *rx_lprime);
+int mei_get_session_key(struct mei_cl_device *cldev, struct mei_hdcp_data *data,
+ struct hdcp2_ske_send_eks *ske_data);
#else
mei_hdcp_data *data, {
return -ENODEV;
}
+static inline
+int mei_get_session_key(struct mei_cl_device *cldev, struct mei_hdcp_data *data,
+ struct hdcp2_ske_send_eks *ske_data) {
+ return -ENODEV;
+}
#endif /* defined (CONFIG_INTEL_MEI_HDCP) */ #endif /* defined
(_LINUX_MEI_HDCP_H) */
--
2.7.4
_______________________________________________
Intel-gfx mailing list
https://lists.freedesktop.org/mailman/listinfo/intel-gfx
Ramalingam C
2018-04-03 13:57:34 UTC
Permalink
Intel HDCP2.2 registers are defined with addr offsets and bit details.

v2:
Replaced the arith calc with _PICK [Sean Paul]
v3:
No changes.

Signed-off-by: Ramalingam C <***@intel.com>
---
drivers/gpu/drm/i915/i915_reg.h | 32 ++++++++++++++++++++++++++++++++
1 file changed, 32 insertions(+)

diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
index e6a8c0ee7df1..f04ad3c15abd 100644
--- a/drivers/gpu/drm/i915/i915_reg.h
+++ b/drivers/gpu/drm/i915/i915_reg.h
@@ -8649,6 +8649,38 @@ enum skl_power_gate {
#define HDCP_STATUS_CIPHER BIT(16)
#define HDCP_STATUS_FRAME_CNT(x) ((x >> 8) & 0xff)

+/* HDCP2.2 Registers */
+#define _PORTA_HDCP2_BASE 0x66800
+#define _PORTB_HDCP2_BASE 0x66500
+#define _PORTC_HDCP2_BASE 0x66600
+#define _PORTD_HDCP2_BASE 0x66700
+#define _PORTE_HDCP2_BASE 0x66A00
+#define _PORTF_HDCP2_BASE 0x66900
+#define _PORT_HDCP2_BASE(port, x) _MMIO(_PICK(port, \
+ _PORTA_HDCP2_BASE, \
+ _PORTB_HDCP2_BASE, \
+ _PORTC_HDCP2_BASE, \
+ _PORTD_HDCP2_BASE, \
+ _PORTE_HDCP2_BASE, \
+ _PORTF_HDCP2_BASE) + x)
+
+#define HDCP2_AUTH_DDI(port) _PORT_HDCP2_BASE(port, 0x98)
+#define AUTH_LINK_AUTHENTICATED BIT(31)
+#define AUTH_LINK_TYPE BIT(30)
+#define AUTH_FORCE_CLR_INPUTCTR BIT(19)
+#define AUTH_CLR_KEYS BIT(18)
+
+#define HDCP2_CTR_DDI(port) _PORT_HDCP2_BASE(port, 0xB0)
+#define CTL_LINK_ENCRYPTION_REQ BIT(31)
+
+#define HDCP2_STATUS_DDI(port) _PORT_HDCP2_BASE(port, 0xB4)
+#define STREAM_ENCRYPTION_STATUS_A BIT(31)
+#define STREAM_ENCRYPTION_STATUS_B BIT(30)
+#define STREAM_ENCRYPTION_STATUS_C BIT(29)
+#define LINK_TYPE_STATUS BIT(22)
+#define LINK_AUTH_STATUS BIT(21)
+#define LINK_ENCRYPTION_STATUS BIT(20)
+
/* Per-pipe DDI Function Control */
#define _TRANS_DDI_FUNC_CTL_A 0x60400
#define _TRANS_DDI_FUNC_CTL_B 0x61400
--
2.7.4
Shankar, Uma
2018-05-09 14:59:48 UTC
Permalink
-----Original Message-----
Ramalingam C
Sent: Tuesday, April 3, 2018 7:28 PM
Subject: [Intel-gfx] [PATCH v3 21/40] drm/i915: Define Intel HDCP2.2 registers
Intel HDCP2.2 registers are defined with addr offsets and bit details.
Replaced the arith calc with _PICK [Sean Paul]
No changes.
---
drivers/gpu/drm/i915/i915_reg.h | 32 ++++++++++++++++++++++++++++++++
1 file changed, 32 insertions(+)
diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
index e6a8c0ee7df1..f04ad3c15abd 100644
--- a/drivers/gpu/drm/i915/i915_reg.h
+++ b/drivers/gpu/drm/i915/i915_reg.h
@@ -8649,6 +8649,38 @@ enum skl_power_gate {
#define HDCP_STATUS_CIPHER BIT(16)
#define HDCP_STATUS_FRAME_CNT(x) ((x >> 8) & 0xff)
+/* HDCP2.2 Registers */
+#define _PORTA_HDCP2_BASE 0x66800
+#define _PORTB_HDCP2_BASE 0x66500
+#define _PORTC_HDCP2_BASE 0x66600
+#define _PORTD_HDCP2_BASE 0x66700
+#define _PORTE_HDCP2_BASE 0x66A00
+#define _PORTF_HDCP2_BASE 0x66900
+#define _PORT_HDCP2_BASE(port, x) _MMIO(_PICK(port, \
+ _PORTA_HDCP2_BASE, \
+ _PORTB_HDCP2_BASE, \
+ _PORTC_HDCP2_BASE, \
+ _PORTD_HDCP2_BASE, \
+ _PORTE_HDCP2_BASE, \
+ _PORTF_HDCP2_BASE) + x)
+
+#define HDCP2_AUTH_DDI(port) _PORT_HDCP2_BASE(port,
0x98)
+#define AUTH_LINK_AUTHENTICATED BIT(31)
+#define AUTH_LINK_TYPE BIT(30)
+#define AUTH_FORCE_CLR_INPUTCTR BIT(19)
+#define AUTH_CLR_KEYS BIT(18)
+
+#define HDCP2_CTR_DDI(port) _PORT_HDCP2_BASE(port, 0xB0)
Rename it to HDCP2_CTL_DDI to match with spec and avoid any ambiguity.
+#define CTL_LINK_ENCRYPTION_REQ BIT(31)
+
+#define HDCP2_STATUS_DDI(port) _PORT_HDCP2_BASE(port,
0xB4)
+#define STREAM_ENCRYPTION_STATUS_A BIT(31)
+#define STREAM_ENCRYPTION_STATUS_B BIT(30)
+#define STREAM_ENCRYPTION_STATUS_C BIT(29)
+#define LINK_TYPE_STATUS BIT(22)
+#define LINK_AUTH_STATUS BIT(21)
+#define LINK_ENCRYPTION_STATUS BIT(20)
+
/* Per-pipe DDI Function Control */
#define _TRANS_DDI_FUNC_CTL_A 0x60400
#define _TRANS_DDI_FUNC_CTL_B 0x61400
--
2.7.4
_______________________________________________
Intel-gfx mailing list
https://lists.freedesktop.org/mailman/listinfo/intel-gfx
Ramalingam C
2018-05-17 10:24:06 UTC
Permalink
Post by Shankar, Uma
-----Original Message-----
Ramalingam C
Sent: Tuesday, April 3, 2018 7:28 PM
Subject: [Intel-gfx] [PATCH v3 21/40] drm/i915: Define Intel HDCP2.2 registers
Intel HDCP2.2 registers are defined with addr offsets and bit details.
Replaced the arith calc with _PICK [Sean Paul]
No changes.
---
drivers/gpu/drm/i915/i915_reg.h | 32 ++++++++++++++++++++++++++++++++
1 file changed, 32 insertions(+)
diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
index e6a8c0ee7df1..f04ad3c15abd 100644
--- a/drivers/gpu/drm/i915/i915_reg.h
+++ b/drivers/gpu/drm/i915/i915_reg.h
@@ -8649,6 +8649,38 @@ enum skl_power_gate {
#define HDCP_STATUS_CIPHER BIT(16)
#define HDCP_STATUS_FRAME_CNT(x) ((x >> 8) & 0xff)
+/* HDCP2.2 Registers */
+#define _PORTA_HDCP2_BASE 0x66800
+#define _PORTB_HDCP2_BASE 0x66500
+#define _PORTC_HDCP2_BASE 0x66600
+#define _PORTD_HDCP2_BASE 0x66700
+#define _PORTE_HDCP2_BASE 0x66A00
+#define _PORTF_HDCP2_BASE 0x66900
+#define _PORT_HDCP2_BASE(port, x) _MMIO(_PICK(port, \
+ _PORTA_HDCP2_BASE, \
+ _PORTB_HDCP2_BASE, \
+ _PORTC_HDCP2_BASE, \
+ _PORTD_HDCP2_BASE, \
+ _PORTE_HDCP2_BASE, \
+ _PORTF_HDCP2_BASE) + x)
+
+#define HDCP2_AUTH_DDI(port) _PORT_HDCP2_BASE(port,
0x98)
+#define AUTH_LINK_AUTHENTICATED BIT(31)
+#define AUTH_LINK_TYPE BIT(30)
+#define AUTH_FORCE_CLR_INPUTCTR BIT(19)
+#define AUTH_CLR_KEYS BIT(18)
+
+#define HDCP2_CTR_DDI(port) _PORT_HDCP2_BASE(port, 0xB0)
Rename it to HDCP2_CTL_DDI to match with spec and avoid any ambiguity.
I will rename it as CTL.

--Ram
Post by Shankar, Uma
+#define CTL_LINK_ENCRYPTION_REQ BIT(31)
+
+#define HDCP2_STATUS_DDI(port) _PORT_HDCP2_BASE(port,
0xB4)
+#define STREAM_ENCRYPTION_STATUS_A BIT(31)
+#define STREAM_ENCRYPTION_STATUS_B BIT(30)
+#define STREAM_ENCRYPTION_STATUS_C BIT(29)
+#define LINK_TYPE_STATUS BIT(22)
+#define LINK_AUTH_STATUS BIT(21)
+#define LINK_ENCRYPTION_STATUS BIT(20)
+
/* Per-pipe DDI Function Control */
#define _TRANS_DDI_FUNC_CTL_A 0x60400
#define _TRANS_DDI_FUNC_CTL_B 0x61400
--
2.7.4
_______________________________________________
Intel-gfx mailing list
https://lists.freedesktop.org/mailman/listinfo/intel-gfx
Ramalingam C
2018-04-03 13:57:30 UTC
Permalink
Request to ME to configure a port as authenticated.

On Success, ME FW will mark th eport as authenticated and provides
HDCP chiper of the port with the encryption keys.

Enabling the Authentication can be requested once the all
stages of HDCP2.2 authentication is completed by interating 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]

Signed-off-by: Ramalingam C <***@intel.com>
---
drivers/misc/mei/hdcp/mei_hdcp.c | 54 ++++++++++++++++++++++++++++++++++++++++
include/linux/mei_hdcp.h | 7 ++++++
2 files changed, 61 insertions(+)

diff --git a/drivers/misc/mei/hdcp/mei_hdcp.c b/drivers/misc/mei/hdcp/mei_hdcp.c
index 68eb5267a8e7..b5d1da41f1d9 100644
--- a/drivers/misc/mei/hdcp/mei_hdcp.c
+++ b/drivers/misc/mei/hdcp/mei_hdcp.c
@@ -632,6 +632,60 @@ int mei_verify_mprime(struct mei_cl_device *cldev, struct mei_hdcp_data *data,
}
EXPORT_SYMBOL(mei_verify_mprime);

+/**
+ * mei_enable_hdcp_authentication:
+ * Function to request ME FW to mark a port as authenticated.
+ *
+ * @cldev : Pointer for mei client device
+ * @data : Intel HW specific Data
+ *
+ * Returns 0 on Success, <0 on Failure
+ */
+int mei_enable_hdcp_authentication(struct mei_cl_device *cldev,
+ struct mei_hdcp_data *data)
+{
+ struct wired_cmd_enable_auth_in enable_auth_in = { { 0 } };
+ struct wired_cmd_enable_auth_out enable_auth_out = { { 0 } };
+ struct device *dev;
+ ssize_t byte;
+
+ if (!data)
+ return -EINVAL;
+
+ dev = &cldev->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 = 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. %d\n", (int)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. %d\n", (int)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 -1;
+ }
+ return 0;
+}
+EXPORT_SYMBOL(mei_enable_hdcp_authentication);
+
void mei_cldev_state_notify_clients(struct mei_cl_device *cldev, bool enabled)
{
if (enabled)
diff --git a/include/linux/mei_hdcp.h b/include/linux/mei_hdcp.h
index dbc216e13f97..2366d0741abe 100644
--- a/include/linux/mei_hdcp.h
+++ b/include/linux/mei_hdcp.h
@@ -136,6 +136,8 @@ mei_repeater_check_flow_prepare_ack(struct mei_cl_device *cldev,
struct hdcp2_rep_send_ack *rep_send_ack);
int mei_verify_mprime(struct mei_cl_device *cldev, struct mei_hdcp_data *data,
struct hdcp2_rep_stream_ready *stream_ready);
+int mei_enable_hdcp_authentication(struct mei_cl_device *cldev,
+ struct mei_hdcp_data *data);
#else
static int mei_cldev_register_notify(struct notifier_block *nb)
{
@@ -209,5 +211,10 @@ int mei_verify_mprime(struct mei_cl_device *cldev, struct mei_hdcp_data *data,
{
return -ENODEV;
}
+static inline int mei_enable_hdcp_authentication(struct mei_cl_device *cldev,
+ struct mei_hdcp_data *data)
+{
+ return -ENODEV;
+}
#endif /* defined (CONFIG_INTEL_MEI_HDCP) */
#endif /* defined (_LINUX_MEI_HDCP_H) */
--
2.7.4
Shankar, Uma
2018-05-09 13:55:35 UTC
Permalink
-----Original Message-----
Ramalingam C
Sent: Tuesday, April 3, 2018 7:28 PM
Subject: [PATCH v3 17/40] misc/mei/hdcp: Enabling the HDCP authentication
Request to ME to configure a port as authenticated.
On Success, ME FW will mark th eport as authenticated and provides HDCP chipper
Rectify "the". Also it should be HDCP cipher.
of the port with the encryption keys.
Enabling the Authentication can be requested once the all stages of HDCP2.2
authentication is completed by interating with ME FW.
Typo in interacting.
Only after this stage, driver can enable the HDCP encryption for the port, through
HW registers.
Rebased.
cldev is passed as first parameter [Tomas]
Redundant comments and cast are removed [Tomas]
---
drivers/misc/mei/hdcp/mei_hdcp.c | 54
++++++++++++++++++++++++++++++++++++++++
include/linux/mei_hdcp.h | 7 ++++++
2 files changed, 61 insertions(+)
diff --git a/drivers/misc/mei/hdcp/mei_hdcp.c
b/drivers/misc/mei/hdcp/mei_hdcp.c
index 68eb5267a8e7..b5d1da41f1d9 100644
--- a/drivers/misc/mei/hdcp/mei_hdcp.c
+++ b/drivers/misc/mei/hdcp/mei_hdcp.c
@@ -632,6 +632,60 @@ int mei_verify_mprime(struct mei_cl_device *cldev,
struct mei_hdcp_data *data, } EXPORT_SYMBOL(mei_verify_mprime);
+/**
+ * Function to request ME FW to mark a port as authenticated.
+ *
+ *
+ * Returns 0 on Success, <0 on Failure
+ */
+int mei_enable_hdcp_authentication(struct mei_cl_device *cldev,
+ struct mei_hdcp_data *data)
+{
+ struct wired_cmd_enable_auth_in enable_auth_in = { { 0 } };
+ struct wired_cmd_enable_auth_out enable_auth_out = { { 0 } };
+ struct device *dev;
+ ssize_t byte;
+
+ if (!data)
+ return -EINVAL;
+
+ dev = &cldev->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 = data->port;
+ enable_auth_in.stream_type = data->streams[0].stream_type;
Check for data->streams.
+
+ byte = mei_cldev_send(cldev, (u8 *)&enable_auth_in,
+ sizeof(enable_auth_in));
+ if (byte < 0) {
+ dev_dbg(dev, "mei_cldev_send failed. %d\n", (int)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. %d\n", (int)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 -1;
+ }
Leave a blank line here.
+ return 0;
+}
+EXPORT_SYMBOL(mei_enable_hdcp_authentication);
+
void mei_cldev_state_notify_clients(struct mei_cl_device *cldev, bool enabled) {
if (enabled)
diff --git a/include/linux/mei_hdcp.h b/include/linux/mei_hdcp.h index
dbc216e13f97..2366d0741abe 100644
--- a/include/linux/mei_hdcp.h
+++ b/include/linux/mei_hdcp.h
@@ -136,6 +136,8 @@ mei_repeater_check_flow_prepare_ack(struct
mei_cl_device *cldev,
struct hdcp2_rep_send_ack *rep_send_ack);
int mei_verify_mprime(struct mei_cl_device *cldev, struct mei_hdcp_data *data,
struct hdcp2_rep_stream_ready *stream_ready);
+int mei_enable_hdcp_authentication(struct mei_cl_device *cldev,
+ struct mei_hdcp_data *data);
#else
mei_hdcp_data *data, {
return -ENODEV;
}
+static inline int mei_enable_hdcp_authentication(struct mei_cl_device *cldev,
+ struct mei_hdcp_data *data)
+{
+ return -ENODEV;
+}
#endif /* defined (CONFIG_INTEL_MEI_HDCP) */ #endif /* defined
(_LINUX_MEI_HDCP_H) */
--
2.7.4
_______________________________________________
dri-devel mailing list
https://lists.freedesktop.org/mailman/listinfo/dri-devel
Ramalingam C
2018-05-16 16:40:25 UTC
Permalink
Post by Shankar, Uma
-----Original Message-----
Ramalingam C
Sent: Tuesday, April 3, 2018 7:28 PM
Subject: [PATCH v3 17/40] misc/mei/hdcp: Enabling the HDCP authentication
Request to ME to configure a port as authenticated.
On Success, ME FW will mark th eport as authenticated and provides HDCP chipper
Rectify "the". Also it should be HDCP cipher.
of the port with the encryption keys.
Enabling the Authentication can be requested once the all stages of HDCP2.2
authentication is completed by interating with ME FW.
Typo in interacting.
Will fix it.

--Ram
Post by Shankar, Uma
Only after this stage, driver can enable the HDCP encryption for the port, through
HW registers.
Rebased.
cldev is passed as first parameter [Tomas]
Redundant comments and cast are removed [Tomas]
---
drivers/misc/mei/hdcp/mei_hdcp.c | 54
++++++++++++++++++++++++++++++++++++++++
include/linux/mei_hdcp.h | 7 ++++++
2 files changed, 61 insertions(+)
diff --git a/drivers/misc/mei/hdcp/mei_hdcp.c
b/drivers/misc/mei/hdcp/mei_hdcp.c
index 68eb5267a8e7..b5d1da41f1d9 100644
--- a/drivers/misc/mei/hdcp/mei_hdcp.c
+++ b/drivers/misc/mei/hdcp/mei_hdcp.c
@@ -632,6 +632,60 @@ int mei_verify_mprime(struct mei_cl_device *cldev,
struct mei_hdcp_data *data, } EXPORT_SYMBOL(mei_verify_mprime);
+/**
+ * Function to request ME FW to mark a port as authenticated.
+ *
+ *
+ * Returns 0 on Success, <0 on Failure
+ */
+int mei_enable_hdcp_authentication(struct mei_cl_device *cldev,
+ struct mei_hdcp_data *data)
+{
+ struct wired_cmd_enable_auth_in enable_auth_in = { { 0 } };
+ struct wired_cmd_enable_auth_out enable_auth_out = { { 0 } };
+ struct device *dev;
+ ssize_t byte;
+
+ if (!data)
+ return -EINVAL;
+
+ dev = &cldev->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 = data->port;
+ enable_auth_in.stream_type = data->streams[0].stream_type;
Check for data->streams.
+
+ byte = mei_cldev_send(cldev, (u8 *)&enable_auth_in,
+ sizeof(enable_auth_in));
+ if (byte < 0) {
+ dev_dbg(dev, "mei_cldev_send failed. %d\n", (int)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. %d\n", (int)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 -1;
+ }
Leave a blank line here.
+ return 0;
+}
+EXPORT_SYMBOL(mei_enable_hdcp_authentication);
+
void mei_cldev_state_notify_clients(struct mei_cl_device *cldev, bool enabled) {
if (enabled)
diff --git a/include/linux/mei_hdcp.h b/include/linux/mei_hdcp.h index
dbc216e13f97..2366d0741abe 100644
--- a/include/linux/mei_hdcp.h
+++ b/include/linux/mei_hdcp.h
@@ -136,6 +136,8 @@ mei_repeater_check_flow_prepare_ack(struct mei_cl_device *cldev,
struct hdcp2_rep_send_ack *rep_send_ack);
int mei_verify_mprime(struct mei_cl_device *cldev, struct mei_hdcp_data *data,
struct hdcp2_rep_stream_ready *stream_ready);
+int mei_enable_hdcp_authentication(struct mei_cl_device *cldev,
+ struct mei_hdcp_data *data);
#else
mei_hdcp_data *data, {
return -ENODEV;
}
+static inline int mei_enable_hdcp_authentication(struct mei_cl_device *cldev,
+ struct mei_hdcp_data *data)
+{
+ return -ENODEV;
+}
#endif /* defined (CONFIG_INTEL_MEI_HDCP) */ #endif /* defined
(_LINUX_MEI_HDCP_H) */
--
2.7.4
_______________________________________________
dri-devel mailing list
https://lists.freedesktop.org/mailman/listinfo/dri-devel
Ramalingam C
2018-04-03 13:57:31 UTC
Permalink
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]

Signed-off-by: Ramalingam C <***@intel.com>
---
drivers/misc/mei/hdcp/mei_hdcp.c | 55 ++++++++++++++++++++++++++++++++++++++++
include/linux/mei_hdcp.h | 7 +++++
2 files changed, 62 insertions(+)

diff --git a/drivers/misc/mei/hdcp/mei_hdcp.c b/drivers/misc/mei/hdcp/mei_hdcp.c
index b5d1da41f1d9..ed402f1f2f64 100644
--- a/drivers/misc/mei/hdcp/mei_hdcp.c
+++ b/drivers/misc/mei/hdcp/mei_hdcp.c
@@ -686,6 +686,61 @@ int mei_enable_hdcp_authentication(struct mei_cl_device *cldev,
}
EXPORT_SYMBOL(mei_enable_hdcp_authentication);

+/**
+ * me_close_hdcp_session:
+ * Function to close the Wired HDCP Tx session of ME FW.
+ * This also disables the authenticated state of the port.
+ *
+ * @data : Intel HW specific Data
+ *
+ * Returns 0 on Success, <0 on Failure
+ */
+int mei_close_hdcp_session(struct mei_cl_device *cldev,
+ struct mei_hdcp_data *data)
+{
+ struct wired_cmd_close_session_in session_close_in = { { 0 } };
+ struct wired_cmd_close_session_out session_close_out = { { 0 } };
+ struct device *dev;
+ ssize_t byte;
+
+ if (!data)
+ return -EINVAL;
+
+ dev = &cldev->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 = 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. %d\n", (int)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. %d\n", (int)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 -1;
+ }
+ return 0;
+}
+EXPORT_SYMBOL(mei_close_hdcp_session);
+
void mei_cldev_state_notify_clients(struct mei_cl_device *cldev, bool enabled)
{
if (enabled)
diff --git a/include/linux/mei_hdcp.h b/include/linux/mei_hdcp.h
index 2366d0741abe..55cbde890571 100644
--- a/include/linux/mei_hdcp.h
+++ b/include/linux/mei_hdcp.h
@@ -138,6 +138,8 @@ int mei_verify_mprime(struct mei_cl_device *cldev, struct mei_hdcp_data *data,
struct hdcp2_rep_stream_ready *stream_ready);
int mei_enable_hdcp_authentication(struct mei_cl_device *cldev,
struct mei_hdcp_data *data);
+int mei_close_hdcp_session(struct mei_cl_device *cldev,
+ struct mei_hdcp_data *data);
#else
static int mei_cldev_register_notify(struct notifier_block *nb)
{
@@ -216,5 +218,10 @@ static inline int mei_enable_hdcp_authentication(struct mei_cl_device *cldev,
{
return -ENODEV;
}
+static inline int mei_close_hdcp_session(struct mei_cl_device *cldev,
+ struct mei_hdcp_data *data)
+{
+ return -ENODEV;
+}
#endif /* defined (CONFIG_INTEL_MEI_HDCP) */
#endif /* defined (_LINUX_MEI_HDCP_H) */
--
2.7.4
Shankar, Uma
2018-05-09 14:02:01 UTC
Permalink
-----Original Message-----
Ramalingam C
Sent: Tuesday, April 3, 2018 7:28 PM
Subject: [Intel-gfx] [PATCH v3 18/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.
Rebased.
cldev is passed as first parameter [Tomas]
Redundant comments and cast are removed [Tomas]
---
drivers/misc/mei/hdcp/mei_hdcp.c | 55
++++++++++++++++++++++++++++++++++++++++
include/linux/mei_hdcp.h | 7 +++++
2 files changed, 62 insertions(+)
diff --git a/drivers/misc/mei/hdcp/mei_hdcp.c
b/drivers/misc/mei/hdcp/mei_hdcp.c
index b5d1da41f1d9..ed402f1f2f64 100644
--- a/drivers/misc/mei/hdcp/mei_hdcp.c
+++ b/drivers/misc/mei/hdcp/mei_hdcp.c
@@ -686,6 +686,61 @@ int mei_enable_hdcp_authentication(struct
mei_cl_device *cldev, } EXPORT_SYMBOL(mei_enable_hdcp_authentication);
+/**
Typo in me. Should be mei.
+ * Function to close the Wired HDCP Tx session of ME FW.
+ * This also disables the authenticated state of the port.
+ *
+ *
+ * Returns 0 on Success, <0 on Failure
+ */
+int mei_close_hdcp_session(struct mei_cl_device *cldev,
+ struct mei_hdcp_data *data)
+{
+ struct wired_cmd_close_session_in session_close_in = { { 0 } };
+ struct wired_cmd_close_session_out session_close_out = { { 0 } };
+ struct device *dev;
+ ssize_t byte;
+
+ if (!data)
+ return -EINVAL;
+
+ dev = &cldev->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 = 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. %d\n", (int)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. %d\n", (int)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 -1;
+ }
+ return 0;
+}
+EXPORT_SYMBOL(mei_close_hdcp_session);
+
void mei_cldev_state_notify_clients(struct mei_cl_device *cldev, bool enabled) {
if (enabled)
diff --git a/include/linux/mei_hdcp.h b/include/linux/mei_hdcp.h index
2366d0741abe..55cbde890571 100644
--- a/include/linux/mei_hdcp.h
+++ b/include/linux/mei_hdcp.h
@@ -138,6 +138,8 @@ int mei_verify_mprime(struct mei_cl_device *cldev,
struct mei_hdcp_data *data,
struct hdcp2_rep_stream_ready *stream_ready); int
mei_enable_hdcp_authentication(struct mei_cl_device *cldev,
struct mei_hdcp_data *data);
+int mei_close_hdcp_session(struct mei_cl_device *cldev,
+ struct mei_hdcp_data *data);
#else
mei_cl_device *cldev, {
return -ENODEV;
}
+static inline int mei_close_hdcp_session(struct mei_cl_device *cldev,
+ struct mei_hdcp_data *data)
+{
+ return -ENODEV;
+}
#endif /* defined (CONFIG_INTEL_MEI_HDCP) */ #endif /* defined
(_LINUX_MEI_HDCP_H) */
--
2.7.4
_______________________________________________
Intel-gfx mailing list
https://lists.freedesktop.org/mailman/listinfo/intel-gfx
Ramalingam C
2018-05-16 16:41:51 UTC
Permalink
Post by Shankar, Uma
-----Original Message-----
Ramalingam C
Sent: Tuesday, April 3, 2018 7:28 PM
Subject: [Intel-gfx] [PATCH v3 18/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.
Rebased.
cldev is passed as first parameter [Tomas]
Redundant comments and cast are removed [Tomas]
---
drivers/misc/mei/hdcp/mei_hdcp.c | 55
++++++++++++++++++++++++++++++++++++++++
include/linux/mei_hdcp.h | 7 +++++
2 files changed, 62 insertions(+)
diff --git a/drivers/misc/mei/hdcp/mei_hdcp.c
b/drivers/misc/mei/hdcp/mei_hdcp.c
index b5d1da41f1d9..ed402f1f2f64 100644
--- a/drivers/misc/mei/hdcp/mei_hdcp.c
+++ b/drivers/misc/mei/hdcp/mei_hdcp.c
@@ -686,6 +686,61 @@ int mei_enable_hdcp_authentication(struct
mei_cl_device *cldev, } EXPORT_SYMBOL(mei_enable_hdcp_authentication);
+/**
Typo in me. Should be mei.
Thank you for catching it.

--Ram
Post by Shankar, Uma
+ * Function to close the Wired HDCP Tx session of ME FW.
+ * This also disables the authenticated state of the port.
+ *
+ *
+ * Returns 0 on Success, <0 on Failure
+ */
+int mei_close_hdcp_session(struct mei_cl_device *cldev,
+ struct mei_hdcp_data *data)
+{
+ struct wired_cmd_close_session_in session_close_in = { { 0 } };
+ struct wired_cmd_close_session_out session_close_out = { { 0 } };
+ struct device *dev;
+ ssize_t byte;
+
+ if (!data)
+ return -EINVAL;
+
+ dev = &cldev->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 = 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. %d\n", (int)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. %d\n", (int)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 -1;
+ }
+ return 0;
+}
+EXPORT_SYMBOL(mei_close_hdcp_session);
+
void mei_cldev_state_notify_clients(struct mei_cl_device *cldev, bool enabled) {
if (enabled)
diff --git a/include/linux/mei_hdcp.h b/include/linux/mei_hdcp.h index
2366d0741abe..55cbde890571 100644
--- a/include/linux/mei_hdcp.h
+++ b/include/linux/mei_hdcp.h
@@ -138,6 +138,8 @@ int mei_verify_mprime(struct mei_cl_device *cldev,
struct mei_hdcp_data *data,
struct hdcp2_rep_stream_ready *stream_ready); int
mei_enable_hdcp_authentication(struct mei_cl_device *cldev,
struct mei_hdcp_data *data);
+int mei_close_hdcp_session(struct mei_cl_device *cldev,
+ struct mei_hdcp_data *data);
#else
mei_cl_device *cldev, {
return -ENODEV;
}
+static inline int mei_close_hdcp_session(struct mei_cl_device *cldev,
+ struct mei_hdcp_data *data)
+{
+ return -ENODEV;
+}
#endif /* defined (CONFIG_INTEL_MEI_HDCP) */ #endif /* defined
(_LINUX_MEI_HDCP_H) */
--
2.7.4
_______________________________________________
Intel-gfx mailing list
https://lists.freedesktop.org/mailman/listinfo/intel-gfx
Ramalingam C
2018-04-03 13:57:26 UTC
Permalink
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]

Signed-off-by: Ramalingam C <***@intel.com>
---
drivers/misc/mei/hdcp/mei_hdcp.c | 59 ++++++++++++++++++++++++++++++++++++++++
include/linux/mei_hdcp.h | 8 ++++++
2 files changed, 67 insertions(+)

diff --git a/drivers/misc/mei/hdcp/mei_hdcp.c b/drivers/misc/mei/hdcp/mei_hdcp.c
index 9bd7e66a91e4..ea84177311b7 100644
--- a/drivers/misc/mei/hdcp/mei_hdcp.c
+++ b/drivers/misc/mei/hdcp/mei_hdcp.c
@@ -361,6 +361,65 @@ int mei_initiate_locality_check(struct mei_cl_device *cldev,
}
EXPORT_SYMBOL(mei_initiate_locality_check);

+/**
+ * mei_verify_lprime:
+ * Function to verify lprime.
+ *
+ * @cldev : Pointer for mei client device
+ * @data : Intel HW specific Data
+ * @rx_lprime : Pointer for LC_Send_L_prime
+ *
+ * Returns 0 on Success, <0 on Failure
+ */
+int mei_verify_lprime(struct mei_cl_device *cldev, struct mei_hdcp_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 device *dev;
+ ssize_t byte;
+
+ if (!data || !rx_lprime)
+ return -EINVAL;
+
+ dev = &cldev->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 = data->port;
+
+ memcpy(verify_lprime_in.l_prime, rx_lprime->l_prime,
+ sizeof(rx_lprime->l_prime));
+
+ byte = mei_cldev_send(cldev, (u8 *)&verify_lprime_in,
+ sizeof(verify_lprime_in));
+ if (byte < 0) {
+ dev_dbg(dev, "mei_cldev_send failed. %d\n", (int)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. %d\n", (int)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 -1;
+ }
+ return 0;
+}
+EXPORT_SYMBOL(mei_verify_lprime);
+
void mei_cldev_state_notify_clients(struct mei_cl_device *cldev, bool enabled)
{
if (enabled)
diff --git a/include/linux/mei_hdcp.h b/include/linux/mei_hdcp.h
index d9c4cac0b276..792143563c46 100644
--- a/include/linux/mei_hdcp.h
+++ b/include/linux/mei_hdcp.h
@@ -124,6 +124,8 @@ int mei_store_pairing_info(struct mei_cl_device *cldev,
int mei_initiate_locality_check(struct mei_cl_device *cldev,
struct mei_hdcp_data *data,
struct hdcp2_lc_init *lc_init_data);
+int mei_verify_lprime(struct mei_cl_device *cldev, struct mei_hdcp_data *data,
+ struct hdcp2_lc_send_lprime *rx_lprime);
#else
static int mei_cldev_register_notify(struct notifier_block *nb)
{
@@ -170,5 +172,11 @@ int mei_initiate_locality_check(struct mei_cl_device *cldev,
{
return -ENODEV;
}
+static inline
+int mei_verify_lprime(struct mei_cl_device *cldev, struct mei_hdcp_data *data,
+ struct hdcp2_lc_send_lprime *rx_lprime)
+{
+ return -ENODEV;
+}
#endif /* defined (CONFIG_INTEL_MEI_HDCP) */
#endif /* defined (_LINUX_MEI_HDCP_H) */
--
2.7.4
Shankar, Uma
2018-05-09 10:36:38 UTC
Permalink
-----Original Message-----
Ramalingam C
Sent: Tuesday, April 3, 2018 7:27 PM
Subject: [Intel-gfx] [PATCH v3 13/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.
Rebased.
cldev is passed as first parameter [Tomas]
Redundant comments and cast are removed [Tomas]
---
drivers/misc/mei/hdcp/mei_hdcp.c | 59
++++++++++++++++++++++++++++++++++++++++
include/linux/mei_hdcp.h | 8 ++++++
2 files changed, 67 insertions(+)
diff --git a/drivers/misc/mei/hdcp/mei_hdcp.c
b/drivers/misc/mei/hdcp/mei_hdcp.c
index 9bd7e66a91e4..ea84177311b7 100644
--- a/drivers/misc/mei/hdcp/mei_hdcp.c
+++ b/drivers/misc/mei/hdcp/mei_hdcp.c
@@ -361,6 +361,65 @@ int mei_initiate_locality_check(struct mei_cl_device
*cldev, } EXPORT_SYMBOL(mei_initiate_locality_check);
+/**
+ * Function to verify lprime.
+ *
+ *
+ * Returns 0 on Success, <0 on Failure
+ */
+int mei_verify_lprime(struct mei_cl_device *cldev, struct mei_hdcp_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 device *dev;
+ ssize_t byte;
+
+ if (!data || !rx_lprime)
+ return -EINVAL;
+
+ dev = &cldev->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 = data->port;
+
+ memcpy(verify_lprime_in.l_prime, rx_lprime->l_prime,
Validate rx_lprime->l_prime for NULL
+ sizeof(rx_lprime->l_prime));
+
+ byte = mei_cldev_send(cldev, (u8 *)&verify_lprime_in,
+ sizeof(verify_lprime_in));
+ if (byte < 0) {
+ dev_dbg(dev, "mei_cldev_send failed. %d\n", (int)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. %d\n", (int)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 -1;
+ }
Leave a blank line.
+ return 0;
+}
+EXPORT_SYMBOL(mei_verify_lprime);
+
void mei_cldev_state_notify_clients(struct mei_cl_device *cldev, bool enabled) {
if (enabled)
diff --git a/include/linux/mei_hdcp.h b/include/linux/mei_hdcp.h index
d9c4cac0b276..792143563c46 100644
--- a/include/linux/mei_hdcp.h
+++ b/include/linux/mei_hdcp.h
@@ -124,6 +124,8 @@ int mei_store_pairing_info(struct mei_cl_device *cldev,
int mei_initiate_locality_check(struct mei_cl_device *cldev,
struct mei_hdcp_data *data,
struct hdcp2_lc_init *lc_init_data);
+int mei_verify_lprime(struct mei_cl_device *cldev, struct mei_hdcp_data *data,
+ struct hdcp2_lc_send_lprime *rx_lprime);
#else
return -ENODEV;
}
+static inline
+int mei_verify_lprime(struct mei_cl_device *cldev, struct mei_hdcp_data *data,
+ struct hdcp2_lc_send_lprime *rx_lprime) {
+ return -ENODEV;
+}
#endif /* defined (CONFIG_INTEL_MEI_HDCP) */ #endif /* defined
(_LINUX_MEI_HDCP_H) */
--
2.7.4
_______________________________________________
Intel-gfx mailing list
https://lists.freedesktop.org/mailman/listinfo/intel-gfx
Ramalingam C
2018-05-16 16:05:25 UTC
Permalink
Post by Shankar, Uma
-----Original Message-----
Ramalingam C
Sent: Tuesday, April 3, 2018 7:27 PM
Subject: [Intel-gfx] [PATCH v3 13/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.
Rebased.
cldev is passed as first parameter [Tomas]
Redundant comments and cast are removed [Tomas]
---
drivers/misc/mei/hdcp/mei_hdcp.c | 59
++++++++++++++++++++++++++++++++++++++++
include/linux/mei_hdcp.h | 8 ++++++
2 files changed, 67 insertions(+)
diff --git a/drivers/misc/mei/hdcp/mei_hdcp.c
b/drivers/misc/mei/hdcp/mei_hdcp.c
index 9bd7e66a91e4..ea84177311b7 100644
--- a/drivers/misc/mei/hdcp/mei_hdcp.c
+++ b/drivers/misc/mei/hdcp/mei_hdcp.c
@@ -361,6 +361,65 @@ int mei_initiate_locality_check(struct mei_cl_device
*cldev, } EXPORT_SYMBOL(mei_initiate_locality_check);
+/**
+ * Function to verify lprime.
+ *
+ *
+ * Returns 0 on Success, <0 on Failure
+ */
+int mei_verify_lprime(struct mei_cl_device *cldev, struct mei_hdcp_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 device *dev;
+ ssize_t byte;
+
+ if (!data || !rx_lprime)
+ return -EINVAL;
+
+ dev = &cldev->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 = data->port;
+
+ memcpy(verify_lprime_in.l_prime, rx_lprime->l_prime,
Validate rx_lprime->l_prime for NULL
+ sizeof(rx_lprime->l_prime));
+
+ byte = mei_cldev_send(cldev, (u8 *)&verify_lprime_in,
+ sizeof(verify_lprime_in));
+ if (byte < 0) {
+ dev_dbg(dev, "mei_cldev_send failed. %d\n", (int)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. %d\n", (int)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 -1;
+ }
Leave a blank line.
Ok sure.
--Ram
Post by Shankar, Uma
+ return 0;
+}
+EXPORT_SYMBOL(mei_verify_lprime);
+
void mei_cldev_state_notify_clients(struct mei_cl_device *cldev, bool enabled) {
if (enabled)
diff --git a/include/linux/mei_hdcp.h b/include/linux/mei_hdcp.h index
d9c4cac0b276..792143563c46 100644
--- a/include/linux/mei_hdcp.h
+++ b/include/linux/mei_hdcp.h
@@ -124,6 +124,8 @@ int mei_store_pairing_info(struct mei_cl_device *cldev,
int mei_initiate_locality_check(struct mei_cl_device *cldev,
struct mei_hdcp_data *data,
struct hdcp2_lc_init *lc_init_data);
+int mei_verify_lprime(struct mei_cl_device *cldev, struct mei_hdcp_data *data,
+ struct hdcp2_lc_send_lprime *rx_lprime);
#else
return -ENODEV;
}
+static inline
+int mei_verify_lprime(struct mei_cl_device *cldev, struct mei_hdcp_data *data,
+ struct hdcp2_lc_send_lprime *rx_lprime) {
+ return -ENODEV;
+}
#endif /* defined (CONFIG_INTEL_MEI_HDCP) */ #endif /* defined
(_LINUX_MEI_HDCP_H) */
--
2.7.4
_______________________________________________
Intel-gfx mailing list
https://lists.freedesktop.org/mailman/listinfo/intel-gfx
Ramalingam C
2018-04-03 13:57:29 UTC
Permalink
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]

Signed-off-by: Ramalingam C <***@intel.com>
---
drivers/misc/mei/hdcp/mei_hdcp.c | 79 ++++++++++++++++++++++++++++++++++++++++
include/linux/mei_hdcp.h | 8 ++++
2 files changed, 87 insertions(+)

diff --git a/drivers/misc/mei/hdcp/mei_hdcp.c b/drivers/misc/mei/hdcp/mei_hdcp.c
index 64fcecfa5b10..68eb5267a8e7 100644
--- a/drivers/misc/mei/hdcp/mei_hdcp.c
+++ b/drivers/misc/mei/hdcp/mei_hdcp.c
@@ -553,6 +553,85 @@ mei_repeater_check_flow_prepare_ack(struct mei_cl_device *cldev,
}
EXPORT_SYMBOL(mei_repeater_check_flow_prepare_ack);

+static inline void reverse_endianness(u8 *dest, size_t dst_sz, u8 *src)
+{
+ u32 index;
+
+ if (dest != NULL && dst_sz != 0) {
+ for (index = 0; index < dst_sz && index < sizeof(u32);
+ index++) {
+ dest[dst_sz - index - 1] = src[index];
+ }
+ }
+}
+
+/**
+ * mei_verify_mprime:
+ * Function to verify mprime.
+ *
+ * @cldev : Pointer for mei client device
+ * @data : Intel HW specific Data
+ * @stream_ready : pointer for RepeaterAuth_Stream_Ready message.
+ *
+ * Returns 0 on Success, <0 on Failure
+ */
+int mei_verify_mprime(struct mei_cl_device *cldev, struct mei_hdcp_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 device *dev;
+ ssize_t byte;
+
+ if (!stream_ready || !data)
+ return -EINVAL;
+
+ dev = &cldev->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 = data->port;
+
+ memcpy(verify_mprime_in.m_prime, stream_ready->m_prime,
+ HDCP_2_2_MPRIME_LEN);
+ reverse_endianness((u8 *)&verify_mprime_in.seq_num_m,
+ HDCP_2_2_SEQ_NUM_LEN, (u8 *)&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. %d\n", (int)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. %d\n", (int)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 -1;
+ }
+ return 0;
+}
+EXPORT_SYMBOL(mei_verify_mprime);
+
void mei_cldev_state_notify_clients(struct mei_cl_device *cldev, bool enabled)
{
if (enabled)
diff --git a/include/linux/mei_hdcp.h b/include/linux/mei_hdcp.h
index 46e2dc295d03..dbc216e13f97 100644
--- a/include/linux/mei_hdcp.h
+++ b/include/linux/mei_hdcp.h
@@ -134,6 +134,8 @@ mei_repeater_check_flow_prepare_ack(struct mei_cl_device *cldev,
struct hdcp2_rep_send_receiverid_list
*rep_topology,
struct hdcp2_rep_send_ack *rep_send_ack);
+int mei_verify_mprime(struct mei_cl_device *cldev, struct mei_hdcp_data *data,
+ struct hdcp2_rep_stream_ready *stream_ready);
#else
static int mei_cldev_register_notify(struct notifier_block *nb)
{
@@ -201,5 +203,11 @@ mei_repeater_check_flow_prepare_ack(struct mei_cl_device *cldev,
{
return -ENODEV;
}
+static inline
+int mei_verify_mprime(struct mei_cl_device *cldev, struct mei_hdcp_data *data,
+ struct hdcp2_rep_stream_ready *stream_ready)
+{
+ return -ENODEV;
+}
#endif /* defined (CONFIG_INTEL_MEI_HDCP) */
#endif /* defined (_LINUX_MEI_HDCP_H) */
--
2.7.4
Shankar, Uma
2018-05-09 13:50:18 UTC
Permalink
-----Original Message-----
Ramalingam C
Sent: Tuesday, April 3, 2018 7:27 PM
Subject: [PATCH v3 16/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.
Rebased.
cldev is passed as first parameter [Tomas]
Redundant comments and cast are removed [Tomas]
---
drivers/misc/mei/hdcp/mei_hdcp.c | 79
++++++++++++++++++++++++++++++++++++++++
include/linux/mei_hdcp.h | 8 ++++
2 files changed, 87 insertions(+)
diff --git a/drivers/misc/mei/hdcp/mei_hdcp.c
b/drivers/misc/mei/hdcp/mei_hdcp.c
index 64fcecfa5b10..68eb5267a8e7 100644
--- a/drivers/misc/mei/hdcp/mei_hdcp.c
+++ b/drivers/misc/mei/hdcp/mei_hdcp.c
@@ -553,6 +553,85 @@ mei_repeater_check_flow_prepare_ack(struct
mei_cl_device *cldev, }
EXPORT_SYMBOL(mei_repeater_check_flow_prepare_ack);
+static inline void reverse_endianness(u8 *dest, size_t dst_sz, u8 *src)
Function with loop ideally should not be inline.
+{
+ u32 index;
+
+ if (dest != NULL && dst_sz != 0) {
Good to check for src as well. Also this function will not do anything if these
check fails with caller not even been aware of the failure. Atleast return an
error or make sure no parameter validation happens here and its done by calling
function.
+ for (index = 0; index < dst_sz && index < sizeof(u32);
+ index++) {
+ dest[dst_sz - index - 1] = src[index];
+ }
+ }
+}
+
+/**
+ * Function to verify mprime.
+ *
+ *
+ * Returns 0 on Success, <0 on Failure
+ */
+int mei_verify_mprime(struct mei_cl_device *cldev, struct mei_hdcp_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 device *dev;
+ ssize_t byte;
+
+ if (!stream_ready || !data)
+ return -EINVAL;
+
+ dev = &cldev->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 = data->port;
+
+ memcpy(verify_mprime_in.m_prime, stream_ready->m_prime,
Validate stream_ready->m_prime.
+ HDCP_2_2_MPRIME_LEN);
+ reverse_endianness((u8 *)&verify_mprime_in.seq_num_m,
+ HDCP_2_2_SEQ_NUM_LEN, (u8 *)&data-
Post by Ramalingam C
seq_num_m);
+ memcpy(verify_mprime_in.streams, data->streams,
Validate 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. %d\n", (int)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. %d\n", (int)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 -1;
+ }
Leave a blank line here.
+ return 0;
+}
+EXPORT_SYMBOL(mei_verify_mprime);
+
void mei_cldev_state_notify_clients(struct mei_cl_device *cldev, bool enabled) {
if (enabled)
diff --git a/include/linux/mei_hdcp.h b/include/linux/mei_hdcp.h index
46e2dc295d03..dbc216e13f97 100644
--- a/include/linux/mei_hdcp.h
+++ b/include/linux/mei_hdcp.h
@@ -134,6 +134,8 @@ mei_repeater_check_flow_prepare_ack(struct
mei_cl_device *cldev,
struct hdcp2_rep_send_receiverid_list
*rep_topology,
struct hdcp2_rep_send_ack *rep_send_ack);
+int mei_verify_mprime(struct mei_cl_device *cldev, struct mei_hdcp_data *data,
+ struct hdcp2_rep_stream_ready *stream_ready);
#else
*cldev, {
return -ENODEV;
}
+static inline
+int mei_verify_mprime(struct mei_cl_device *cldev, struct mei_hdcp_data *data,
+ struct hdcp2_rep_stream_ready *stream_ready) {
+ return -ENODEV;
+}
#endif /* defined (CONFIG_INTEL_MEI_HDCP) */ #endif /* defined
(_LINUX_MEI_HDCP_H) */
--
2.7.4
_______________________________________________
dri-devel mailing list
https://lists.freedesktop.org/mailman/listinfo/dri-devel
Ramalingam C
2018-05-16 16:32:05 UTC
Permalink
Post by Shankar, Uma
-----Original Message-----
Ramalingam C
Sent: Tuesday, April 3, 2018 7:27 PM
Subject: [PATCH v3 16/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.
Rebased.
cldev is passed as first parameter [Tomas]
Redundant comments and cast are removed [Tomas]
---
drivers/misc/mei/hdcp/mei_hdcp.c | 79
++++++++++++++++++++++++++++++++++++++++
include/linux/mei_hdcp.h | 8 ++++
2 files changed, 87 insertions(+)
diff --git a/drivers/misc/mei/hdcp/mei_hdcp.c
b/drivers/misc/mei/hdcp/mei_hdcp.c
index 64fcecfa5b10..68eb5267a8e7 100644
--- a/drivers/misc/mei/hdcp/mei_hdcp.c
+++ b/drivers/misc/mei/hdcp/mei_hdcp.c
@@ -553,6 +553,85 @@ mei_repeater_check_flow_prepare_ack(struct
mei_cl_device *cldev, }
EXPORT_SYMBOL(mei_repeater_check_flow_prepare_ack);
+static inline void reverse_endianness(u8 *dest, size_t dst_sz, u8 *src)
Function with loop ideally should not be inline.
Thanks for catching it.
Post by Shankar, Uma
+{
+ u32 index;
+
+ if (dest != NULL && dst_sz != 0) {
Good to check for src as well. Also this function will not do anything if these
check fails with caller not even been aware of the failure. Atleast return an
error or make sure no parameter validation happens here and its done by calling
function.
bit rewriting this function. Thanks

--Ram
Post by Shankar, Uma
+ for (index = 0; index < dst_sz && index < sizeof(u32);
+ index++) {
+ dest[dst_sz - index - 1] = src[index];
+ }
+ }
+}
+
+/**
+ * Function to verify mprime.
+ *
+ *
+ * Returns 0 on Success, <0 on Failure
+ */
+int mei_verify_mprime(struct mei_cl_device *cldev, struct mei_hdcp_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 device *dev;
+ ssize_t byte;
+
+ if (!stream_ready || !data)
+ return -EINVAL;
+
+ dev = &cldev->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 = data->port;
+
+ memcpy(verify_mprime_in.m_prime, stream_ready->m_prime,
Validate stream_ready->m_prime.
+ HDCP_2_2_MPRIME_LEN);
+ reverse_endianness((u8 *)&verify_mprime_in.seq_num_m,
+ HDCP_2_2_SEQ_NUM_LEN, (u8 *)&data-
Post by Ramalingam C
seq_num_m);
+ memcpy(verify_mprime_in.streams, data->streams,
Validate 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. %d\n", (int)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. %d\n", (int)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 -1;
+ }
Leave a blank line here.
+ return 0;
+}
+EXPORT_SYMBOL(mei_verify_mprime);
+
void mei_cldev_state_notify_clients(struct mei_cl_device *cldev, bool enabled) {
if (enabled)
diff --git a/include/linux/mei_hdcp.h b/include/linux/mei_hdcp.h index
46e2dc295d03..dbc216e13f97 100644
--- a/include/linux/mei_hdcp.h
+++ b/include/linux/mei_hdcp.h
@@ -134,6 +134,8 @@ mei_repeater_check_flow_prepare_ack(struct mei_cl_device *cldev,
struct hdcp2_rep_send_receiverid_list
*rep_topology,
struct hdcp2_rep_send_ack *rep_send_ack);
+int mei_verify_mprime(struct mei_cl_device *cldev, struct mei_hdcp_data *data,
+ struct hdcp2_rep_stream_ready *stream_ready);
#else
*cldev, {
return -ENODEV;
}
+static inline
+int mei_verify_mprime(struct mei_cl_device *cldev, struct mei_hdcp_data *data,
+ struct hdcp2_rep_stream_ready *stream_ready) {
+ return -ENODEV;
+}
#endif /* defined (CONFIG_INTEL_MEI_HDCP) */ #endif /* defined
(_LINUX_MEI_HDCP_H) */
--
2.7.4
_______________________________________________
dri-devel mailing list
https://lists.freedesktop.org/mailman/listinfo/dri-devel
Ramalingam C
2018-04-03 13:57:35 UTC
Permalink
Adds the wrapper for all mei hdcp2.2 service functions.

v2:
Rebased.
v3:
cldev is moved from mei_hdcp_data to hdcp.

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

diff --git a/drivers/gpu/drm/i915/intel_hdcp.c b/drivers/gpu/drm/i915/intel_hdcp.c
index 1cca4f349064..b4d56b21cf9b 100644
--- a/drivers/gpu/drm/i915/intel_hdcp.c
+++ b/drivers/gpu/drm/i915/intel_hdcp.c
@@ -10,10 +10,13 @@
#include <drm/drm_hdcp.h>
#include <linux/i2c.h>
#include <linux/random.h>
+#include <linux/mei_hdcp.h>

#include "intel_drv.h"
#include "i915_reg.h"

+#define GET_MEI_DDI_INDEX(port) (((port) == PORT_A) ? DDI_A : \
+ (enum hdcp_physical_port) (port))
#define KEY_LOAD_TRIES 5

static int intel_hdcp_poll_ksv_fifo(struct intel_digital_port *intel_dig_port,
@@ -817,3 +820,194 @@ int intel_hdcp_check_link(struct intel_connector *connector)
mutex_unlock(&hdcp->hdcp_mutex);
return ret;
}
+
+static int
+hdcp2_prepare_ake_init(struct intel_hdcp *hdcp, struct hdcp2_ake_init *ake_data)
+{
+ struct mei_hdcp_data *data = &hdcp->mei_data;
+ struct intel_connector *connector = container_of(hdcp,
+ struct intel_connector,
+ hdcp);
+
+ if (!hdcp->cldev)
+ return -EINVAL;
+
+ if (data->port == INVALID_PORT && connector->encoder)
+ data->port = GET_MEI_DDI_INDEX(connector->encoder->port);
+
+ /* Clear ME FW instance for the port, just incase */
+ mei_close_hdcp_session(hdcp->cldev, data);
+
+ return mei_initiate_hdcp2_session(hdcp->cldev, data, ake_data);
+}
+
+static int hdcp2_close_mei_session(struct intel_hdcp *hdcp)
+{
+ struct mei_hdcp_data *data = &hdcp->mei_data;
+
+ if (!hdcp->cldev || data->port == INVALID_PORT)
+ return -EINVAL;
+
+ return mei_close_hdcp_session(hdcp->cldev, data);
+}
+
+static int
+hdcp2_verify_rx_cert_prepare_km(struct intel_hdcp *hdcp,
+ struct hdcp2_ake_send_cert *rx_cert,
+ bool *paired,
+ struct hdcp2_ake_no_stored_km *ek_pub_km,
+ size_t *msg_sz)
+{
+ struct mei_hdcp_data *data = &hdcp->mei_data;
+ int ret;
+
+ if (!hdcp->cldev)
+ return -EINVAL;
+
+ ret = mei_verify_receiver_cert_prepare_km(hdcp->cldev, data, rx_cert,
+ paired, ek_pub_km, msg_sz);
+ if (ret < 0)
+ mei_close_hdcp_session(hdcp->cldev, data);
+
+ return ret;
+}
+
+static int hdcp2_verify_hprime(struct intel_hdcp *hdcp,
+ struct hdcp2_ake_send_hprime *rx_hprime)
+{
+ struct mei_hdcp_data *data = &hdcp->mei_data;
+ int ret;
+
+ if (!hdcp->cldev)
+ return -EINVAL;
+
+ ret = mei_verify_hprime(hdcp->cldev, data, rx_hprime);
+ if (ret < 0)
+ mei_close_hdcp_session(hdcp->cldev, data);
+
+ return ret;
+}
+
+static int
+hdcp2_store_paring_info(struct intel_hdcp *hdcp,
+ struct hdcp2_ake_send_pairing_info *pairing_info)
+{
+ struct mei_hdcp_data *data = &hdcp->mei_data;
+ int ret;
+
+ if (!hdcp->cldev)
+ return -EINVAL;
+
+ ret = mei_store_pairing_info(hdcp->cldev, data, pairing_info);
+ if (ret < 0)
+ mei_close_hdcp_session(hdcp->cldev, data);
+
+ return ret;
+}
+
+static int
+hdcp2_prepare_lc_init(struct intel_hdcp *hdcp, struct hdcp2_lc_init *lc_init)
+{
+ struct mei_hdcp_data *data = &hdcp->mei_data;
+ int ret;
+
+ if (!hdcp->cldev)
+ return -EINVAL;
+
+ ret = mei_initiate_locality_check(hdcp->cldev, data, lc_init);
+ if (ret < 0)
+ mei_close_hdcp_session(hdcp->cldev, data);
+
+ return ret;
+}
+
+static int
+hdcp2_verify_lprime(struct intel_hdcp *hdcp,
+ struct hdcp2_lc_send_lprime *rx_lprime)
+{
+ struct mei_hdcp_data *data = &hdcp->mei_data;
+ int ret;
+
+ if (!hdcp->cldev)
+ return -EINVAL;
+
+ ret = mei_verify_lprime(hdcp->cldev, data, rx_lprime);
+ if (ret < 0)
+ mei_close_hdcp_session(hdcp->cldev, data);
+
+ return ret;
+}
+
+static int hdcp2_prepare_skey(struct intel_hdcp *hdcp,
+ struct hdcp2_ske_send_eks *ske_data)
+{
+ struct mei_hdcp_data *data = &hdcp->mei_data;
+ int ret;
+
+ if (!hdcp->cldev)
+ return -EINVAL;
+
+ ret = mei_get_session_key(hdcp->cldev, data, ske_data);
+ if (ret < 0)
+ mei_close_hdcp_session(hdcp->cldev, data);
+
+ return ret;
+}
+
+static int
+hdcp2_verify_rep_topology_prepare_ack(
+ struct intel_hdcp *hdcp,
+ struct hdcp2_rep_send_receiverid_list *rep_topology,
+ struct hdcp2_rep_send_ack *rep_send_ack)
+{
+ struct mei_hdcp_data *data = &hdcp->mei_data;
+ int ret;
+
+ if (!hdcp->cldev)
+ return -EINVAL;
+
+ ret = mei_repeater_check_flow_prepare_ack(hdcp->cldev, data,
+ rep_topology, rep_send_ack);
+ if (ret < 0)
+ mei_close_hdcp_session(hdcp->cldev, data);
+
+ return ret;
+}
+
+static int
+hdcp2_verify_mprime(struct intel_hdcp *hdcp,
+ struct hdcp2_rep_stream_ready *stream_ready)
+{
+ struct mei_hdcp_data *data = &hdcp->mei_data;
+ int ret;
+
+ if (!hdcp->cldev)
+ return -EINVAL;
+
+ ret = mei_verify_mprime(hdcp->cldev, data, stream_ready);
+ if (ret < 0)
+ mei_close_hdcp_session(hdcp->cldev, data);
+
+ return ret;
+}
+
+
+static int hdcp2_authenticate_port(struct intel_hdcp *hdcp)
+{
+ struct mei_hdcp_data *data = &hdcp->mei_data;
+ int ret;
+
+ if (!hdcp->cldev)
+ return -EINVAL;
+
+ ret = mei_enable_hdcp_authentication(hdcp->cldev, data);
+ if (ret < 0)
+ mei_close_hdcp_session(hdcp->cldev, data);
+
+ return ret;
+}
+
+static inline int hdcp2_deauthenticate_port(struct intel_hdcp *hdcp)
+{
+ return hdcp2_close_mei_session(hdcp);
+}
--
2.7.4
Shankar, Uma
2018-05-09 15:10:04 UTC
Permalink
-----Original Message-----
Ramalingam C
Sent: Tuesday, April 3, 2018 7:28 PM
Subject: [Intel-gfx] [PATCH v3 22/40] drm/i915: Wrappers for mei HDCP2.2
services
Adds the wrapper for all mei hdcp2.2 service functions.
Rebased.
cldev is moved from mei_hdcp_data to hdcp.
---
drivers/gpu/drm/i915/intel_hdcp.c | 194
++++++++++++++++++++++++++++++++++++++
1 file changed, 194 insertions(+)
diff --git a/drivers/gpu/drm/i915/intel_hdcp.c
b/drivers/gpu/drm/i915/intel_hdcp.c
index 1cca4f349064..b4d56b21cf9b 100644
--- a/drivers/gpu/drm/i915/intel_hdcp.c
+++ b/drivers/gpu/drm/i915/intel_hdcp.c
@@ -10,10 +10,13 @@
#include <drm/drm_hdcp.h>
#include <linux/i2c.h>
#include <linux/random.h>
+#include <linux/mei_hdcp.h>
#include "intel_drv.h"
#include "i915_reg.h"
+#define GET_MEI_DDI_INDEX(port) (((port) == PORT_A) ? DDI_A : \
+ (enum hdcp_physical_port) (port))
#define KEY_LOAD_TRIES 5
*connector)
mutex_unlock(&hdcp->hdcp_mutex);
return ret;
}
+
+static int
+hdcp2_prepare_ake_init(struct intel_hdcp *hdcp, struct hdcp2_ake_init
+*ake_data) {
+ struct mei_hdcp_data *data = &hdcp->mei_data;
+ struct intel_connector *connector = container_of(hdcp,
+ struct intel_connector,
+ hdcp);
+
+ if (!hdcp->cldev)
+ return -EINVAL;
+
+ if (data->port == INVALID_PORT && connector->encoder)
+ data->port = GET_MEI_DDI_INDEX(connector->encoder->port);
I believe caller should provide valid port and this should fail if port received is invalid instead of
retrieving it here.
+
+ /* Clear ME FW instance for the port, just incase */
+ mei_close_hdcp_session(hdcp->cldev, data);
+
+ return mei_initiate_hdcp2_session(hdcp->cldev, data, ake_data); }
+
+static int hdcp2_close_mei_session(struct intel_hdcp *hdcp) {
+ struct mei_hdcp_data *data = &hdcp->mei_data;
+
+ if (!hdcp->cldev || data->port == INVALID_PORT)
This is what I was saying for above.
+ return -EINVAL;
+
+ return mei_close_hdcp_session(hdcp->cldev, data); }
+
+static int
+hdcp2_verify_rx_cert_prepare_km(struct intel_hdcp *hdcp,
+ struct hdcp2_ake_send_cert *rx_cert,
+ bool *paired,
+ struct hdcp2_ake_no_stored_km *ek_pub_km,
+ size_t *msg_sz)
+{
+ struct mei_hdcp_data *data = &hdcp->mei_data;
+ int ret;
+
+ if (!hdcp->cldev)
+ return -EINVAL;
+
+ ret = mei_verify_receiver_cert_prepare_km(hdcp->cldev, data, rx_cert,
+ paired, ek_pub_km, msg_sz);
+ if (ret < 0)
+ mei_close_hdcp_session(hdcp->cldev, data);
+
+ return ret;
+}
+
+static int hdcp2_verify_hprime(struct intel_hdcp *hdcp,
+ struct hdcp2_ake_send_hprime *rx_hprime) {
+ struct mei_hdcp_data *data = &hdcp->mei_data;
+ int ret;
+
+ if (!hdcp->cldev)
+ return -EINVAL;
+
+ ret = mei_verify_hprime(hdcp->cldev, data, rx_hprime);
+ if (ret < 0)
+ mei_close_hdcp_session(hdcp->cldev, data);
+
+ return ret;
+}
+
+static int
+hdcp2_store_paring_info(struct intel_hdcp *hdcp,
+ struct hdcp2_ake_send_pairing_info *pairing_info) {
+ struct mei_hdcp_data *data = &hdcp->mei_data;
+ int ret;
+
+ if (!hdcp->cldev)
+ return -EINVAL;
+
+ ret = mei_store_pairing_info(hdcp->cldev, data, pairing_info);
+ if (ret < 0)
+ mei_close_hdcp_session(hdcp->cldev, data);
+
+ return ret;
+}
+
+static int
+hdcp2_prepare_lc_init(struct intel_hdcp *hdcp, struct hdcp2_lc_init
+*lc_init) {
+ struct mei_hdcp_data *data = &hdcp->mei_data;
+ int ret;
+
+ if (!hdcp->cldev)
+ return -EINVAL;
+
+ ret = mei_initiate_locality_check(hdcp->cldev, data, lc_init);
+ if (ret < 0)
+ mei_close_hdcp_session(hdcp->cldev, data);
+
+ return ret;
+}
+
+static int
+hdcp2_verify_lprime(struct intel_hdcp *hdcp,
+ struct hdcp2_lc_send_lprime *rx_lprime) {
+ struct mei_hdcp_data *data = &hdcp->mei_data;
+ int ret;
+
+ if (!hdcp->cldev)
+ return -EINVAL;
+
+ ret = mei_verify_lprime(hdcp->cldev, data, rx_lprime);
+ if (ret < 0)
+ mei_close_hdcp_session(hdcp->cldev, data);
+
+ return ret;
+}
+
+static int hdcp2_prepare_skey(struct intel_hdcp *hdcp,
+ struct hdcp2_ske_send_eks *ske_data) {
+ struct mei_hdcp_data *data = &hdcp->mei_data;
+ int ret;
+
+ if (!hdcp->cldev)
+ return -EINVAL;
+
+ ret = mei_get_session_key(hdcp->cldev, data, ske_data);
+ if (ret < 0)
+ mei_close_hdcp_session(hdcp->cldev, data);
+
+ return ret;
+}
+
+static int
+hdcp2_verify_rep_topology_prepare_ack(
+ struct intel_hdcp *hdcp,
+ struct hdcp2_rep_send_receiverid_list *rep_topology,
+ struct hdcp2_rep_send_ack *rep_send_ack) {
+ struct mei_hdcp_data *data = &hdcp->mei_data;
+ int ret;
+
+ if (!hdcp->cldev)
+ return -EINVAL;
+
+ ret = mei_repeater_check_flow_prepare_ack(hdcp->cldev, data,
+ rep_topology, rep_send_ack);
+ if (ret < 0)
+ mei_close_hdcp_session(hdcp->cldev, data);
+
+ return ret;
+}
+
+static int
+hdcp2_verify_mprime(struct intel_hdcp *hdcp,
+ struct hdcp2_rep_stream_ready *stream_ready) {
+ struct mei_hdcp_data *data = &hdcp->mei_data;
+ int ret;
+
+ if (!hdcp->cldev)
+ return -EINVAL;
+
+ ret = mei_verify_mprime(hdcp->cldev, data, stream_ready);
+ if (ret < 0)
+ mei_close_hdcp_session(hdcp->cldev, data);
+
+ return ret;
+}
+
+
+static int hdcp2_authenticate_port(struct intel_hdcp *hdcp) {
+ struct mei_hdcp_data *data = &hdcp->mei_data;
+ int ret;
+
+ if (!hdcp->cldev)
+ return -EINVAL;
+
+ ret = mei_enable_hdcp_authentication(hdcp->cldev, data);
+ if (ret < 0)
+ mei_close_hdcp_session(hdcp->cldev, data);
+
+ return ret;
+}
+
+static inline int hdcp2_deauthenticate_port(struct intel_hdcp *hdcp) {
+ return hdcp2_close_mei_session(hdcp);
+}
--
2.7.4
_______________________________________________
Intel-gfx mailing list
https://lists.freedesktop.org/mailman/listinfo/intel-gfx
Ramalingam C
2018-04-03 13:57:28 UTC
Permalink
Request ot ME to verify the downatream 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]

Signed-off-by: Ramalingam C <***@intel.com>
---
drivers/misc/mei/hdcp/mei_hdcp.c | 75 ++++++++++++++++++++++++++++++++++++++++
include/linux/mei_hdcp.h | 15 ++++++++
2 files changed, 90 insertions(+)

diff --git a/drivers/misc/mei/hdcp/mei_hdcp.c b/drivers/misc/mei/hdcp/mei_hdcp.c
index abfcc57863b8..64fcecfa5b10 100644
--- a/drivers/misc/mei/hdcp/mei_hdcp.c
+++ b/drivers/misc/mei/hdcp/mei_hdcp.c
@@ -478,6 +478,81 @@ int mei_get_session_key(struct mei_cl_device *cldev, struct mei_hdcp_data *data,
}
EXPORT_SYMBOL(mei_get_session_key);

+/**
+ * mei_repeater_check_flow_prepare_ack:
+ * Function to validate the Downstream topology and prepare rep_ack.
+ *
+ * @cldev : Pointer for mei client device
+ * @data : Intel HW specific Data
+ * @rep_topology : Pointer for Receiver Id List to be validated.
+ * @rep_send_ack : Pointer for repeater ack
+ *
+ * Returns 0 on Success, <0 on Failure
+ */
+
+int
+mei_repeater_check_flow_prepare_ack(struct mei_cl_device *cldev,
+ struct mei_hdcp_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 device *dev;
+ ssize_t byte;
+
+ if (!rep_topology || !rep_send_ack || !data)
+ return -EINVAL;
+
+ dev = &cldev->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 = 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_LPRIME_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. %d\n", (int)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. %d\n", (int)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 -1;
+ }
+
+ memcpy(rep_send_ack->v, verify_repeater_out.v,
+ HDCP_2_2_LPRIME_HALF_LEN);
+ rep_send_ack->msg_id = HDCP_2_2_REP_SEND_ACK;
+ return 0;
+}
+EXPORT_SYMBOL(mei_repeater_check_flow_prepare_ack);
+
void mei_cldev_state_notify_clients(struct mei_cl_device *cldev, bool enabled)
{
if (enabled)
diff --git a/include/linux/mei_hdcp.h b/include/linux/mei_hdcp.h
index 534170d746af..46e2dc295d03 100644
--- a/include/linux/mei_hdcp.h
+++ b/include/linux/mei_hdcp.h
@@ -128,6 +128,12 @@ int mei_verify_lprime(struct mei_cl_device *cldev, struct mei_hdcp_data *data,
struct hdcp2_lc_send_lprime *rx_lprime);
int mei_get_session_key(struct mei_cl_device *cldev, struct mei_hdcp_data *data,
struct hdcp2_ske_send_eks *ske_data);
+int
+mei_repeater_check_flow_prepare_ack(struct mei_cl_device *cldev,
+ struct mei_hdcp_data *data,
+ struct hdcp2_rep_send_receiverid_list
+ *rep_topology,
+ struct hdcp2_rep_send_ack *rep_send_ack);
#else
static int mei_cldev_register_notify(struct notifier_block *nb)
{
@@ -186,5 +192,14 @@ int mei_get_session_key(struct mei_cl_device *cldev, struct mei_hdcp_data *data,
{
return -ENODEV;
}
+static inline int
+mei_repeater_check_flow_prepare_ack(struct mei_cl_device *cldev,
+ struct mei_hdcp_data *data,
+ struct hdcp2_rep_send_receiverid_list
+ *rep_topology,
+ struct hdcp2_rep_send_ack *rep_send_ack)
+{
+ return -ENODEV;
+}
#endif /* defined (CONFIG_INTEL_MEI_HDCP) */
#endif /* defined (_LINUX_MEI_HDCP_H) */
--
2.7.4
Shankar, Uma
2018-05-09 11:04:17 UTC
Permalink
-----Original Message-----
Ramalingam C
Sent: Tuesday, April 3, 2018 7:27 PM
Subject: [PATCH v3 15/40] misc/mei/hdcp: Repeater topology verifcation and ack
Typo in verification.
Request ot ME to verify the downatream topology information received.
"To" misspelled. Also typo in downstream.
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.
Rebased.
cldev is passed as first parameter [Tomas]
Redundant comments and cast are removed [Tomas]
---
drivers/misc/mei/hdcp/mei_hdcp.c | 75
++++++++++++++++++++++++++++++++++++++++
include/linux/mei_hdcp.h | 15 ++++++++
2 files changed, 90 insertions(+)
diff --git a/drivers/misc/mei/hdcp/mei_hdcp.c
b/drivers/misc/mei/hdcp/mei_hdcp.c
index abfcc57863b8..64fcecfa5b10 100644
--- a/drivers/misc/mei/hdcp/mei_hdcp.c
+++ b/drivers/misc/mei/hdcp/mei_hdcp.c
@@ -478,6 +478,81 @@ int mei_get_session_key(struct mei_cl_device *cldev,
struct mei_hdcp_data *data, } EXPORT_SYMBOL(mei_get_session_key);
+/**
+ * Function to validate the Downstream topology and prepare rep_ack.
+ *
+ *
+ * Returns 0 on Success, <0 on Failure
+ */
+
+int
+mei_repeater_check_flow_prepare_ack(struct mei_cl_device *cldev,
+ struct mei_hdcp_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 device *dev;
+ ssize_t byte;
+
+ if (!rep_topology || !rep_send_ack || !data)
+ return -EINVAL;
+
+ dev = &cldev->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 = 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_LPRIME_HALF_LEN);
+ memcpy(verify_repeater_in.receiver_ids, rep_topology->receiver_ids,
+ HDCP_2_2_RECEIVER_IDS_MAX_LEN);
Check for validity of rep_topology->... pointers.
+
+ byte = mei_cldev_send(cldev, (u8 *)&verify_repeater_in,
+ sizeof(verify_repeater_in));
+ if (byte < 0) {
+ dev_dbg(dev, "mei_cldev_send failed. %d\n", (int)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. %d\n", (int)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 -1;
+ }
+
+ memcpy(rep_send_ack->v, verify_repeater_out.v,
Same as above.
+ HDCP_2_2_LPRIME_HALF_LEN);
+ rep_send_ack->msg_id = HDCP_2_2_REP_SEND_ACK;
Leave a blank line here.
+ return 0;
+}
+EXPORT_SYMBOL(mei_repeater_check_flow_prepare_ack);
+
void mei_cldev_state_notify_clients(struct mei_cl_device *cldev, bool enabled) {
if (enabled)
diff --git a/include/linux/mei_hdcp.h b/include/linux/mei_hdcp.h index
534170d746af..46e2dc295d03 100644
--- a/include/linux/mei_hdcp.h
+++ b/include/linux/mei_hdcp.h
@@ -128,6 +128,12 @@ int mei_verify_lprime(struct mei_cl_device *cldev,
struct mei_hdcp_data *data,
struct hdcp2_lc_send_lprime *rx_lprime); int
mei_get_session_key(struct mei_cl_device *cldev, struct mei_hdcp_data *data,
struct hdcp2_ske_send_eks *ske_data);
+int
+mei_repeater_check_flow_prepare_ack(struct mei_cl_device *cldev,
+ struct mei_hdcp_data *data,
+ struct hdcp2_rep_send_receiverid_list
+ *rep_topology,
+ struct hdcp2_rep_send_ack *rep_send_ack);
#else
mei_hdcp_data *data, {
return -ENODEV;
}
+static inline int
+mei_repeater_check_flow_prepare_ack(struct mei_cl_device *cldev,
+ struct mei_hdcp_data *data,
+ struct hdcp2_rep_send_receiverid_list
+ *rep_topology,
+ struct hdcp2_rep_send_ack *rep_send_ack) {
+ return -ENODEV;
+}
#endif /* defined (CONFIG_INTEL_MEI_HDCP) */ #endif /* defined
(_LINUX_MEI_HDCP_H) */
--
2.7.4
_______________________________________________
dri-devel mailing list
https://lists.freedesktop.org/mailman/listinfo/dri-devel
Ramalingam C
2018-05-16 16:32:48 UTC
Permalink
Post by Shankar, Uma
-----Original Message-----
Ramalingam C
Sent: Tuesday, April 3, 2018 7:27 PM
Subject: [PATCH v3 15/40] misc/mei/hdcp: Repeater topology verifcation and ack
Typo in verification.
Request ot ME to verify the downatream topology information received.
"To" misspelled. Also typo in downstream.
ok. Will fix it.
Post by Shankar, Uma
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.
Rebased.
cldev is passed as first parameter [Tomas]
Redundant comments and cast are removed [Tomas]
---
drivers/misc/mei/hdcp/mei_hdcp.c | 75
++++++++++++++++++++++++++++++++++++++++
include/linux/mei_hdcp.h | 15 ++++++++
2 files changed, 90 insertions(+)
diff --git a/drivers/misc/mei/hdcp/mei_hdcp.c
b/drivers/misc/mei/hdcp/mei_hdcp.c
index abfcc57863b8..64fcecfa5b10 100644
--- a/drivers/misc/mei/hdcp/mei_hdcp.c
+++ b/drivers/misc/mei/hdcp/mei_hdcp.c
@@ -478,6 +478,81 @@ int mei_get_session_key(struct mei_cl_device *cldev,
struct mei_hdcp_data *data, } EXPORT_SYMBOL(mei_get_session_key);
+/**
+ * Function to validate the Downstream topology and prepare rep_ack.
+ *
+ *
+ * Returns 0 on Success, <0 on Failure
+ */
+
+int
+mei_repeater_check_flow_prepare_ack(struct mei_cl_device *cldev,
+ struct mei_hdcp_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 device *dev;
+ ssize_t byte;
+
+ if (!rep_topology || !rep_send_ack || !data)
+ return -EINVAL;
+
+ dev = &cldev->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 = 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_LPRIME_HALF_LEN);
+ memcpy(verify_repeater_in.receiver_ids, rep_topology->receiver_ids,
+ HDCP_2_2_RECEIVER_IDS_MAX_LEN);
Check for validity of rep_topology->... pointers.
+
+ byte = mei_cldev_send(cldev, (u8 *)&verify_repeater_in,
+ sizeof(verify_repeater_in));
+ if (byte < 0) {
+ dev_dbg(dev, "mei_cldev_send failed. %d\n", (int)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. %d\n", (int)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 -1;
+ }
+
+ memcpy(rep_send_ack->v, verify_repeater_out.v,
Same as above.
+ HDCP_2_2_LPRIME_HALF_LEN);
+ rep_send_ack->msg_id = HDCP_2_2_REP_SEND_ACK;
Leave a blank line here.
Ok.

--Ram
Post by Shankar, Uma
+ return 0;
+}
+EXPORT_SYMBOL(mei_repeater_check_flow_prepare_ack);
+
void mei_cldev_state_notify_clients(struct mei_cl_device *cldev, bool enabled) {
if (enabled)
diff --git a/include/linux/mei_hdcp.h b/include/linux/mei_hdcp.h index
534170d746af..46e2dc295d03 100644
--- a/include/linux/mei_hdcp.h
+++ b/include/linux/mei_hdcp.h
@@ -128,6 +128,12 @@ int mei_verify_lprime(struct mei_cl_device *cldev,
struct mei_hdcp_data *data,
struct hdcp2_lc_send_lprime *rx_lprime); int
mei_get_session_key(struct mei_cl_device *cldev, struct mei_hdcp_data *data,
struct hdcp2_ske_send_eks *ske_data);
+int
+mei_repeater_check_flow_prepare_ack(struct mei_cl_device *cldev,
+ struct mei_hdcp_data *data,
+ struct hdcp2_rep_send_receiverid_list
+ *rep_topology,
+ struct hdcp2_rep_send_ack *rep_send_ack);
#else
mei_hdcp_data *data, {
return -ENODEV;
}
+static inline int
+mei_repeater_check_flow_prepare_ack(struct mei_cl_device *cldev,
+ struct mei_hdcp_data *data,
+ struct hdcp2_rep_send_receiverid_list
+ *rep_topology,
+ struct hdcp2_rep_send_ack *rep_send_ack) {
+ return -ENODEV;
+}
#endif /* defined (CONFIG_INTEL_MEI_HDCP) */ #endif /* defined
(_LINUX_MEI_HDCP_H) */
--
2.7.4
_______________________________________________
dri-devel mailing list
https://lists.freedesktop.org/mailman/listinfo/dri-devel
Ramalingam C
2018-04-03 13:57:25 UTC
Permalink
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]

Signed-off-by: Ramalingam C <***@intel.com>
---
drivers/misc/mei/hdcp/mei_hdcp.c | 56 ++++++++++++++++++++++++++++++++++++++++
include/linux/mei_hdcp.h | 10 +++++++
2 files changed, 66 insertions(+)

diff --git a/drivers/misc/mei/hdcp/mei_hdcp.c b/drivers/misc/mei/hdcp/mei_hdcp.c
index 60afdd0cee79..9bd7e66a91e4 100644
--- a/drivers/misc/mei/hdcp/mei_hdcp.c
+++ b/drivers/misc/mei/hdcp/mei_hdcp.c
@@ -305,6 +305,62 @@ int mei_store_pairing_info(struct mei_cl_device *cldev,
}
EXPORT_SYMBOL(mei_store_pairing_info);

+/**
+ * mei_initiate_locality_check:
+ * Function to prepare LC_Init.
+ *
+ * @cldev : Pointer for mei client device
+ * @data : Intel HW specific Data
+ * @hdcp2_lc_init : Pointer for storing LC_Init
+ *
+ * Returns 0 on Success, <0 on Failure
+ */
+int mei_initiate_locality_check(struct mei_cl_device *cldev,
+ struct mei_hdcp_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 device *dev;
+ ssize_t byte;
+
+ if (!data || !lc_init_data)
+ return -EINVAL;
+
+ dev = &cldev->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 = 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. %d\n", (int)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. %d\n", (int)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 -1;
+ }
+
+ 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;
+}
+EXPORT_SYMBOL(mei_initiate_locality_check);
+
void mei_cldev_state_notify_clients(struct mei_cl_device *cldev, bool enabled)
{
if (enabled)
diff --git a/include/linux/mei_hdcp.h b/include/linux/mei_hdcp.h
index be16e49d8018..d9c4cac0b276 100644
--- a/include/linux/mei_hdcp.h
+++ b/include/linux/mei_hdcp.h
@@ -121,6 +121,9 @@ int mei_verify_hprime(struct mei_cl_device *cldev, struct mei_hdcp_data *data,
int mei_store_pairing_info(struct mei_cl_device *cldev,
struct mei_hdcp_data *data,
struct hdcp2_ake_send_pairing_info *pairing_info);
+int mei_initiate_locality_check(struct mei_cl_device *cldev,
+ struct mei_hdcp_data *data,
+ struct hdcp2_lc_init *lc_init_data);
#else
static int mei_cldev_register_notify(struct notifier_block *nb)
{
@@ -160,5 +163,12 @@ int mei_store_pairing_info(struct mei_cl_device *cldev,
{
return -ENODEV;
}
+static inline
+int mei_initiate_locality_check(struct mei_cl_device *cldev,
+ struct mei_hdcp_data *data,
+ struct hdcp2_lc_init *lc_init_data)
+{
+ return -ENODEV;
+}
#endif /* defined (CONFIG_INTEL_MEI_HDCP) */
#endif /* defined (_LINUX_MEI_HDCP_H) */
--
2.7.4
kbuild test robot
2018-04-03 23:02:17 UTC
Permalink
Hi Ramalingam,

Thank you for the patch! Yet something to improve:

[auto build test ERROR on drm-intel/for-linux-next]
[also build test ERROR on next-20180403]
[cannot apply to v4.16]
[if your patch is applied to the wrong git tree, please drop us a note to help improve the system]

url: https://github.com/0day-ci/linux/commits/Ramalingam-C/drm-i915-Implement-HDCP2-2/20180404-031743
base: git://anongit.freedesktop.org/drm-intel for-linux-next
config: i386-allmodconfig (attached as .config)
compiler: gcc-7 (Debian 7.3.0-1) 7.3.0
reproduce:
# save the attached .config to linux build tree
make ARCH=i386

All errors (new ones prefixed by >>):

drivers/misc/mei/hdcp/mei_hdcp.c:52:5: error: redefinition of 'mei_initiate_hdcp2_session'
int mei_initiate_hdcp2_session(struct mei_cl_device *cldev,
^~~~~~~~~~~~~~~~~~~~~~~~~~
In file included from drivers/misc/mei/hdcp/mei_hdcp.c:35:0:
include/linux/mei_hdcp.h:137:5: note: previous definition of 'mei_initiate_hdcp2_session' was here
int mei_initiate_hdcp2_session(struct mei_cl_device *cldev,
^~~~~~~~~~~~~~~~~~~~~~~~~~
drivers/misc/mei/hdcp/mei_hdcp.c:122:1: error: redefinition of 'mei_verify_receiver_cert_prepare_km'
mei_verify_receiver_cert_prepare_km(struct mei_cl_device *cldev,
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
In file included from drivers/misc/mei/hdcp/mei_hdcp.c:35:0:
include/linux/mei_hdcp.h:144:1: note: previous definition of 'mei_verify_receiver_cert_prepare_km' was here
mei_verify_receiver_cert_prepare_km(struct mei_cl_device *cldev,
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
drivers/misc/mei/hdcp/mei_hdcp.c:200:5: error: redefinition of 'mei_verify_hprime'
int mei_verify_hprime(struct mei_cl_device *cldev, struct mei_hdcp_data *data,
^~~~~~~~~~~~~~~~~
In file included from drivers/misc/mei/hdcp/mei_hdcp.c:35:0:
include/linux/mei_hdcp.h:154:5: note: previous definition of 'mei_verify_hprime' was here
int mei_verify_hprime(struct mei_cl_device *cldev, struct mei_hdcp_data *data,
^~~~~~~~~~~~~~~~~
drivers/misc/mei/hdcp/mei_hdcp.c:258:5: error: redefinition of 'mei_store_pairing_info'
int mei_store_pairing_info(struct mei_cl_device *cldev,
^~~~~~~~~~~~~~~~~~~~~~
In file included from drivers/misc/mei/hdcp/mei_hdcp.c:35:0:
include/linux/mei_hdcp.h:160:5: note: previous definition of 'mei_store_pairing_info' was here
int mei_store_pairing_info(struct mei_cl_device *cldev,
^~~~~~~~~~~~~~~~~~~~~~
drivers/misc/mei/hdcp/mei_hdcp.c:318:5: error: redefinition of 'mei_initiate_locality_check'
int mei_initiate_locality_check(struct mei_cl_device *cldev,
^~~~~~~~~~~~~~~~~~~~~~~~~~~
In file included from drivers/misc/mei/hdcp/mei_hdcp.c:35:0:
include/linux/mei_hdcp.h:167:5: note: previous definition of 'mei_initiate_locality_check' was here
int mei_initiate_locality_check(struct mei_cl_device *cldev,
^~~~~~~~~~~~~~~~~~~~~~~~~~~
drivers/misc/mei/hdcp/mei_hdcp.c:374:5: error: redefinition of 'mei_cldev_register_notify'
int mei_cldev_register_notify(struct notifier_block *nb)
^~~~~~~~~~~~~~~~~~~~~~~~~
In file included from drivers/misc/mei/hdcp/mei_hdcp.c:35:0:
include/linux/mei_hdcp.h:128:12: note: previous definition of 'mei_cldev_register_notify' was here
static int mei_cldev_register_notify(struct notifier_block *nb)
^~~~~~~~~~~~~~~~~~~~~~~~~
drivers/misc/mei/hdcp/mei_hdcp.c:380:5: error: redefinition of 'mei_cldev_unregister_notify'
int mei_cldev_unregister_notify(struct notifier_block *nb)
^~~~~~~~~~~~~~~~~~~~~~~~~~~
In file included from drivers/misc/mei/hdcp/mei_hdcp.c:35:0:
include/linux/mei_hdcp.h:132:12: note: previous definition of 'mei_cldev_unregister_notify' was here
static int mei_cldev_unregister_notify(struct notifier_block *nb)
^~~~~~~~~~~~~~~~~~~~~~~~~~~
include/linux/mei_hdcp.h:132:12: warning: 'mei_cldev_unregister_notify' defined but not used [-Wunused-function]
include/linux/mei_hdcp.h:128:12: warning: 'mei_cldev_register_notify' defined but not used [-Wunused-function]
static int mei_cldev_register_notify(struct notifier_block *nb)
^~~~~~~~~~~~~~~~~~~~~~~~~

vim +/mei_initiate_locality_check +318 drivers/misc/mei/hdcp/mei_hdcp.c

246
247 /**
248 * mei_store_pairing_info:
249 * Function to store pairing info received from panel
250 *
251 * @cldev : Pointer for mei client device
252 * @data : Intel HW specific Data
253 * @pairing_info : Pointer for AKE_Send_Pairing_Info
254 *
255 * Returns 0 on Success, <0 on Failure
256 */
257
258 int mei_store_pairing_info(struct mei_cl_device *cldev,
259 struct mei_hdcp_data *data,
260 struct hdcp2_ake_send_pairing_info *pairing_info)
261 {
262 struct wired_cmd_ake_send_pairing_info_in pairing_info_in = { { 0 } };
263 struct wired_cmd_ake_send_pairing_info_out pairing_info_out = { { 0 } };
264 struct device *dev;
265 ssize_t byte;
266
267 if (!data || !pairing_info)
268 return -EINVAL;
269
270 dev = &cldev->dev;
271
272 pairing_info_in.header.api_version = HDCP_API_VERSION;
273 pairing_info_in.header.command_id = WIRED_AKE_SEND_PAIRING_INFO;
274 pairing_info_in.header.status = ME_HDCP_STATUS_SUCCESS;
275 pairing_info_in.header.buffer_len =
276 WIRED_CMD_BUF_LEN_SEND_PAIRING_INFO_IN;
277
278 pairing_info_in.port.integrated_port_type = data->port_type;
279 pairing_info_in.port.physical_port = data->port;
280
281 memcpy(pairing_info_in.e_kh_km, pairing_info->e_kh_km,
282 sizeof(pairing_info_in.e_kh_km));
283
284 byte = mei_cldev_send(cldev, (u8 *)&pairing_info_in,
285 sizeof(pairing_info_in));
286 if (byte < 0) {
287 dev_dbg(dev, "mei_cldev_send failed. %d\n", (int)byte);
288 return byte;
289 }
290
291 byte = mei_cldev_recv(cldev, (u8 *)&pairing_info_out,
292 sizeof(pairing_info_out));
293 if (byte < 0) {
294 dev_dbg(dev, "mei_cldev_recv failed. %d\n", (int)byte);
295 return byte;
296 }
297
298 if (pairing_info_out.header.status != ME_HDCP_STATUS_SUCCESS) {
299 dev_dbg(dev, "ME cmd 0x%08X failed. Status: 0x%X\n",
300 WIRED_AKE_SEND_PAIRING_INFO,
301 pairing_info_out.header.status);
302 return -1;
303 }
304 return 0;
305 }
306 EXPORT_SYMBOL(mei_store_pairing_info);
307
308 /**
309 * mei_initiate_locality_check:
310 * Function to prepare LC_Init.
311 *
312 * @cldev : Pointer for mei client device
313 * @data : Intel HW specific Data
314 * @hdcp2_lc_init : Pointer for storing LC_Init
315 *
316 * Returns 0 on Success, <0 on Failure
317 */
318 int mei_initiate_locality_check(struct mei_cl_device *cldev,
319 struct mei_hdcp_data *data,
320 struct hdcp2_lc_init *lc_init_data)
321 {
322 struct wired_cmd_init_locality_check_in lc_init_in = { { 0 } };
323 struct wired_cmd_init_locality_check_out lc_init_out = { { 0 } };
324 struct device *dev;
325 ssize_t byte;
326
327 if (!data || !lc_init_data)
328 return -EINVAL;
329
330 dev = &cldev->dev;
331
332 lc_init_in.header.api_version = HDCP_API_VERSION;
333 lc_init_in.header.command_id = WIRED_INIT_LOCALITY_CHECK;
334 lc_init_in.header.status = ME_HDCP_STATUS_SUCCESS;
335 lc_init_in.header.buffer_len = WIRED_CMD_BUF_LEN_INIT_LOCALITY_CHECK_IN;
336
337 lc_init_in.port.integrated_port_type = data->port_type;
338 lc_init_in.port.physical_port = data->port;
339
340 byte = mei_cldev_send(cldev, (u8 *)&lc_init_in, sizeof(lc_init_in));
341 if (byte < 0) {
342 dev_dbg(dev, "mei_cldev_send failed. %d\n", (int)byte);
343 return byte;
344 }
345
346 byte = mei_cldev_recv(cldev, (u8 *)&lc_init_out, sizeof(lc_init_out));
347 if (byte < 0) {
348 dev_dbg(dev, "mei_cldev_recv failed. %d\n", (int)byte);
349 return byte;
350 }
351
352 if (lc_init_out.header.status != ME_HDCP_STATUS_SUCCESS) {
353 dev_dbg(dev, "ME cmd 0x%08X Failed. status: 0x%X\n",
354 WIRED_INIT_LOCALITY_CHECK, lc_init_out.header.status);
355 return -1;
356 }
357
358 lc_init_data->msg_id = HDCP_2_2_LC_INIT;
359 memcpy(lc_init_data->r_n, lc_init_out.r_n, HDCP_2_2_RN_LEN);
360 return 0;
361 }
362 EXPORT_SYMBOL(mei_initiate_locality_check);
363

---
0-DAY kernel test infrastructure Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all Intel Corporation
Shankar, Uma
2018-05-09 10:31:55 UTC
Permalink
-----Original Message-----
Ramalingam C
Sent: Tuesday, April 3, 2018 7:27 PM
Subject: [PATCH v3 12/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.
Rebased.
cldev is passed as first parameter [Tomas]
Redundant comments and cast are removed [Tomas]
---
drivers/misc/mei/hdcp/mei_hdcp.c | 56
++++++++++++++++++++++++++++++++++++++++
include/linux/mei_hdcp.h | 10 +++++++
2 files changed, 66 insertions(+)
diff --git a/drivers/misc/mei/hdcp/mei_hdcp.c
b/drivers/misc/mei/hdcp/mei_hdcp.c
index 60afdd0cee79..9bd7e66a91e4 100644
--- a/drivers/misc/mei/hdcp/mei_hdcp.c
+++ b/drivers/misc/mei/hdcp/mei_hdcp.c
@@ -305,6 +305,62 @@ int mei_store_pairing_info(struct mei_cl_device *cldev,
} EXPORT_SYMBOL(mei_store_pairing_info);
+/**
+ * Function to prepare LC_Init.
+ *
+ *
+ * Returns 0 on Success, <0 on Failure
+ */
+int mei_initiate_locality_check(struct mei_cl_device *cldev,
+ struct mei_hdcp_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 device *dev;
+ ssize_t byte;
+
+ if (!data || !lc_init_data)
+ return -EINVAL;
+
+ dev = &cldev->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 = 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. %d\n", (int)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. %d\n", (int)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 -1;
+ }
+
+ 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);
Check for validity of lc_init_data->r_n.
Also, leave a blank line.
+ return 0;
+}
+EXPORT_SYMBOL(mei_initiate_locality_check);
+
void mei_cldev_state_notify_clients(struct mei_cl_device *cldev, bool enabled) {
if (enabled)
diff --git a/include/linux/mei_hdcp.h b/include/linux/mei_hdcp.h index
be16e49d8018..d9c4cac0b276 100644
--- a/include/linux/mei_hdcp.h
+++ b/include/linux/mei_hdcp.h
@@ -121,6 +121,9 @@ int mei_verify_hprime(struct mei_cl_device *cldev, struct
mei_hdcp_data *data, int mei_store_pairing_info(struct mei_cl_device *cldev,
struct mei_hdcp_data *data,
struct hdcp2_ake_send_pairing_info *pairing_info);
+int mei_initiate_locality_check(struct mei_cl_device *cldev,
+ struct mei_hdcp_data *data,
+ struct hdcp2_lc_init *lc_init_data);
#else
return -ENODEV;
}
+static inline
+int mei_initiate_locality_check(struct mei_cl_device *cldev,
+ struct mei_hdcp_data *data,
+ struct hdcp2_lc_init *lc_init_data) {
+ return -ENODEV;
+}
#endif /* defined (CONFIG_INTEL_MEI_HDCP) */ #endif /* defined
(_LINUX_MEI_HDCP_H) */
--
2.7.4
_______________________________________________
dri-devel mailing list
https://lists.freedesktop.org/mailman/listinfo/dri-devel
Ramalingam C
2018-05-16 16:02:40 UTC
Permalink
Post by Shankar, Uma
-----Original Message-----
Ramalingam C
Sent: Tuesday, April 3, 2018 7:27 PM
Subject: [PATCH v3 12/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.
Rebased.
cldev is passed as first parameter [Tomas]
Redundant comments and cast are removed [Tomas]
---
drivers/misc/mei/hdcp/mei_hdcp.c | 56
++++++++++++++++++++++++++++++++++++++++
include/linux/mei_hdcp.h | 10 +++++++
2 files changed, 66 insertions(+)
diff --git a/drivers/misc/mei/hdcp/mei_hdcp.c
b/drivers/misc/mei/hdcp/mei_hdcp.c
index 60afdd0cee79..9bd7e66a91e4 100644
--- a/drivers/misc/mei/hdcp/mei_hdcp.c
+++ b/drivers/misc/mei/hdcp/mei_hdcp.c
@@ -305,6 +305,62 @@ int mei_store_pairing_info(struct mei_cl_device *cldev,
} EXPORT_SYMBOL(mei_store_pairing_info);
+/**
+ * Function to prepare LC_Init.
+ *
+ *
+ * Returns 0 on Success, <0 on Failure
+ */
+int mei_initiate_locality_check(struct mei_cl_device *cldev,
+ struct mei_hdcp_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 device *dev;
+ ssize_t byte;
+
+ if (!data || !lc_init_data)
+ return -EINVAL;
+
+ dev = &cldev->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 = 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. %d\n", (int)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. %d\n", (int)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 -1;
+ }
+
+ 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);
Check for validity of lc_init_data->r_n.
Also, leave a blank line.
ok

--Ram
Post by Shankar, Uma
+ return 0;
+}
+EXPORT_SYMBOL(mei_initiate_locality_check);
+
void mei_cldev_state_notify_clients(struct mei_cl_device *cldev, bool enabled) {
if (enabled)
diff --git a/include/linux/mei_hdcp.h b/include/linux/mei_hdcp.h index
be16e49d8018..d9c4cac0b276 100644
--- a/include/linux/mei_hdcp.h
+++ b/include/linux/mei_hdcp.h
@@ -121,6 +121,9 @@ int mei_verify_hprime(struct mei_cl_device *cldev, struct
mei_hdcp_data *data, int mei_store_pairing_info(struct mei_cl_device *cldev,
struct mei_hdcp_data *data,
struct hdcp2_ake_send_pairing_info *pairing_info);
+int mei_initiate_locality_check(struct mei_cl_device *cldev,
+ struct mei_hdcp_data *data,
+ struct hdcp2_lc_init *lc_init_data);
#else
return -ENODEV;
}
+static inline
+int mei_initiate_locality_check(struct mei_cl_device *cldev,
+ struct mei_hdcp_data *data,
+ struct hdcp2_lc_init *lc_init_data) {
+ return -ENODEV;
+}
#endif /* defined (CONFIG_INTEL_MEI_HDCP) */ #endif /* defined
(_LINUX_MEI_HDCP_H) */
--
2.7.4
_______________________________________________
dri-devel mailing list
https://lists.freedesktop.org/mailman/listinfo/dri-devel
Ramalingam C
2018-04-03 13:57:32 UTC
Permalink
Considering the upcoming significant no HDCP2.2 variables, it will
be clean to have separate struct fo HDCP.

New structure called intel_hdcp is introduced.

v2:
struct hdcp statically allocated. [Sean Paul]
enable and disable function parameters are retained.[Sean Paul]
v3:
No Changes.

Signed-off-by: Ramalingam C <***@intel.com>
---
drivers/gpu/drm/i915/intel_display.c | 7 +--
drivers/gpu/drm/i915/intel_drv.h | 14 ++++--
drivers/gpu/drm/i915/intel_hdcp.c | 94 ++++++++++++++++++++----------------
3 files changed, 66 insertions(+), 49 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index 331084082545..2d7c47135e1a 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -15395,9 +15395,10 @@ static void intel_hpd_poll_fini(struct drm_device *dev)
for_each_intel_connector_iter(connector, &conn_iter) {
if (connector->modeset_retry_work.func)
cancel_work_sync(&connector->modeset_retry_work);
- if (connector->hdcp_shim) {
- cancel_delayed_work_sync(&connector->hdcp_check_work);
- cancel_work_sync(&connector->hdcp_prop_work);
+ if (connector->hdcp.hdcp_shim) {
+ cancel_delayed_work_sync(
+ &connector->hdcp.hdcp_check_work);
+ cancel_work_sync(&connector->hdcp.hdcp_prop_work);
}
}
drm_connector_list_iter_end(&conn_iter);
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index d4368589b355..fdffcb833cd2 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -377,6 +377,14 @@ struct intel_hdcp_shim {
bool *hdcp_capable);
};

+struct intel_hdcp {
+ const struct intel_hdcp_shim *hdcp_shim;
+ struct mutex hdcp_mutex;
+ uint64_t hdcp_value; /* protected by hdcp_mutex */
+ struct delayed_work hdcp_check_work;
+ struct work_struct hdcp_prop_work;
+};
+
struct intel_connector {
struct drm_connector base;
/*
@@ -409,11 +417,7 @@ struct intel_connector {
/* Work struct to schedule a uevent on link train failure */
struct work_struct modeset_retry_work;

- const struct intel_hdcp_shim *hdcp_shim;
- struct mutex hdcp_mutex;
- uint64_t hdcp_value; /* protected by hdcp_mutex */
- struct delayed_work hdcp_check_work;
- struct work_struct hdcp_prop_work;
+ struct intel_hdcp hdcp;
};

struct intel_digital_connector_state {
diff --git a/drivers/gpu/drm/i915/intel_hdcp.c b/drivers/gpu/drm/i915/intel_hdcp.c
index 14ca5d3057a7..1cca4f349064 100644
--- a/drivers/gpu/drm/i915/intel_hdcp.c
+++ b/drivers/gpu/drm/i915/intel_hdcp.c
@@ -547,6 +547,7 @@ struct intel_digital_port *conn_to_dig_port(struct intel_connector *connector)

static int _intel_hdcp_disable(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;
@@ -562,7 +563,7 @@ static int _intel_hdcp_disable(struct intel_connector *connector)
return -ETIMEDOUT;
}

- ret = connector->hdcp_shim->toggle_signalling(intel_dig_port, false);
+ ret = hdcp->hdcp_shim->toggle_signalling(intel_dig_port, false);
if (ret) {
DRM_ERROR("Failed to disable HDCP signalling\n");
return ret;
@@ -574,6 +575,7 @@ static int _intel_hdcp_disable(struct intel_connector *connector)

static int _intel_hdcp_enable(struct intel_connector *connector)
{
+ struct intel_hdcp *hdcp = &connector->hdcp;
struct drm_i915_private *dev_priv = connector->base.dev->dev_private;
int i, ret, tries = 3;

@@ -599,7 +601,7 @@ 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),
- connector->hdcp_shim);
+ hdcp->hdcp_shim);
if (!ret)
return 0;

@@ -615,36 +617,42 @@ static int _intel_hdcp_enable(struct intel_connector *connector)

static void intel_hdcp_check_work(struct work_struct *work)
{
- struct intel_connector *connector = container_of(to_delayed_work(work),
+ struct intel_hdcp *hdcp = container_of(to_delayed_work(work),
+ struct intel_hdcp,
+ hdcp_check_work);
+ struct intel_connector *connector = container_of(hdcp,
struct intel_connector,
- hdcp_check_work);
+ hdcp);
+
if (!intel_hdcp_check_link(connector))
- schedule_delayed_work(&connector->hdcp_check_work,
+ schedule_delayed_work(&hdcp->hdcp_check_work,
DRM_HDCP_CHECK_PERIOD_MS);
}

static void intel_hdcp_prop_work(struct work_struct *work)
{
- struct intel_connector *connector = container_of(work,
+ struct intel_hdcp *hdcp = container_of(work, struct intel_hdcp,
+ hdcp_prop_work);
+ struct intel_connector *connector = container_of(hdcp,
struct intel_connector,
- hdcp_prop_work);
+ hdcp);
struct drm_device *dev = connector->base.dev;
struct drm_connector_state *state;

drm_modeset_lock(&dev->mode_config.connection_mutex, NULL);
- mutex_lock(&connector->hdcp_mutex);
+ mutex_lock(&hdcp->hdcp_mutex);

/*
* This worker is only used to flip between ENABLED/DESIRED. Either of
* those to UNDESIRED is handled by core. If hdcp_value == UNDESIRED,
* we're running just after hdcp has been disabled, so just exit
*/
- if (connector->hdcp_value != DRM_MODE_CONTENT_PROTECTION_UNDESIRED) {
+ if (hdcp->hdcp_value != DRM_MODE_CONTENT_PROTECTION_UNDESIRED) {
state = connector->base.state;
- state->content_protection = connector->hdcp_value;
+ state->content_protection = hdcp->hdcp_value;
}

- mutex_unlock(&connector->hdcp_mutex);
+ mutex_unlock(&hdcp->hdcp_mutex);
drm_modeset_unlock(&dev->mode_config.connection_mutex);
}

@@ -658,6 +666,7 @@ bool is_hdcp_supported(struct drm_i915_private *dev_priv, enum port port)
int intel_hdcp_init(struct intel_connector *connector,
const struct intel_hdcp_shim *hdcp_shim)
{
+ struct intel_hdcp *hdcp = &connector->hdcp;
int ret;

ret = drm_connector_attach_content_protection_property(
@@ -665,51 +674,53 @@ int intel_hdcp_init(struct intel_connector *connector,
if (ret)
return ret;

- connector->hdcp_shim = hdcp_shim;
- mutex_init(&connector->hdcp_mutex);
- INIT_DELAYED_WORK(&connector->hdcp_check_work, intel_hdcp_check_work);
- INIT_WORK(&connector->hdcp_prop_work, intel_hdcp_prop_work);
+ hdcp->hdcp_shim = hdcp_shim;
+ mutex_init(&hdcp->hdcp_mutex);
+ INIT_DELAYED_WORK(&hdcp->hdcp_check_work, intel_hdcp_check_work);
+ INIT_WORK(&hdcp->hdcp_prop_work, intel_hdcp_prop_work);
return 0;
}

int intel_hdcp_enable(struct intel_connector *connector)
{
+ struct intel_hdcp *hdcp = &connector->hdcp;
int ret;

- if (!connector->hdcp_shim)
+ if (!hdcp->hdcp_shim)
return -ENOENT;

- mutex_lock(&connector->hdcp_mutex);
+ mutex_lock(&hdcp->hdcp_mutex);

ret = _intel_hdcp_enable(connector);
if (ret)
goto out;

- connector->hdcp_value = DRM_MODE_CONTENT_PROTECTION_ENABLED;
- schedule_work(&connector->hdcp_prop_work);
- schedule_delayed_work(&connector->hdcp_check_work,
+ hdcp->hdcp_value = DRM_MODE_CONTENT_PROTECTION_ENABLED;
+ schedule_work(&hdcp->hdcp_prop_work);
+ schedule_delayed_work(&hdcp->hdcp_check_work,
DRM_HDCP_CHECK_PERIOD_MS);
out:
- mutex_unlock(&connector->hdcp_mutex);
+ mutex_unlock(&hdcp->hdcp_mutex);
return ret;
}

int intel_hdcp_disable(struct intel_connector *connector)
{
+ struct intel_hdcp *hdcp = &connector->hdcp;
int ret = 0;

- if (!connector->hdcp_shim)
+ if (!hdcp->hdcp_shim)
return -ENOENT;

- mutex_lock(&connector->hdcp_mutex);
+ mutex_lock(&hdcp->hdcp_mutex);

- if (connector->hdcp_value != DRM_MODE_CONTENT_PROTECTION_UNDESIRED) {
- connector->hdcp_value = DRM_MODE_CONTENT_PROTECTION_UNDESIRED;
+ if (hdcp->hdcp_value != DRM_MODE_CONTENT_PROTECTION_UNDESIRED) {
+ hdcp->hdcp_value = DRM_MODE_CONTENT_PROTECTION_UNDESIRED;
ret = _intel_hdcp_disable(connector);
}

- mutex_unlock(&connector->hdcp_mutex);
- cancel_delayed_work_sync(&connector->hdcp_check_work);
+ mutex_unlock(&hdcp->hdcp_mutex);
+ cancel_delayed_work_sync(&hdcp->hdcp_check_work);
return ret;
}

@@ -749,17 +760,18 @@ void intel_hdcp_atomic_check(struct drm_connector *connector,
/* 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 (!connector->hdcp_shim)
+ if (!hdcp->hdcp_shim)
return -ENOENT;

- mutex_lock(&connector->hdcp_mutex);
+ mutex_lock(&hdcp->hdcp_mutex);

- if (connector->hdcp_value == DRM_MODE_CONTENT_PROTECTION_UNDESIRED)
+ if (hdcp->hdcp_value == DRM_MODE_CONTENT_PROTECTION_UNDESIRED)
goto out;

if (!(I915_READ(PORT_HDCP_STATUS(port)) & HDCP_STATUS_ENC)) {
@@ -767,17 +779,17 @@ int intel_hdcp_check_link(struct intel_connector *connector)
connector->base.name, connector->base.base.id,
I915_READ(PORT_HDCP_STATUS(port)));
ret = -ENXIO;
- connector->hdcp_value = DRM_MODE_CONTENT_PROTECTION_DESIRED;
- schedule_work(&connector->hdcp_prop_work);
+ hdcp->hdcp_value = DRM_MODE_CONTENT_PROTECTION_DESIRED;
+ schedule_work(&hdcp->hdcp_prop_work);
goto out;
}

- if (connector->hdcp_shim->check_link(intel_dig_port)) {
- if (connector->hdcp_value !=
+ if (hdcp->hdcp_shim->check_link(intel_dig_port)) {
+ if (hdcp->hdcp_value !=
DRM_MODE_CONTENT_PROTECTION_UNDESIRED) {
- connector->hdcp_value =
+ hdcp->hdcp_value =
DRM_MODE_CONTENT_PROTECTION_ENABLED;
- schedule_work(&connector->hdcp_prop_work);
+ schedule_work(&hdcp->hdcp_prop_work);
}
goto out;
}
@@ -788,20 +800,20 @@ int intel_hdcp_check_link(struct intel_connector *connector)
ret = _intel_hdcp_disable(connector);
if (ret) {
DRM_ERROR("Failed to disable hdcp (%d)\n", ret);
- connector->hdcp_value = DRM_MODE_CONTENT_PROTECTION_DESIRED;
- schedule_work(&connector->hdcp_prop_work);
+ hdcp->hdcp_value = DRM_MODE_CONTENT_PROTECTION_DESIRED;
+ schedule_work(&hdcp->hdcp_prop_work);
goto out;
}

ret = _intel_hdcp_enable(connector);
if (ret) {
DRM_ERROR("Failed to enable hdcp (%d)\n", ret);
- connector->hdcp_value = DRM_MODE_CONTENT_PROTECTION_DESIRED;
- schedule_work(&connector->hdcp_prop_work);
+ hdcp->hdcp_value = DRM_MODE_CONTENT_PROTECTION_DESIRED;
+ schedule_work(&hdcp->hdcp_prop_work);
goto out;
}

out:
- mutex_unlock(&connector->hdcp_mutex);
+ mutex_unlock(&hdcp->hdcp_mutex);
return ret;
}
--
2.7.4
Shankar, Uma
2018-05-09 14:11:12 UTC
Permalink
-----Original Message-----
Ramalingam C
Sent: Tuesday, April 3, 2018 7:28 PM
Subject: [PATCH v3 19/40] drm/i915: wrapping all hdcp var into intel_hdcp
Considering the upcoming significant no HDCP2.2 variables, it will be clean to
Rephrase this sentence.
have separate struct fo HDCP.
Typo here.
New structure called intel_hdcp is introduced.
struct hdcp statically allocated. [Sean Paul]
enable and disable function parameters are retained.[Sean Paul]
No Changes.
---
drivers/gpu/drm/i915/intel_display.c | 7 +--
drivers/gpu/drm/i915/intel_drv.h | 14 ++++--
drivers/gpu/drm/i915/intel_hdcp.c | 94 ++++++++++++++++++++----------------
3 files changed, 66 insertions(+), 49 deletions(-)
diff --git a/drivers/gpu/drm/i915/intel_display.c
b/drivers/gpu/drm/i915/intel_display.c
index 331084082545..2d7c47135e1a 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -15395,9 +15395,10 @@ static void intel_hpd_poll_fini(struct drm_device *dev)
for_each_intel_connector_iter(connector, &conn_iter) {
if (connector->modeset_retry_work.func)
cancel_work_sync(&connector->modeset_retry_work);
- if (connector->hdcp_shim) {
- cancel_delayed_work_sync(&connector-
Post by Ramalingam C
hdcp_check_work);
- cancel_work_sync(&connector->hdcp_prop_work);
+ if (connector->hdcp.hdcp_shim) {
+ cancel_delayed_work_sync(
+ &connector->hdcp.hdcp_check_work);
+ cancel_work_sync(&connector->hdcp.hdcp_prop_work);
}
}
drm_connector_list_iter_end(&conn_iter);
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index d4368589b355..fdffcb833cd2 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -377,6 +377,14 @@ struct intel_hdcp_shim {
bool *hdcp_capable);
};
+struct intel_hdcp {
+ const struct intel_hdcp_shim *hdcp_shim;
+ struct mutex hdcp_mutex;
+ uint64_t hdcp_value; /* protected by hdcp_mutex */
+ struct delayed_work hdcp_check_work;
+ struct work_struct hdcp_prop_work;
+};
+
struct intel_connector {
struct drm_connector base;
/*
@@ -409,11 +417,7 @@ struct intel_connector {
/* Work struct to schedule a uevent on link train failure */
struct work_struct modeset_retry_work;
- const struct intel_hdcp_shim *hdcp_shim;
- struct mutex hdcp_mutex;
- uint64_t hdcp_value; /* protected by hdcp_mutex */
- struct delayed_work hdcp_check_work;
- struct work_struct hdcp_prop_work;
+ struct intel_hdcp hdcp;
};
struct intel_digital_connector_state {
diff --git a/drivers/gpu/drm/i915/intel_hdcp.c
b/drivers/gpu/drm/i915/intel_hdcp.c
index 14ca5d3057a7..1cca4f349064 100644
--- a/drivers/gpu/drm/i915/intel_hdcp.c
+++ b/drivers/gpu/drm/i915/intel_hdcp.c
@@ -547,6 +547,7 @@ struct intel_digital_port *conn_to_dig_port(struct
intel_connector *connector)
static int _intel_hdcp_disable(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);
static int _intel_hdcp_disable(struct intel_connector *connector)
return -ETIMEDOUT;
}
- ret = connector->hdcp_shim->toggle_signalling(intel_dig_port, false);
+ ret = hdcp->hdcp_shim->toggle_signalling(intel_dig_port, false);
if (ret) {
DRM_ERROR("Failed to disable HDCP signalling\n");
return ret;
@@ -574,6 +575,7 @@ static int _intel_hdcp_disable(struct intel_connector *connector)
static int _intel_hdcp_enable(struct intel_connector *connector) {
+ struct intel_hdcp *hdcp = &connector->hdcp;
struct drm_i915_private *dev_priv = connector->base.dev->dev_private;
int i, ret, tries = 3;
@@ -599,7 +601,7 @@ 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),
- connector->hdcp_shim);
+ hdcp->hdcp_shim);
if (!ret)
return 0;
@@ -615,36 +617,42 @@ static int _intel_hdcp_enable(struct intel_connector *connector)
static void intel_hdcp_check_work(struct work_struct *work) {
- struct intel_connector *connector =
container_of(to_delayed_work(work),
+ struct intel_hdcp *hdcp = container_of(to_delayed_work(work),
+ struct intel_hdcp,
+ hdcp_check_work);
+ struct intel_connector *connector = container_of(hdcp,
struct intel_connector,
- hdcp_check_work);
+ hdcp);
+
if (!intel_hdcp_check_link(connector))
- schedule_delayed_work(&connector->hdcp_check_work,
+ schedule_delayed_work(&hdcp->hdcp_check_work,
DRM_HDCP_CHECK_PERIOD_MS);
}
static void intel_hdcp_prop_work(struct work_struct *work) {
- struct intel_connector *connector = container_of(work,
+ struct intel_hdcp *hdcp = container_of(work, struct intel_hdcp,
+ hdcp_prop_work);
+ struct intel_connector *connector = container_of(hdcp,
struct intel_connector,
- hdcp_prop_work);
+ hdcp);
struct drm_device *dev = connector->base.dev;
struct drm_connector_state *state;
drm_modeset_lock(&dev->mode_config.connection_mutex, NULL);
- mutex_lock(&connector->hdcp_mutex);
+ mutex_lock(&hdcp->hdcp_mutex);
/*
* This worker is only used to flip between ENABLED/DESIRED. Either of
* those to UNDESIRED is handled by core. If hdcp_value == UNDESIRED,
* we're running just after hdcp has been disabled, so just exit
*/
- if (connector->hdcp_value !=
DRM_MODE_CONTENT_PROTECTION_UNDESIRED) {
+ if (hdcp->hdcp_value !=
DRM_MODE_CONTENT_PROTECTION_UNDESIRED) {
state = connector->base.state;
- state->content_protection = connector->hdcp_value;
+ state->content_protection = hdcp->hdcp_value;
}
- mutex_unlock(&connector->hdcp_mutex);
+ mutex_unlock(&hdcp->hdcp_mutex);
drm_modeset_unlock(&dev->mode_config.connection_mutex);
}
@@ -658,6 +666,7 @@ bool is_hdcp_supported(struct drm_i915_private
*dev_priv, enum port port) int intel_hdcp_init(struct intel_connector *connector,
const struct intel_hdcp_shim *hdcp_shim) {
+ struct intel_hdcp *hdcp = &connector->hdcp;
int ret;
ret = drm_connector_attach_content_protection_property(
@@ -665,51 +674,53 @@ int intel_hdcp_init(struct intel_connector *connector,
if (ret)
return ret;
- connector->hdcp_shim = hdcp_shim;
- mutex_init(&connector->hdcp_mutex);
- INIT_DELAYED_WORK(&connector->hdcp_check_work,
intel_hdcp_check_work);
- INIT_WORK(&connector->hdcp_prop_work, intel_hdcp_prop_work);
+ hdcp->hdcp_shim = hdcp_shim;
+ mutex_init(&hdcp->hdcp_mutex);
+ INIT_DELAYED_WORK(&hdcp->hdcp_check_work,
intel_hdcp_check_work);
+ INIT_WORK(&hdcp->hdcp_prop_work, intel_hdcp_prop_work);
return 0;
}
int intel_hdcp_enable(struct intel_connector *connector) {
+ struct intel_hdcp *hdcp = &connector->hdcp;
int ret;
- if (!connector->hdcp_shim)
+ if (!hdcp->hdcp_shim)
return -ENOENT;
- mutex_lock(&connector->hdcp_mutex);
+ mutex_lock(&hdcp->hdcp_mutex);
ret = _intel_hdcp_enable(connector);
if (ret)
goto out;
- connector->hdcp_value =
DRM_MODE_CONTENT_PROTECTION_ENABLED;
- schedule_work(&connector->hdcp_prop_work);
- schedule_delayed_work(&connector->hdcp_check_work,
+ hdcp->hdcp_value = DRM_MODE_CONTENT_PROTECTION_ENABLED;
+ schedule_work(&hdcp->hdcp_prop_work);
+ schedule_delayed_work(&hdcp->hdcp_check_work,
DRM_HDCP_CHECK_PERIOD_MS);
- mutex_unlock(&connector->hdcp_mutex);
+ mutex_unlock(&hdcp->hdcp_mutex);
return ret;
}
int intel_hdcp_disable(struct intel_connector *connector) {
+ struct intel_hdcp *hdcp = &connector->hdcp;
int ret = 0;
- if (!connector->hdcp_shim)
+ if (!hdcp->hdcp_shim)
return -ENOENT;
- mutex_lock(&connector->hdcp_mutex);
+ mutex_lock(&hdcp->hdcp_mutex);
- if (connector->hdcp_value !=
DRM_MODE_CONTENT_PROTECTION_UNDESIRED) {
- connector->hdcp_value =
DRM_MODE_CONTENT_PROTECTION_UNDESIRED;
+ if (hdcp->hdcp_value !=
DRM_MODE_CONTENT_PROTECTION_UNDESIRED) {
+ hdcp->hdcp_value =
DRM_MODE_CONTENT_PROTECTION_UNDESIRED;
ret = _intel_hdcp_disable(connector);
}
- mutex_unlock(&connector->hdcp_mutex);
- cancel_delayed_work_sync(&connector->hdcp_check_work);
+ mutex_unlock(&hdcp->hdcp_mutex);
+ cancel_delayed_work_sync(&hdcp->hdcp_check_work);
return ret;
}
@@ -749,17 +760,18 @@ void intel_hdcp_atomic_check(struct drm_connector *connector,
/* 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 (!connector->hdcp_shim)
+ if (!hdcp->hdcp_shim)
return -ENOENT;
- mutex_lock(&connector->hdcp_mutex);
+ mutex_lock(&hdcp->hdcp_mutex);
- if (connector->hdcp_value ==
DRM_MODE_CONTENT_PROTECTION_UNDESIRED)
+ if (hdcp->hdcp_value ==
DRM_MODE_CONTENT_PROTECTION_UNDESIRED)
goto out;
if (!(I915_READ(PORT_HDCP_STATUS(port)) & HDCP_STATUS_ENC)) {
@@ -767,17 +779,17 @@ int intel_hdcp_check_link(struct intel_connector *connector)
connector->base.name, connector->base.base.id,
I915_READ(PORT_HDCP_STATUS(port)));
ret = -ENXIO;
- connector->hdcp_value =
DRM_MODE_CONTENT_PROTECTION_DESIRED;
- schedule_work(&connector->hdcp_prop_work);
+ hdcp->hdcp_value =
DRM_MODE_CONTENT_PROTECTION_DESIRED;
+ schedule_work(&hdcp->hdcp_prop_work);
goto out;
}
- if (connector->hdcp_shim->check_link(intel_dig_port)) {
- if (connector->hdcp_value !=
+ if (hdcp->hdcp_shim->check_link(intel_dig_port)) {
+ if (hdcp->hdcp_value !=
DRM_MODE_CONTENT_PROTECTION_UNDESIRED) {
- connector->hdcp_value =
+ hdcp->hdcp_value =
DRM_MODE_CONTENT_PROTECTION_ENABLED;
- schedule_work(&connector->hdcp_prop_work);
+ schedule_work(&hdcp->hdcp_prop_work);
}
goto out;
}
@@ -788,20 +800,20 @@ int intel_hdcp_check_link(struct intel_connector *connector)
ret = _intel_hdcp_disable(connector);
if (ret) {
DRM_ERROR("Failed to disable hdcp (%d)\n", ret);
- connector->hdcp_value =
DRM_MODE_CONTENT_PROTECTION_DESIRED;
- schedule_work(&connector->hdcp_prop_work);
+ hdcp->hdcp_value =
DRM_MODE_CONTENT_PROTECTION_DESIRED;
+ schedule_work(&hdcp->hdcp_prop_work);
goto out;
}
ret = _intel_hdcp_enable(connector);
if (ret) {
DRM_ERROR("Failed to enable hdcp (%d)\n", ret);
- connector->hdcp_value =
DRM_MODE_CONTENT_PROTECTION_DESIRED;
- schedule_work(&connector->hdcp_prop_work);
+ hdcp->hdcp_value =
DRM_MODE_CONTENT_PROTECTION_DESIRED;
+ schedule_work(&hdcp->hdcp_prop_work);
goto out;
}
- mutex_unlock(&connector->hdcp_mutex);
+ mutex_unlock(&hdcp->hdcp_mutex);
return ret;
}
--
2.7.4
_______________________________________________
dri-devel mailing list
https://lists.freedesktop.org/mailman/listinfo/dri-devel
Ramalingam C
2018-04-03 13:57:33 UTC
Permalink
For upcoming implementation of HDCP2.2 in I915, important variable
required for HDCP2.2 are defined.

HDCP_shim is extended to support encoder specific HDCP2.2 flows.

v2:
1.4 shim is extended to support hdcp2.2. [Sean Paul]
platform's/panel's hdcp ver capability is removed. [Sean Paul]
mei references in i915_private are moved to later patches. [Chris Wilson]
v3:
mei_cl_device ref is moved into intel_hdcp

Signed-off-by: Ramalingam C <***@intel.com>
---
drivers/gpu/drm/i915/intel_drv.h | 61 ++++++++++++++++++++++++++++++++++++++++
1 file changed, 61 insertions(+)

diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index fdffcb833cd2..ca06d9a158f6 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -29,6 +29,7 @@
#include <linux/i2c.h>
#include <linux/hdmi.h>
#include <linux/sched/clock.h>
+#include <linux/mei_hdcp.h>
#include <drm/i915_drm.h>
#include "i915_drv.h"
#include <drm/drm_crtc.h>
@@ -375,6 +376,32 @@ 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);
+
+ /* 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,
+ uint8_t 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 Chiper for En/De-Cryption. Not applicable for HDMI.
+ */
+ int (*config_stream_type)(struct intel_digital_port *intel_dig_port,
+ void *buf, size_t size);
+
+ /* HDCP2.2 Link Integrity Check */
+ int (*check_2_2_link)(struct intel_digital_port *intel_dig_port);
+
+ /* Detects whether Panel is HDCP2.2 capable */
+ int (*hdcp_2_2_capable)(struct intel_digital_port *intel_dig_port,
+ bool *capable);
+
+ /* Detects the HDCP protocol(DP/HDMI) required on the port */
+ enum hdcp_protocol (*hdcp_protocol)(void);
};

struct intel_hdcp {
@@ -383,6 +410,40 @@ struct intel_hdcp {
uint64_t hdcp_value; /* protected by hdcp_mutex */
struct delayed_work hdcp_check_work;
struct work_struct hdcp_prop_work;
+
+ /** HDCP2.2 related definitions **/
+ 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;
+
+ 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.
+ */
+ uint32_t 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.
+ */
+ uint32_t seq_num_m;
+
+ /* mei interface related information */
+ struct mei_cl_device *cldev;
+ struct mei_hdcp_data mei_data;
+
+ struct delayed_work hdcp2_check_work;
};

struct intel_connector {
--
2.7.4
kbuild test robot
2018-04-03 20:27:56 UTC
Permalink
Hi Ramalingam,

Thank you for the patch! Yet something to improve:

[auto build test ERROR on drm-intel/for-linux-next]
[also build test ERROR on next-20180403]
[cannot apply to v4.16]
[if your patch is applied to the wrong git tree, please drop us a note to help improve the system]

url: https://github.com/0day-ci/linux/commits/Ramalingam-C/drm-i915-Implement-HDCP2-2/20180404-031743
base: git://anongit.freedesktop.org/drm-intel for-linux-next
config: x86_64-randconfig-x001-201813 (attached as .config)
compiler: gcc-7 (Debian 7.3.0-1) 7.3.0
reproduce:
# save the attached .config to linux build tree
make ARCH=x86_64

All errors (new ones prefixed by >>):

In file included from drivers/gpu//drm/i915/intel_drv.h:32:0,
from drivers/gpu//drm/i915/i915_trace.h:11,
from drivers/gpu//drm/i915/i915_drv.h:2919,
include/linux/mei_hdcp.h:148:12: error: 'mei_cldev_unregister_notify' defined but not used [-Werror=unused-function]
static int mei_cldev_unregister_notify(struct notifier_block *nb)
^~~~~~~~~~~~~~~~~~~~~~~~~~~
include/linux/mei_hdcp.h:144:12: error: 'mei_cldev_register_notify' defined but not used [-Werror=unused-function]
static int mei_cldev_register_notify(struct notifier_block *nb)
^~~~~~~~~~~~~~~~~~~~~~~~~
cc1: all warnings being treated as errors

vim +/mei_cldev_unregister_notify +148 include/linux/mei_hdcp.h

3ce9e24eb Ramalingam C 2018-04-03 105
ca998fc38 Ramalingam C 2018-04-03 106 #ifdef CONFIG_INTEL_MEI_HDCP
ca998fc38 Ramalingam C 2018-04-03 107 int mei_cldev_register_notify(struct notifier_block *nb);
ca998fc38 Ramalingam C 2018-04-03 108 int mei_cldev_unregister_notify(struct notifier_block *nb);
5240fee41 Ramalingam C 2018-04-03 109 int mei_initiate_hdcp2_session(struct mei_cl_device *cldev,
5240fee41 Ramalingam C 2018-04-03 110 struct mei_hdcp_data *data,
5240fee41 Ramalingam C 2018-04-03 111 struct hdcp2_ake_init *ake_data);
e33886f53 Ramalingam C 2018-04-03 112 int
e33886f53 Ramalingam C 2018-04-03 113 mei_verify_receiver_cert_prepare_km(struct mei_cl_device *cldev,
e33886f53 Ramalingam C 2018-04-03 114 struct mei_hdcp_data *data,
e33886f53 Ramalingam C 2018-04-03 115 struct hdcp2_ake_send_cert *rx_cert,
e33886f53 Ramalingam C 2018-04-03 116 bool *km_stored,
e33886f53 Ramalingam C 2018-04-03 117 struct hdcp2_ake_no_stored_km *ek_pub_km,
e33886f53 Ramalingam C 2018-04-03 118 size_t *msg_sz);
a27b68fb5 Ramalingam C 2018-04-03 119 int mei_verify_hprime(struct mei_cl_device *cldev, struct mei_hdcp_data *data,
a27b68fb5 Ramalingam C 2018-04-03 120 struct hdcp2_ake_send_hprime *rx_hprime);
dc86bde43 Ramalingam C 2018-04-03 121 int mei_store_pairing_info(struct mei_cl_device *cldev,
dc86bde43 Ramalingam C 2018-04-03 122 struct mei_hdcp_data *data,
dc86bde43 Ramalingam C 2018-04-03 123 struct hdcp2_ake_send_pairing_info *pairing_info);
67158470b Ramalingam C 2018-04-03 124 int mei_initiate_locality_check(struct mei_cl_device *cldev,
67158470b Ramalingam C 2018-04-03 125 struct mei_hdcp_data *data,
67158470b Ramalingam C 2018-04-03 126 struct hdcp2_lc_init *lc_init_data);
b10099c9a Ramalingam C 2018-04-03 127 int mei_verify_lprime(struct mei_cl_device *cldev, struct mei_hdcp_data *data,
b10099c9a Ramalingam C 2018-04-03 128 struct hdcp2_lc_send_lprime *rx_lprime);
931c35709 Ramalingam C 2018-04-03 129 int mei_get_session_key(struct mei_cl_device *cldev, struct mei_hdcp_data *data,
931c35709 Ramalingam C 2018-04-03 130 struct hdcp2_ske_send_eks *ske_data);
654828e8b Ramalingam C 2018-04-03 131 int
654828e8b Ramalingam C 2018-04-03 132 mei_repeater_check_flow_prepare_ack(struct mei_cl_device *cldev,
654828e8b Ramalingam C 2018-04-03 133 struct mei_hdcp_data *data,
654828e8b Ramalingam C 2018-04-03 134 struct hdcp2_rep_send_receiverid_list
654828e8b Ramalingam C 2018-04-03 135 *rep_topology,
654828e8b Ramalingam C 2018-04-03 136 struct hdcp2_rep_send_ack *rep_send_ack);
315c37225 Ramalingam C 2018-04-03 137 int mei_verify_mprime(struct mei_cl_device *cldev, struct mei_hdcp_data *data,
315c37225 Ramalingam C 2018-04-03 138 struct hdcp2_rep_stream_ready *stream_ready);
702a0ad13 Ramalingam C 2018-04-03 139 int mei_enable_hdcp_authentication(struct mei_cl_device *cldev,
702a0ad13 Ramalingam C 2018-04-03 140 struct mei_hdcp_data *data);
015031e8d Ramalingam C 2018-04-03 141 int mei_close_hdcp_session(struct mei_cl_device *cldev,
015031e8d Ramalingam C 2018-04-03 142 struct mei_hdcp_data *data);
ca998fc38 Ramalingam C 2018-04-03 143 #else
ca998fc38 Ramalingam C 2018-04-03 @144 static int mei_cldev_register_notify(struct notifier_block *nb)
ca998fc38 Ramalingam C 2018-04-03 145 {
ca998fc38 Ramalingam C 2018-04-03 146 return -ENODEV;
ca998fc38 Ramalingam C 2018-04-03 147 }
ca998fc38 Ramalingam C 2018-04-03 @148 static int mei_cldev_unregister_notify(struct notifier_block *nb)

:::::: The code at line 148 was first introduced by commit
:::::: ca998fc3888ec55e0039c23b61cbe2057cc5d7a9 misc/mei/hdcp: Notifier chain for mei cldev state change

:::::: TO: Ramalingam C <***@intel.com>
:::::: CC: 0day robot <***@intel.com>

---
0-DAY kernel test infrastructure Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all Intel Corporation
Shankar, Uma
2018-05-09 14:23:37 UTC
Permalink
-----Original Message-----
Ramalingam C
Sent: Tuesday, April 3, 2018 7:28 PM
Subject: [PATCH v3 20/40] drm/i915: Define HDCP2.2 related variables
For upcoming implementation of HDCP2.2 in I915, important variable required for
HDCP2.2 are defined.
HDCP_shim is extended to support encoder specific HDCP2.2 flows.
1.4 shim is extended to support hdcp2.2. [Sean Paul]
platform's/panel's hdcp ver capability is removed. [Sean Paul]
mei references in i915_private are moved to later patches. [Chris Wilson]
mei_cl_device ref is moved into intel_hdcp
---
drivers/gpu/drm/i915/intel_drv.h | 61
++++++++++++++++++++++++++++++++++++++++
1 file changed, 61 insertions(+)
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index fdffcb833cd2..ca06d9a158f6 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -29,6 +29,7 @@
#include <linux/i2c.h>
#include <linux/hdmi.h>
#include <linux/sched/clock.h>
+#include <linux/mei_hdcp.h>
#include <drm/i915_drm.h>
#include "i915_drv.h"
#include <drm/drm_crtc.h>
@@ -375,6 +376,32 @@ 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);
+
+ /* 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,
+ uint8_t 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 Chiper for En/De-Cryption. Not applicable for HDMI.
+ */
+ int (*config_stream_type)(struct intel_digital_port *intel_dig_port,
+ void *buf, size_t size);
+
+ /* HDCP2.2 Link Integrity Check */
+ int (*check_2_2_link)(struct intel_digital_port *intel_dig_port);
+
+ /* Detects whether Panel is HDCP2.2 capable */
+ int (*hdcp_2_2_capable)(struct intel_digital_port *intel_dig_port,
+ bool *capable);
+
+ /* Detects the HDCP protocol(DP/HDMI) required on the port */
+ enum hdcp_protocol (*hdcp_protocol)(void);
};
struct intel_hdcp {
@@ -383,6 +410,40 @@ struct intel_hdcp {
uint64_t hdcp_value; /* protected by hdcp_mutex */
struct delayed_work hdcp_check_work;
struct work_struct hdcp_prop_work;
+
+ /** HDCP2.2 related definitions **/
Drop extra *.
+ 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;
+
+ 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.
+ */
+ uint32_t 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.
+ */
+ uint32_t seq_num_m;
+
+ /* mei interface related information */
+ struct mei_cl_device *cldev;
+ struct mei_hdcp_data mei_data;
+
+ struct delayed_work hdcp2_check_work;
};
struct intel_connector {
--
2.7.4
_______________________________________________
dri-devel mailing list
https://lists.freedesktop.org/mailman/listinfo/dri-devel
Ramalingam C
2018-04-03 13:57:36 UTC
Permalink
Implements HDCP2.2 authentication for hdcp2.2 receivers, with
following steps:
Authentication and Key enchange (AKE).
Locality Check (LC).
Session Key Exchange(SKE).
DP Errata for stream type confuguration 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_shim
defined.

v2:
Rebased.
v3:
No Changes.

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

diff --git a/drivers/gpu/drm/i915/intel_hdcp.c b/drivers/gpu/drm/i915/intel_hdcp.c
index b4d56b21cf9b..ee9b7519fe73 100644
--- a/drivers/gpu/drm/i915/intel_hdcp.c
+++ b/drivers/gpu/drm/i915/intel_hdcp.c
@@ -18,6 +18,7 @@
#define GET_MEI_DDI_INDEX(port) (((port) == PORT_A) ? DDI_A : \
(enum hdcp_physical_port) (port))
#define KEY_LOAD_TRIES 5
+#define HDCP2_LC_RETRY_CNT 3

static int intel_hdcp_poll_ksv_fifo(struct intel_digital_port *intel_dig_port,
const struct intel_hdcp_shim *shim)
@@ -1011,3 +1012,186 @@ static inline int hdcp2_deauthenticate_port(struct intel_hdcp *hdcp)
{
return hdcp2_close_mei_session(hdcp);
}
+
+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->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(hdcp, &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(hdcp, &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(hdcp, &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_PARING_INFO,
+ &msgs.pairing_info,
+ sizeof(msgs.pairing_info));
+ if (ret < 0)
+ return ret;
+
+ ret = hdcp2_store_paring_info(hdcp, &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->hdcp_shim;
+ int tries = HDCP2_LC_RETRY_CNT, ret, i;
+
+ for (i = 0; i < tries; i++) {
+ ret = hdcp2_prepare_lc_init(hdcp, &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(hdcp, &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(hdcp, &send_eks);
+ if (ret < 0)
+ return ret;
+
+ ret = hdcp->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)
+{
+ 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->hdcp_shim;
+ struct hdcp2_dp_errata_stream_type stream_type_msg;
+ int ret;
+
+ ret = hdcp2_authentication_key_exchange(connector);
+ if (ret < 0) {
+ DRM_DEBUG_KMS("AKE Failed. Err : %d\n", ret);
+ return ret;
+ }
+
+ ret = hdcp2_locality_check(connector);
+ if (ret < 0) {
+ DRM_DEBUG_KMS("Locality Check failed. Err : %d\n", ret);
+ return ret;
+ }
+
+ ret = hdcp2_session_key_exchange(connector);
+ if (ret < 0) {
+ DRM_DEBUG_KMS("SKE Failed. Err : %d\n", ret);
+ return ret;
+ }
+
+ if (!hdcp->is_repeater && shim->config_stream_type) {
+
+ /* Errata for DP: As Stream type is used for encryption,
+ * Receiver should be communicated with stream type for the
+ * decryption of the content.
+ * Repeater will be communicated with stream type as a
+ * part of it's auth in later in time
+ */
+ stream_type_msg.msg_id = HDCP_2_2_ERRATA_DP_STREAM_TYPE;
+ stream_type_msg.stream_type = hdcp->content_type;
+
+ ret = shim->config_stream_type(intel_dig_port, &stream_type_msg,
+ sizeof(stream_type_msg));
+ if (ret < 0)
+ return ret;
+ }
+
+ hdcp->mei_data.streams[0].stream_type = hdcp->content_type;
+ ret = hdcp2_authenticate_port(hdcp);
+ if (ret < 0)
+ return ret;
+
+ return ret;
+}
--
2.7.4
Shankar, Uma
2018-05-09 15:20:36 UTC
Permalink
-----Original Message-----
Ramalingam C
Sent: Tuesday, April 3, 2018 7:28 PM
Subject: [Intel-gfx] [PATCH v3 23/40] drm/i915: Implement HDCP2.2 receiver
authentication
Authentication and Key enchange (AKE).
Typo in exchange.
Locality Check (LC).
Session Key Exchange(SKE).
DP Errata for stream type confuguration for receivers.
Typo in configuration.
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_shim defined.
Rebased.
No Changes.
---
drivers/gpu/drm/i915/intel_hdcp.c | 184
++++++++++++++++++++++++++++++++++++++
1 file changed, 184 insertions(+)
diff --git a/drivers/gpu/drm/i915/intel_hdcp.c
b/drivers/gpu/drm/i915/intel_hdcp.c
index b4d56b21cf9b..ee9b7519fe73 100644
--- a/drivers/gpu/drm/i915/intel_hdcp.c
+++ b/drivers/gpu/drm/i915/intel_hdcp.c
@@ -18,6 +18,7 @@
#define GET_MEI_DDI_INDEX(port) (((port) == PORT_A) ? DDI_A : \
(enum hdcp_physical_port) (port))
#define KEY_LOAD_TRIES 5
+#define HDCP2_LC_RETRY_CNT 3
static int intel_hdcp_poll_ksv_fifo(struct intel_digital_port *intel_dig_port,
intel_hdcp *hdcp) {
return hdcp2_close_mei_session(hdcp);
}
+
+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->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(hdcp, &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(hdcp, &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(hdcp, &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_PARING_INFO,
+ &msgs.pairing_info,
+ sizeof(msgs.pairing_info));
+ if (ret < 0)
+ return ret;
+
+ ret = hdcp2_store_paring_info(hdcp, &msgs.pairing_info);
+ if (ret < 0)
+ return ret;
+ hdcp->is_paired = true;
+ }
Leave a blank line here.
+ 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->hdcp_shim;
+ int tries = HDCP2_LC_RETRY_CNT, ret, i;
+
+ for (i = 0; i < tries; i++) {
+ ret = hdcp2_prepare_lc_init(hdcp, &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(hdcp, &msgs.send_lprime);
+ if (!ret)
+ break;
+ }
Leave a blank line.
+ 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(hdcp, &send_eks);
+ if (ret < 0)
+ return ret;
+
+ ret = hdcp->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) {
+ 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->hdcp_shim;
+ struct hdcp2_dp_errata_stream_type stream_type_msg;
+ int ret;
+
+ ret = hdcp2_authentication_key_exchange(connector);
+ if (ret < 0) {
+ DRM_DEBUG_KMS("AKE Failed. Err : %d\n", ret);
+ return ret;
+ }
+
+ ret = hdcp2_locality_check(connector);
+ if (ret < 0) {
+ DRM_DEBUG_KMS("Locality Check failed. Err : %d\n", ret);
+ return ret;
+ }
+
+ ret = hdcp2_session_key_exchange(connector);
+ if (ret < 0) {
+ DRM_DEBUG_KMS("SKE Failed. Err : %d\n", ret);
+ return ret;
+ }
+
+ if (!hdcp->is_repeater && shim->config_stream_type) {
+
+ /* Errata for DP: As Stream type is used for encryption,
Incorrect multi line comment style.
+ * 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 in later in time
Remove "in"
+ */
+ stream_type_msg.msg_id =
HDCP_2_2_ERRATA_DP_STREAM_TYPE;
+ stream_type_msg.stream_type = hdcp->content_type;
+
+ ret = shim->config_stream_type(intel_dig_port,
&stream_type_msg,
+ sizeof(stream_type_msg));
+ if (ret < 0)
+ return ret;
+ }
+
+ hdcp->mei_data.streams[0].stream_type = hdcp->content_type;
+ ret = hdcp2_authenticate_port(hdcp);
+ if (ret < 0)
+ return ret;
+
+ return ret;
+}
--
2.7.4
_______________________________________________
Intel-gfx mailing list
https://lists.freedesktop.org/mailman/listinfo/intel-gfx
Ramalingam C
2018-04-03 13:57:37 UTC
Permalink
Implements the HDCP2.2 repeaters authentication steps such as verifying
the downstream topology and sending stream management information.

v2:
Rebased.
v3:
No Changes.

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

diff --git a/drivers/gpu/drm/i915/intel_hdcp.c b/drivers/gpu/drm/i915/intel_hdcp.c
index ee9b7519fe73..d70320da85e4 100644
--- a/drivers/gpu/drm/i915/intel_hdcp.c
+++ b/drivers/gpu/drm/i915/intel_hdcp.c
@@ -1145,6 +1145,135 @@ static int hdcp2_session_key_exchange(struct intel_connector *connector)
return 0;
}

+/*
+ * Lib endianness functions are aligned for 16/32/64 bits. Since here sequence
+ * num is 24bits developed a small conversion function.
+ */
+static inline void reverse_endianness(u8 *dest, size_t dst_sz, u8 *src)
+{
+ u32 index;
+
+ if (dest != NULL && dst_sz != 0) {
+ for (index = 0; index < dst_sz && index < sizeof(u32);
+ index++) {
+ dest[dst_sz - index - 1] = src[index];
+ }
+ }
+}
+
+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->hdcp_shim;
+ int ret;
+
+ /* Prepare RepeaterAuth_Stream_Manage msg */
+ msgs.stream_manage.msg_id = HDCP_2_2_REP_STREAM_MANAGE;
+ reverse_endianness(msgs.stream_manage.seq_num_m, HDCP_2_2_SEQ_NUM_LEN,
+ (u8 *)&hdcp->seq_num_m);
+
+ /* K no of streams is fixed as 1. Stored as big-endian. */
+ msgs.stream_manage.k = __swab16(1);
+
+ /* For HDMI this is forced to be 0x0. For DP SST also this is 0x0. */
+ msgs.stream_manage.streams[0].stream_id = 0;
+ msgs.stream_manage.streams[0].stream_type = hdcp->content_type;
+
+ /* Send it to Repeater */
+ ret = shim->write_2_2_msg(intel_dig_port, &msgs.stream_manage,
+ sizeof(msgs.stream_manage));
+ if (ret < 0)
+ return ret;
+
+ ret = shim->read_2_2_msg(intel_dig_port, HDCP_2_2_REP_STREAM_READY,
+ &msgs.stream_ready, sizeof(msgs.stream_ready));
+ if (ret < 0)
+ return ret;
+
+ hdcp->mei_data.seq_num_m = hdcp->seq_num_m;
+ hdcp->mei_data.streams[0].stream_type = hdcp->content_type;
+
+ ret = hdcp2_verify_mprime(hdcp, &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->hdcp_shim;
+ uint8_t *rx_info;
+ uint32_t 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 -1;
+ }
+
+ /* Converting and Storing the seq_num_v to local variable as DWORD */
+ reverse_endianness((u8 *)&seq_num_v, HDCP_2_2_SEQ_NUM_LEN,
+ 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 -1;
+ }
+
+ ret = hdcp2_verify_rep_topology_prepare_ack(hdcp, &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);
@@ -1186,6 +1315,12 @@ static int hdcp2_authenticate_sink(struct intel_connector *connector)
sizeof(stream_type_msg));
if (ret < 0)
return ret;
+ } else if (hdcp->is_repeater) {
+ ret = hdcp2_authenticate_repeater(connector);
+ if (ret < 0) {
+ DRM_DEBUG_KMS("Repeater Auth Failed. Err: %d\n", ret);
+ return ret;
+ }
}

hdcp->mei_data.streams[0].stream_type = hdcp->content_type;
--
2.7.4
kbuild test robot
2018-04-04 01:11:37 UTC
Permalink
Hi Ramalingam,

Thank you for the patch! Perhaps something to improve:

[auto build test WARNING on drm-intel/for-linux-next]
[also build test WARNING on next-20180403]
[cannot apply to v4.16]
[if your patch is applied to the wrong git tree, please drop us a note to help improve the system]

url: https://github.com/0day-ci/linux/commits/Ramalingam-C/drm-i915-Implement-HDCP2-2/20180404-031743
base: git://anongit.freedesktop.org/drm-intel for-linux-next
reproduce:
# apt-get install sparse
make ARCH=x86_64 allmodconfig
make C=1 CF=-D__CHECK_ENDIAN__


sparse warnings: (new ones prefixed by >>)
drivers/gpu/drm/i915/intel_hdcp.c:1182:30: expected restricted __be16 [assigned] [usertype] k
drivers/gpu/drm/i915/intel_hdcp.c:1182:30: got int
drivers/gpu/drm/i915/intel_hdcp.c:1277:12: warning: 'hdcp2_authenticate_sink' defined but not used [-Wunused-function]
static int hdcp2_authenticate_sink(struct intel_connector *connector)
^~~~~~~~~~~~~~~~~~~~~~~
In file included from drivers/gpu/drm/i915/intel_hdcp.c:13:0:
include/linux/mei_hdcp.h:148:12: warning: 'mei_cldev_unregister_notify' defined but not used [-Wunused-function]
static int mei_cldev_unregister_notify(struct notifier_block *nb)
^~~~~~~~~~~~~~~~~~~~~~~~~~~
include/linux/mei_hdcp.h:144:12: warning: 'mei_cldev_register_notify' defined but not used [-Wunused-function]
static int mei_cldev_register_notify(struct notifier_block *nb)
^~~~~~~~~~~~~~~~~~~~~~~~~

vim +1182 drivers/gpu/drm/i915/intel_hdcp.c

1163
1164 static
1165 int hdcp2_propagate_stream_management_info(struct intel_connector *connector)
1166 {
1167 struct intel_digital_port *intel_dig_port = conn_to_dig_port(connector);
1168 struct intel_hdcp *hdcp = &connector->hdcp;
1169 union {
1170 struct hdcp2_rep_stream_manage stream_manage;
1171 struct hdcp2_rep_stream_ready stream_ready;
1172 } msgs;
1173 const struct intel_hdcp_shim *shim = hdcp->hdcp_shim;
1174 int ret;
1175
1176 /* Prepare RepeaterAuth_Stream_Manage msg */
1177 msgs.stream_manage.msg_id = HDCP_2_2_REP_STREAM_MANAGE;
1178 reverse_endianness(msgs.stream_manage.seq_num_m, HDCP_2_2_SEQ_NUM_LEN,
1179 (u8 *)&hdcp->seq_num_m);
1180
1181 /* K no of streams is fixed as 1. Stored as big-endian. */
1182 msgs.stream_manage.k = __swab16(1);
1183
1184 /* For HDMI this is forced to be 0x0. For DP SST also this is 0x0. */
1185 msgs.stream_manage.streams[0].stream_id = 0;
1186 msgs.stream_manage.streams[0].stream_type = hdcp->content_type;
1187
1188 /* Send it to Repeater */
1189 ret = shim->write_2_2_msg(intel_dig_port, &msgs.stream_manage,
1190 sizeof(msgs.stream_manage));
1191 if (ret < 0)
1192 return ret;
1193
1194 ret = shim->read_2_2_msg(intel_dig_port, HDCP_2_2_REP_STREAM_READY,
1195 &msgs.stream_ready, sizeof(msgs.stream_ready));
1196 if (ret < 0)
1197 return ret;
1198
1199 hdcp->mei_data.seq_num_m = hdcp->seq_num_m;
1200 hdcp->mei_data.streams[0].stream_type = hdcp->content_type;
1201
1202 ret = hdcp2_verify_mprime(hdcp, &msgs.stream_ready);
1203 if (ret < 0)
1204 return ret;
1205
1206 hdcp->seq_num_m++;
1207
1208 if (hdcp->seq_num_m > HDCP_2_2_SEQ_NUM_MAX) {
1209 DRM_DEBUG_KMS("seq_num_m roll over.\n");
1210 return -1;
1211 }
1212 return 0;
1213 }
1214

---
0-DAY kernel test infrastructure Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all Intel Corporation
Shankar, Uma
2018-05-14 09:08:04 UTC
Permalink
-----Original Message-----
Ramalingam C
Sent: Tuesday, April 3, 2018 7:28 PM
Subject: [Intel-gfx] [PATCH v3 24/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.
Rebased.
No Changes.
---
drivers/gpu/drm/i915/intel_hdcp.c | 135
++++++++++++++++++++++++++++++++++++++
1 file changed, 135 insertions(+)
diff --git a/drivers/gpu/drm/i915/intel_hdcp.c
b/drivers/gpu/drm/i915/intel_hdcp.c
index ee9b7519fe73..d70320da85e4 100644
--- a/drivers/gpu/drm/i915/intel_hdcp.c
+++ b/drivers/gpu/drm/i915/intel_hdcp.c
@@ -1145,6 +1145,135 @@ static int hdcp2_session_key_exchange(struct
intel_connector *connector)
return 0;
}
+/*
+ * Lib endianness functions are aligned for 16/32/64 bits. Since here
+sequence
+ * num is 24bits developed a small conversion function.
+ */
+static inline void reverse_endianness(u8 *dest, size_t dst_sz, u8 *src)
This function is already defined and used in mei layer. Define this in some
common header file and use instead of duplicating it here. May be in below file:
<drm/drm_connector.h>
+{
+ u32 index;
+
+ if (dest != NULL && dst_sz != 0) {
+ for (index = 0; index < dst_sz && index < sizeof(u32);
+ index++) {
+ dest[dst_sz - index - 1] = src[index];
+ }
+ }
+}
+
+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->hdcp_shim;
+ int ret;
+
+ /* Prepare RepeaterAuth_Stream_Manage msg */
+ msgs.stream_manage.msg_id = HDCP_2_2_REP_STREAM_MANAGE;
+ reverse_endianness(msgs.stream_manage.seq_num_m,
HDCP_2_2_SEQ_NUM_LEN,
+ (u8 *)&hdcp->seq_num_m);
+
+ /* K no of streams is fixed as 1. Stored as big-endian. */
+ msgs.stream_manage.k = __swab16(1);
+
+ /* For HDMI this is forced to be 0x0. For DP SST also this is 0x0. */
+ msgs.stream_manage.streams[0].stream_id = 0;
+ msgs.stream_manage.streams[0].stream_type = hdcp->content_type;
+
+ /* Send it to Repeater */
+ ret = shim->write_2_2_msg(intel_dig_port, &msgs.stream_manage,
+ sizeof(msgs.stream_manage));
+ if (ret < 0)
+ return ret;
+
+ ret = shim->read_2_2_msg(intel_dig_port,
HDCP_2_2_REP_STREAM_READY,
+ &msgs.stream_ready,
sizeof(msgs.stream_ready));
+ if (ret < 0)
+ return ret;
+
+ hdcp->mei_data.seq_num_m = hdcp->seq_num_m;
+ hdcp->mei_data.streams[0].stream_type = hdcp->content_type;
+
+ ret = hdcp2_verify_mprime(hdcp, &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;
+ }
Leave a blank line.
+ 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->hdcp_shim;
+ uint8_t *rx_info;
+ uint32_t 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 -1;
+ }
+
+ /* Converting and Storing the seq_num_v to local variable as DWORD */
+ reverse_endianness((u8 *)&seq_num_v, HDCP_2_2_SEQ_NUM_LEN,
+ 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 -1;
+ }
+
+ ret = hdcp2_verify_rep_topology_prepare_ack(hdcp, &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);
@@ -1186,6 +1315,12 @@ static int hdcp2_authenticate_sink(struct intel_connector *connector)
sizeof(stream_type_msg));
if (ret < 0)
return ret;
+ } else if (hdcp->is_repeater) {
+ ret = hdcp2_authenticate_repeater(connector);
+ if (ret < 0) {
+ DRM_DEBUG_KMS("Repeater Auth Failed. Err: %d\n",
ret);
+ return ret;
+ }
}
hdcp->mei_data.streams[0].stream_type = hdcp->content_type;
--
2.7.4
_______________________________________________
Intel-gfx mailing list
https://lists.freedesktop.org/mailman/listinfo/intel-gfx
Ramalingam C
2018-04-03 13:57:38 UTC
Permalink
Implements the enable and disable functions for HDCP2.2 encryption
of the PORT.

v2:
intel_wait_for_register is used instead of wait_for. [Chris Wilson]
v3:
No Changes.

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

diff --git a/drivers/gpu/drm/i915/intel_hdcp.c b/drivers/gpu/drm/i915/intel_hdcp.c
index d70320da85e4..91cac643f083 100644
--- a/drivers/gpu/drm/i915/intel_hdcp.c
+++ b/drivers/gpu/drm/i915/intel_hdcp.c
@@ -19,6 +19,7 @@
(enum hdcp_physical_port) (port))
#define KEY_LOAD_TRIES 5
#define HDCP2_LC_RETRY_CNT 3
+#define TIME_FOR_ENCRYPT_STATUS_CHANGE 32

static int intel_hdcp_poll_ksv_fifo(struct intel_digital_port *intel_dig_port,
const struct intel_hdcp_shim *shim)
@@ -1330,3 +1331,56 @@ static int hdcp2_authenticate_sink(struct intel_connector *connector)

return ret;
}
+
+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;
+
+ if (I915_READ(HDCP2_STATUS_DDI(port)) & LINK_ENCRYPTION_STATUS)
+ return 0;
+
+ if (hdcp->hdcp_shim->toggle_signalling)
+ hdcp->hdcp_shim->toggle_signalling(intel_dig_port, true);
+
+ if (I915_READ(HDCP2_STATUS_DDI(port)) & LINK_AUTH_STATUS) {
+
+ /* Link is Authenticated. Now set for Encryption */
+ I915_WRITE(HDCP2_CTR_DDI(port),
+ I915_READ(HDCP2_CTR_DDI(port)) |
+ CTL_LINK_ENCRYPTION_REQ);
+ }
+
+ ret = intel_wait_for_register(dev_priv, HDCP2_STATUS_DDI(port),
+ LINK_ENCRYPTION_STATUS,
+ LINK_ENCRYPTION_STATUS,
+ TIME_FOR_ENCRYPT_STATUS_CHANGE);
+ 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;
+
+ if (!(I915_READ(HDCP2_STATUS_DDI(port)) & LINK_ENCRYPTION_STATUS))
+ return 0;
+
+ I915_WRITE(HDCP2_CTR_DDI(port),
+ I915_READ(HDCP2_CTR_DDI(port)) & ~CTL_LINK_ENCRYPTION_REQ);
+
+ ret = intel_wait_for_register(dev_priv, HDCP2_STATUS_DDI(port),
+ LINK_ENCRYPTION_STATUS, 0x0,
+ TIME_FOR_ENCRYPT_STATUS_CHANGE);
+
+ if (hdcp->hdcp_shim->toggle_signalling)
+ hdcp->hdcp_shim->toggle_signalling(intel_dig_port, false);
+
+ return ret;
+}
--
2.7.4
Shankar, Uma
2018-05-14 09:23:29 UTC
Permalink
-----Original Message-----
Ramalingam C
Sent: Tuesday, April 3, 2018 7:28 PM
Subject: [PATCH v3 25/40] drm/i915: Enable and Disable HDCP2.2 port encryption
Implements the enable and disable functions for HDCP2.2 encryption of the
PORT.
intel_wait_for_register is used instead of wait_for. [Chris Wilson]
No Changes.
---
drivers/gpu/drm/i915/intel_hdcp.c | 54
+++++++++++++++++++++++++++++++++++++++
1 file changed, 54 insertions(+)
diff --git a/drivers/gpu/drm/i915/intel_hdcp.c
b/drivers/gpu/drm/i915/intel_hdcp.c
index d70320da85e4..91cac643f083 100644
--- a/drivers/gpu/drm/i915/intel_hdcp.c
+++ b/drivers/gpu/drm/i915/intel_hdcp.c
@@ -19,6 +19,7 @@
(enum hdcp_physical_port) (port))
#define KEY_LOAD_TRIES 5
#define HDCP2_LC_RETRY_CNT 3
+#define TIME_FOR_ENCRYPT_STATUS_CHANGE 32
static int intel_hdcp_poll_ksv_fifo(struct intel_digital_port *intel_dig_port,
*connector)
return ret;
}
+
+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;
+
+ if (I915_READ(HDCP2_STATUS_DDI(port)) & LINK_ENCRYPTION_STATUS)
Print a message saying "Encryption Already enabled" .
+ return 0;
+
+ if (hdcp->hdcp_shim->toggle_signalling)
Check for "hdcp->hdcp_shim" as well.
+ hdcp->hdcp_shim->toggle_signalling(intel_dig_port, true);
+
+ if (I915_READ(HDCP2_STATUS_DDI(port)) & LINK_AUTH_STATUS) {
+
+ /* Link is Authenticated. Now set for Encryption */
+ I915_WRITE(HDCP2_CTR_DDI(port),
+ I915_READ(HDCP2_CTR_DDI(port)) |
+ CTL_LINK_ENCRYPTION_REQ);
+ }
+
+ ret = intel_wait_for_register(dev_priv, HDCP2_STATUS_DDI(port),
+ LINK_ENCRYPTION_STATUS,
+ LINK_ENCRYPTION_STATUS,
+ TIME_FOR_ENCRYPT_STATUS_CHANGE);
Print a message in case of timeout.
+ 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;
+
+ if (!(I915_READ(HDCP2_STATUS_DDI(port)) &
LINK_ENCRYPTION_STATUS))
Put a info message saying "Already Disabled" .
+ return 0;
+
+ I915_WRITE(HDCP2_CTR_DDI(port),
+ I915_READ(HDCP2_CTR_DDI(port)) &
~CTL_LINK_ENCRYPTION_REQ);
+
+ ret = intel_wait_for_register(dev_priv, HDCP2_STATUS_DDI(port),
+ LINK_ENCRYPTION_STATUS, 0x0,
+ TIME_FOR_ENCRYPT_STATUS_CHANGE);
If this times out, do we still need to toggle the signalling ?
+
+ if (hdcp->hdcp_shim->toggle_signalling)
Check for validity of " hdcp->hdcp_shim".
+ hdcp->hdcp_shim->toggle_signalling(intel_dig_port, false);
+
+ return ret;
+}
--
2.7.4
_______________________________________________
dri-devel mailing list
https://lists.freedesktop.org/mailman/listinfo/dri-devel
Ramalingam C
2018-04-03 13:57:39 UTC
Permalink
Implements a sequence of enabling and disabling the HDCP2.2
(auth and encryption).

v2:
Rebased.
v3:
No Changes.

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

diff --git a/drivers/gpu/drm/i915/intel_hdcp.c b/drivers/gpu/drm/i915/intel_hdcp.c
index 91cac643f083..005627746ca5 100644
--- a/drivers/gpu/drm/i915/intel_hdcp.c
+++ b/drivers/gpu/drm/i915/intel_hdcp.c
@@ -21,6 +21,9 @@
#define HDCP2_LC_RETRY_CNT 3
#define TIME_FOR_ENCRYPT_STATUS_CHANGE 32

+static int _intel_hdcp2_enable(struct intel_connector *connector);
+static int _intel_hdcp2_disable(struct intel_connector *connector);
+
static int intel_hdcp_poll_ksv_fifo(struct intel_digital_port *intel_dig_port,
const struct intel_hdcp_shim *shim)
{
@@ -1384,3 +1387,75 @@ static int hdcp2_disable_encryption(struct intel_connector *connector)

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 */
+ hdcp2_deauthenticate_port(&connector->hdcp);
+ DRM_DEBUG_KMS("HDCP2.2 Auth %d of %d Failed.(%d)\n",
+ i + 1, tries, ret);
+ }
+
+ 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);
+ hdcp2_deauthenticate_port(&connector->hdcp);
+ }
+ }
+
+ return ret;
+}
+
+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);
+
+ hdcp2_deauthenticate_port(&connector->hdcp);
+
+ 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_ERROR("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->hdcp_value = DRM_MODE_CONTENT_PROTECTION_ENABLED;
+ schedule_work(&hdcp->hdcp_prop_work);
+
+ return 0;
+}
--
2.7.4
Shankar, Uma
2018-05-14 09:30:08 UTC
Permalink
-----Original Message-----
Ramalingam C
Sent: Tuesday, April 3, 2018 7:28 PM
Subject: [PATCH v3 26/40] drm/i915: Implement HDCP2.2 En/Dis-able
May be calling enable/disable sequence separately will be better :)
Implements a sequence of enabling and disabling the HDCP2.2 (auth and
encryption).
Rebased.
No Changes.
---
drivers/gpu/drm/i915/intel_hdcp.c | 75
+++++++++++++++++++++++++++++++++++++++
1 file changed, 75 insertions(+)
diff --git a/drivers/gpu/drm/i915/intel_hdcp.c
b/drivers/gpu/drm/i915/intel_hdcp.c
index 91cac643f083..005627746ca5 100644
--- a/drivers/gpu/drm/i915/intel_hdcp.c
+++ b/drivers/gpu/drm/i915/intel_hdcp.c
@@ -21,6 +21,9 @@
#define HDCP2_LC_RETRY_CNT 3
#define TIME_FOR_ENCRYPT_STATUS_CHANGE 32
+static int _intel_hdcp2_enable(struct intel_connector *connector);
+static int _intel_hdcp2_disable(struct intel_connector *connector);
+
static int intel_hdcp_poll_ksv_fifo(struct intel_digital_port *intel_dig_port,
*connector)
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 */
+ hdcp2_deauthenticate_port(&connector->hdcp);
+ DRM_DEBUG_KMS("HDCP2.2 Auth %d of %d Failed.(%d)\n",
+ i + 1, tries, ret);
+ }
+
+ 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);
+ hdcp2_deauthenticate_port(&connector->hdcp);
+ }
+ }
+
+ return ret;
+}
+
+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);
Check for return and print a message.
+
+ hdcp2_deauthenticate_port(&connector->hdcp);
+
+ 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_ERROR("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->hdcp_value = DRM_MODE_CONTENT_PROTECTION_ENABLED;
+ schedule_work(&hdcp->hdcp_prop_work);
+
+ return 0;
+}
--
2.7.4
_______________________________________________
dri-devel mailing list
;>https://lists.freedesktop.org/mailman/listinfo/dri-devel
Ramalingam C
2018-04-03 13:57:40 UTC
Permalink
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:
No Changes.

Signed-off-by: Ramalingam C <***@intel.com>
---
drivers/gpu/drm/i915/intel_hdcp.c | 81 ++++++++++++++++++++++++++++++++++++++-
include/drm/drm_hdcp.h | 8 ++++
2 files changed, 88 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/i915/intel_hdcp.c b/drivers/gpu/drm/i915/intel_hdcp.c
index 005627746ca5..e2aec73aefe3 100644
--- a/drivers/gpu/drm/i915/intel_hdcp.c
+++ b/drivers/gpu/drm/i915/intel_hdcp.c
@@ -23,6 +23,8 @@

static int _intel_hdcp2_enable(struct intel_connector *connector);
static int _intel_hdcp2_disable(struct intel_connector *connector);
+static void intel_hdcp2_check_work(struct work_struct *work);
+static int intel_hdcp2_check_link(struct intel_connector *connector);

static int intel_hdcp_poll_ksv_fifo(struct intel_digital_port *intel_dig_port,
const struct intel_hdcp_shim *shim)
@@ -1456,6 +1458,83 @@ static int _intel_hdcp2_enable(struct intel_connector *connector)

hdcp->hdcp_value = DRM_MODE_CONTENT_PROTECTION_ENABLED;
schedule_work(&hdcp->hdcp_prop_work);
-
+ schedule_delayed_work(&hdcp->hdcp2_check_work,
+ DRM_HDCP2_CHECK_PERIOD_MS);
return 0;
}
+
+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;
+
+ if (!hdcp->hdcp_shim)
+ return -ENOENT;
+
+ mutex_lock(&hdcp->hdcp_mutex);
+
+ if (hdcp->hdcp_value == DRM_MODE_CONTENT_PROTECTION_UNDESIRED)
+ goto out;
+
+ if (!(I915_READ(HDCP2_STATUS_DDI(port)) & LINK_ENCRYPTION_STATUS)) {
+ DRM_ERROR("HDCP check failed: link is not encrypted, %x\n",
+ I915_READ(HDCP2_STATUS_DDI(port)));
+ ret = -ENXIO;
+ hdcp->hdcp_value = DRM_MODE_CONTENT_PROTECTION_DESIRED;
+ schedule_work(&hdcp->hdcp_prop_work);
+ goto out;
+ }
+
+ ret = hdcp->hdcp_shim->check_2_2_link(intel_dig_port);
+ if (!ret) {
+ if (hdcp->hdcp_value != DRM_MODE_CONTENT_PROTECTION_UNDESIRED) {
+ hdcp->hdcp_value = DRM_MODE_CONTENT_PROTECTION_ENABLED;
+ schedule_work(&hdcp->hdcp_prop_work);
+ }
+ goto out;
+ }
+
+ DRM_INFO("[%s:%d] HDCP2.2 link failed, retrying authentication\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->hdcp_value = DRM_MODE_CONTENT_PROTECTION_DESIRED;
+ schedule_work(&hdcp->hdcp_prop_work);
+ goto out;
+ }
+
+ ret = _intel_hdcp2_enable(connector);
+ if (ret) {
+ DRM_ERROR("[%s:%d] Failed to enable hdcp2.2 (%d)\n",
+ connector->base.name, connector->base.base.id, ret);
+
+ hdcp->hdcp_value = DRM_MODE_CONTENT_PROTECTION_DESIRED;
+ schedule_work(&hdcp->hdcp_prop_work);
+ goto out;
+ }
+
+out:
+ mutex_unlock(&hdcp->hdcp_mutex);
+ return ret;
+}
+
+static void intel_hdcp2_check_work(struct work_struct *work)
+{
+ struct intel_hdcp *hdcp = container_of(to_delayed_work(work),
+ struct intel_hdcp,
+ hdcp2_check_work);
+ struct intel_connector *connector = container_of(hdcp,
+ struct intel_connector,
+ hdcp);
+
+ if (!intel_hdcp2_check_link(connector))
+ schedule_delayed_work(&hdcp->hdcp2_check_work,
+ DRM_HDCP2_CHECK_PERIOD_MS);
+}
diff --git a/include/drm/drm_hdcp.h b/include/drm/drm_hdcp.h
index f3f28414b189..b0601215c798 100644
--- a/include/drm/drm_hdcp.h
+++ b/include/drm/drm_hdcp.h
@@ -11,6 +11,14 @@

/* Period of hdcp checks (to ensure we're still authenticated) */
#define DRM_HDCP_CHECK_PERIOD_MS (128 * 16)
+#define DRM_HDCP2_CHECK_PERIOD_MS 500
+
+enum check_link_response {
+ DRM_HDCP_LINK_PROTECTED = 0,
+ DRM_HDCP_TOPOLOGY_CHANGE,
+ DRM_HDCP_LINK_INTEGRITY_FAILURE,
+ DRM_HDCP_REAUTH_REQUEST
+};

/* Shared lengths/masks between HDMI/DVI/DisplayPort */
#define DRM_HDCP_AN_LEN 8
--
2.7.4
Shankar, Uma
2018-05-14 09:45:37 UTC
Permalink
-----Original Message-----
Ramalingam C
Sent: Tuesday, April 3, 2018 7:28 PM
Subject: [PATCH v3 27/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.
Rebased.
No Changes.
---
drivers/gpu/drm/i915/intel_hdcp.c | 81
++++++++++++++++++++++++++++++++++++++-
include/drm/drm_hdcp.h | 8 ++++
2 files changed, 88 insertions(+), 1 deletion(-)
diff --git a/drivers/gpu/drm/i915/intel_hdcp.c
b/drivers/gpu/drm/i915/intel_hdcp.c
index 005627746ca5..e2aec73aefe3 100644
--- a/drivers/gpu/drm/i915/intel_hdcp.c
+++ b/drivers/gpu/drm/i915/intel_hdcp.c
@@ -23,6 +23,8 @@
static int _intel_hdcp2_enable(struct intel_connector *connector); static int
_intel_hdcp2_disable(struct intel_connector *connector);
+static void intel_hdcp2_check_work(struct work_struct *work); static
+int intel_hdcp2_check_link(struct intel_connector *connector);
static int intel_hdcp_poll_ksv_fifo(struct intel_digital_port *intel_dig_port,
*connector)
hdcp->hdcp_value = DRM_MODE_CONTENT_PROTECTION_ENABLED;
schedule_work(&hdcp->hdcp_prop_work);
-
+ schedule_delayed_work(&hdcp->hdcp2_check_work,
+ DRM_HDCP2_CHECK_PERIOD_MS);
return 0;
}
+
+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;
+
+ if (!hdcp->hdcp_shim)
+ return -ENOENT;
+
+ mutex_lock(&hdcp->hdcp_mutex);
+
+ if (hdcp->hdcp_value ==
DRM_MODE_CONTENT_PROTECTION_UNDESIRED)
+ goto out;
+
+ if (!(I915_READ(HDCP2_STATUS_DDI(port)) &
LINK_ENCRYPTION_STATUS)) {
+ DRM_ERROR("HDCP check failed: link is not encrypted, %x\n",
+ I915_READ(HDCP2_STATUS_DDI(port)));
+ ret = -ENXIO;
+ hdcp->hdcp_value =
DRM_MODE_CONTENT_PROTECTION_DESIRED;
+ schedule_work(&hdcp->hdcp_prop_work);
+ goto out;
+ }
+
+ ret = hdcp->hdcp_shim->check_2_2_link(intel_dig_port);
Check " hdcp->hdcp_shim->check_2_2_link " for NULL.
+ if (!ret) {
+ if (hdcp->hdcp_value !=
DRM_MODE_CONTENT_PROTECTION_UNDESIRED) {
+ hdcp->hdcp_value =
DRM_MODE_CONTENT_PROTECTION_ENABLED;
+ schedule_work(&hdcp->hdcp_prop_work);
+ }
+ goto out;
+ }
+
+ DRM_INFO("[%s:%d] HDCP2.2 link failed, retrying authentication\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->hdcp_value =
DRM_MODE_CONTENT_PROTECTION_DESIRED;
+ schedule_work(&hdcp->hdcp_prop_work);
+ goto out;
+ }
+
+ ret = _intel_hdcp2_enable(connector);
+ if (ret) {
+ DRM_ERROR("[%s:%d] Failed to enable hdcp2.2 (%d)\n",
+ connector->base.name, connector->base.base.id, ret);
+
+ hdcp->hdcp_value =
DRM_MODE_CONTENT_PROTECTION_DESIRED;
+ schedule_work(&hdcp->hdcp_prop_work);
+ goto out;
+ }
+
+ mutex_unlock(&hdcp->hdcp_mutex);
+ return ret;
+}
+
+static void intel_hdcp2_check_work(struct work_struct *work) {
+ struct intel_hdcp *hdcp = container_of(to_delayed_work(work),
+ struct intel_hdcp,
+ hdcp2_check_work);
+ struct intel_connector *connector = container_of(hdcp,
+ struct intel_connector,
+ hdcp);
+
+ if (!intel_hdcp2_check_link(connector))
A print saying "link not active" will be good, since this was supposed to re-schedule itself and
won't do it again if this doesn’t happen.
+ schedule_delayed_work(&hdcp->hdcp2_check_work,
+ DRM_HDCP2_CHECK_PERIOD_MS);
+}
diff --git a/include/drm/drm_hdcp.h b/include/drm/drm_hdcp.h index
f3f28414b189..b0601215c798 100644
--- a/include/drm/drm_hdcp.h
+++ b/include/drm/drm_hdcp.h
@@ -11,6 +11,14 @@
/* Period of hdcp checks (to ensure we're still authenticated) */
#define DRM_HDCP_CHECK_PERIOD_MS (128 * 16)
+#define DRM_HDCP2_CHECK_PERIOD_MS 500
+
+enum check_link_response {
Don't think this patch uses any of these enums. Add it where its first used.
+ DRM_HDCP_LINK_PROTECTED = 0,
+ DRM_HDCP_TOPOLOGY_CHANGE,
+ DRM_HDCP_LINK_INTEGRITY_FAILURE,
+ DRM_HDCP_REAUTH_REQUEST
+};
/* Shared lengths/masks between HDMI/DVI/DisplayPort */
#define DRM_HDCP_AN_LEN 8
--
2.7.4
_______________________________________________
dri-devel mailing list
https://lists.freedesktop.org/mailman/listinfo/dri-devel
Ramalingam C
2018-04-03 13:57:41 UTC
Permalink
When repeater notifies a downstream topology change, this patch
reauthenticate the repeater alone with out disabling the hdcp
encryption. If that fails then complete reauthentication is executed.

v2:
Rebased.
v3:
No Changes.

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

diff --git a/drivers/gpu/drm/i915/intel_hdcp.c b/drivers/gpu/drm/i915/intel_hdcp.c
index e2aec73aefe3..fd30e2b1ddc3 100644
--- a/drivers/gpu/drm/i915/intel_hdcp.c
+++ b/drivers/gpu/drm/i915/intel_hdcp.c
@@ -1497,8 +1497,23 @@ static int intel_hdcp2_check_link(struct intel_connector *connector)
goto out;
}

- DRM_INFO("[%s:%d] HDCP2.2 link failed, retrying authentication\n",
- connector->base.name, connector->base.base.id);
+ if (ret == DRM_HDCP_TOPOLOGY_CHANGE) {
+ if (hdcp->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->hdcp_value = DRM_MODE_CONTENT_PROTECTION_ENABLED;
+ schedule_work(&hdcp->hdcp_prop_work);
+ goto out;
+ }
+ DRM_ERROR("[%s:%d] Repeater topology auth failed.(%d)\n",
+ connector->base.name, connector->base.base.id, ret);
+ } else {
+ DRM_ERROR("[%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
Ramalingam C
2018-04-03 13:57:42 UTC
Permalink
For reusability purpose, this patch implements the hdcp1.4 bksv's
read and validation as a functions.

For detecting the HDMI panel's HDCP capability this fucntions will be
used.

v2:
Rebased.
v3:
No Changes.

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

diff --git a/drivers/gpu/drm/i915/intel_hdcp.c b/drivers/gpu/drm/i915/intel_hdcp.c
index fd30e2b1ddc3..53d35ee8f683 100644
--- a/drivers/gpu/drm/i915/intel_hdcp.c
+++ b/drivers/gpu/drm/i915/intel_hdcp.c
@@ -152,6 +152,27 @@ bool intel_hdcp_is_ksv_valid(u8 *ksv)
return true;
}

+static inline
+int intel_hdcp_read_valid_bksv(struct intel_digital_port *intel_dig_port,
+ const struct intel_hdcp_shim *shim, u8 *bksv)
+{
+ int ret, i, tries = 2;
+
+ /* HDCP spec states that we must retry the bksv if it is invalid */
+ for (i = 0; i < tries; i++) {
+ ret = shim->read_bksv(intel_dig_port, bksv);
+ if (ret)
+ return ret;
+ if (intel_hdcp_is_ksv_valid(bksv))
+ break;
+ }
+ if (i == tries) {
+ DRM_ERROR("HDCP failed, Bksv is invalid\n");
+ return -ENODEV;
+ }
+ return 0;
+}
+
/* Implements Part 2 of the HDCP authorization procedure */
static
int intel_hdcp_auth_downstream(struct intel_digital_port *intel_dig_port,
@@ -411,7 +432,7 @@ static int intel_hdcp_auth(struct intel_digital_port *intel_dig_port,
struct drm_i915_private *dev_priv;
enum port port;
unsigned long r0_prime_gen_start;
- int ret, i, tries = 2;
+ int ret, i;
union {
u32 reg[2];
u8 shim[DRM_HDCP_AN_LEN];
@@ -469,18 +490,9 @@ static int intel_hdcp_auth(struct intel_digital_port *intel_dig_port,

memset(&bksv, 0, sizeof(bksv));

- /* HDCP spec states that we must retry the bksv if it is invalid */
- for (i = 0; i < tries; i++) {
- ret = shim->read_bksv(intel_dig_port, bksv.shim);
- if (ret)
- return ret;
- if (intel_hdcp_is_ksv_valid(bksv.shim))
- break;
- }
- if (i == tries) {
- DRM_ERROR("HDCP failed, Bksv is invalid\n");
- return -ENODEV;
- }
+ ret = intel_hdcp_read_valid_bksv(intel_dig_port, shim, bksv.shim);
+ if (ret < 0)
+ return ret;

I915_WRITE(PORT_HDCP_BKSVLO(port), bksv.reg[0]);
I915_WRITE(PORT_HDCP_BKSVHI(port), bksv.reg[1]);
--
2.7.4
Ramalingam C
2018-04-03 13:57:44 UTC
Permalink
As a preparation for making the intel_hdcp_enable as common function
for both HDCP1.4 and HDCP2.2, HDCP1.4 check_link scheduling is moved
into _intel_hdcp_enable() function.

v3:
No Changes.

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

diff --git a/drivers/gpu/drm/i915/intel_hdcp.c b/drivers/gpu/drm/i915/intel_hdcp.c
index 6eb58a833c7d..383e35689fbd 100644
--- a/drivers/gpu/drm/i915/intel_hdcp.c
+++ b/drivers/gpu/drm/i915/intel_hdcp.c
@@ -627,7 +627,7 @@ static int _intel_hdcp_enable(struct intel_connector *connector)
ret = intel_hdcp_auth(conn_to_dig_port(connector),
hdcp->hdcp_shim);
if (!ret)
- return 0;
+ break;

DRM_DEBUG_KMS("HDCP Auth failure (%d)\n", ret);

@@ -635,7 +635,12 @@ static int _intel_hdcp_enable(struct intel_connector *connector)
_intel_hdcp_disable(connector);
}

- DRM_ERROR("HDCP authentication failed (%d tries/%d)\n", tries, ret);
+ if (i != tries)
+ schedule_delayed_work(&hdcp->hdcp_check_work,
+ DRM_HDCP_CHECK_PERIOD_MS);
+ else
+ DRM_ERROR("HDCP authentication failed (%d tries/%d)\n",
+ tries, ret);
return ret;
}

@@ -730,8 +735,6 @@ int intel_hdcp_enable(struct intel_connector *connector)

hdcp->hdcp_value = DRM_MODE_CONTENT_PROTECTION_ENABLED;
schedule_work(&hdcp->hdcp_prop_work);
- schedule_delayed_work(&hdcp->hdcp_check_work,
- DRM_HDCP_CHECK_PERIOD_MS);
out:
mutex_unlock(&hdcp->hdcp_mutex);
return ret;
--
2.7.4
Ramalingam C
2018-04-03 13:57:43 UTC
Permalink
Initialize HDCP2.2 support. This includes the mei interface
initialization along with required notifier registration.

v2:
mei interface handle is protected with mutex. [Chris Wilson]
v3:
Notifiers are used for the mei interface state.

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

diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
index 9a4a51e79fa1..955a20208097 100644
--- a/drivers/gpu/drm/i915/intel_dp.c
+++ b/drivers/gpu/drm/i915/intel_dp.c
@@ -6381,7 +6381,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 ca06d9a158f6..2f14756b4b0e 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -442,7 +442,7 @@ struct intel_hdcp {
/* mei interface related information */
struct mei_cl_device *cldev;
struct mei_hdcp_data mei_data;
-
+ struct notifier_block mei_cldev_nb;
struct delayed_work hdcp2_check_work;
};

@@ -1928,7 +1928,8 @@ 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);
diff --git a/drivers/gpu/drm/i915/intel_hdcp.c b/drivers/gpu/drm/i915/intel_hdcp.c
index 53d35ee8f683..6eb58a833c7d 100644
--- a/drivers/gpu/drm/i915/intel_hdcp.c
+++ b/drivers/gpu/drm/i915/intel_hdcp.c
@@ -11,6 +11,7 @@
#include <linux/i2c.h>
#include <linux/random.h>
#include <linux/mei_hdcp.h>
+#include <linux/notifier.h>

#include "intel_drv.h"
#include "i915_reg.h"
@@ -25,6 +26,7 @@ static int _intel_hdcp2_enable(struct intel_connector *connector);
static int _intel_hdcp2_disable(struct intel_connector *connector);
static void intel_hdcp2_check_work(struct work_struct *work);
static int intel_hdcp2_check_link(struct intel_connector *connector);
+static int intel_hdcp2_init(struct intel_connector *connector);

static int intel_hdcp_poll_ksv_fifo(struct intel_digital_port *intel_dig_port,
const struct intel_hdcp_shim *shim)
@@ -686,11 +688,15 @@ bool is_hdcp_supported(struct drm_i915_private *dev_priv, enum port port)
}

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)
{
struct intel_hdcp *hdcp = &connector->hdcp;
int ret;

+ if (!hdcp_shim)
+ return -EINVAL;
+
ret = drm_connector_attach_content_protection_property(
&connector->base);
if (ret)
@@ -699,7 +705,12 @@ int intel_hdcp_init(struct intel_connector *connector,
hdcp->hdcp_shim = hdcp_shim;
mutex_init(&hdcp->hdcp_mutex);
INIT_DELAYED_WORK(&hdcp->hdcp_check_work, intel_hdcp_check_work);
+ INIT_DELAYED_WORK(&hdcp->hdcp2_check_work, intel_hdcp2_check_work);
INIT_WORK(&hdcp->hdcp_prop_work, intel_hdcp_prop_work);
+
+ if (hdcp2_supported)
+ intel_hdcp2_init(connector);
+
return 0;
}

@@ -1565,3 +1576,94 @@ static void intel_hdcp2_check_work(struct work_struct *work)
schedule_delayed_work(&hdcp->hdcp2_check_work,
DRM_HDCP2_CHECK_PERIOD_MS);
}
+
+static inline int initialize_mei_hdcp_data(struct intel_connector *connector)
+{
+ struct intel_hdcp *hdcp = &connector->hdcp;
+ struct mei_hdcp_data *data = &hdcp->mei_data;
+ enum port port;
+
+ if (connector->encoder) {
+ port = connector->encoder->port;
+ data->port = GET_MEI_DDI_INDEX(port);
+ }
+
+ data->port_type = INTEGRATED;
+ data->protocol = hdcp->hdcp_shim->hdcp_protocol();
+
+ data->k = 1;
+ if (!data->streams)
+ data->streams = kcalloc(data->k,
+ sizeof(struct hdcp2_streamid_type),
+ GFP_KERNEL);
+ if (!data->streams)
+ return -ENOMEM;
+
+ data->streams[0].stream_id = 0;
+ data->streams[0].stream_type = hdcp->content_type;
+
+ return 0;
+}
+
+static void intel_hdcp2_exit(struct intel_connector *connector)
+{
+ intel_hdcp_disable(connector);
+ kfree(connector->hdcp.mei_data.streams);
+}
+
+static int mei_cldev_notify(struct notifier_block *nb, unsigned long event,
+ void *cldev)
+{
+ struct intel_hdcp *hdcp = container_of(nb, struct intel_hdcp,
+ mei_cldev_nb);
+ struct intel_connector *intel_connector = container_of(hdcp,
+ struct intel_connector,
+ hdcp);
+
+ DRM_ERROR("MEI_HDCP Notification. Interface: %s\n",
+ cldev ? "UP" : "Down");
+
+ if (event == MEI_CLDEV_ENABLED) {
+ hdcp->cldev = cldev;
+ initialize_mei_hdcp_data(intel_connector);
+ } else {
+ hdcp->cldev = NULL;
+ intel_hdcp2_exit(intel_connector);
+ }
+ return NOTIFY_OK;
+}
+
+static inline
+bool is_hdcp2_supported(struct drm_i915_private *dev_priv)
+{
+ return (INTEL_GEN(dev_priv) >= 10 || IS_GEMINILAKE(dev_priv) ||
+ IS_KABYLAKE(dev_priv));
+}
+
+static int intel_hdcp2_init(struct intel_connector *connector)
+{
+ struct drm_i915_private *dev_priv = to_i915(connector->base.dev);
+ struct intel_hdcp *hdcp = &connector->hdcp;
+ int ret;
+
+ if (!is_hdcp2_supported(dev_priv))
+ return -EINVAL;
+
+ hdcp->hdcp2_supported = true;
+
+ hdcp->mei_cldev_nb.notifier_call = mei_cldev_notify;
+ ret = mei_cldev_register_notify(&hdcp->mei_cldev_nb);
+ if (ret) {
+ DRM_ERROR("mei_cldev not available. %d\n", ret);
+ goto exit;
+ }
+
+ ret = initialize_mei_hdcp_data(connector);
+ if (ret)
+ mei_cldev_unregister_notify(&hdcp->mei_cldev_nb);
+
+exit:
+ if (ret)
+ hdcp->hdcp2_supported = false;
+ return ret;
+}
diff --git a/drivers/gpu/drm/i915/intel_hdmi.c b/drivers/gpu/drm/i915/intel_hdmi.c
index 1baef4ac7ecb..b8b1086c0cbd 100644
--- a/drivers/gpu/drm/i915/intel_hdmi.c
+++ b/drivers/gpu/drm/i915/intel_hdmi.c
@@ -2342,7 +2342,7 @@ void intel_hdmi_init_connector(struct intel_digital_port *intel_dig_port,

if (is_hdcp_supported(dev_priv, port)) {
int ret = intel_hdcp_init(intel_connector,
- &intel_hdmi_hdcp_shim);
+ &intel_hdmi_hdcp_shim, false);
if (ret)
DRM_DEBUG_KMS("HDCP init failed, skipping.\n");
}
--
2.7.4
Ramalingam C
2018-04-03 13:57:45 UTC
Permalink
Considering that HDCP2.2 is more secure than HDCP1.4, When a setup
supports HDCP2.2 and HDCP1.4, HDCP2.2 will be enabled.

v2:
Included few optimization suggestions [Chris Wilson]
Commit message is updated as per the rebased version.
v3:
No changes.

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

diff --git a/drivers/gpu/drm/i915/intel_hdcp.c b/drivers/gpu/drm/i915/intel_hdcp.c
index 383e35689fbd..01701d7b7b07 100644
--- a/drivers/gpu/drm/i915/intel_hdcp.c
+++ b/drivers/gpu/drm/i915/intel_hdcp.c
@@ -27,6 +27,57 @@ static int _intel_hdcp2_disable(struct intel_connector *connector);
static void intel_hdcp2_check_work(struct work_struct *work);
static int intel_hdcp2_check_link(struct intel_connector *connector);
static int intel_hdcp2_init(struct intel_connector *connector);
+static inline
+int intel_hdcp_read_valid_bksv(struct intel_digital_port *intel_dig_port,
+ const struct intel_hdcp_shim *shim, u8 *bksv);
+static
+struct intel_digital_port *conn_to_dig_port(struct intel_connector *connector);
+
+static inline
+bool panel_supports_hdcp(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;
+ u8 bksv[5];
+
+ if (hdcp->hdcp_shim) {
+ if (hdcp->hdcp_shim->hdcp_capable) {
+ hdcp->hdcp_shim->hdcp_capable(intel_dig_port, &capable);
+ } else {
+ if (!intel_hdcp_read_valid_bksv(intel_dig_port,
+ hdcp->hdcp_shim, bksv))
+ capable = true;
+ }
+ }
+ return capable;
+}
+
+static inline
+bool panel_supports_hdcp2(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;
+
+ if (hdcp->hdcp2_supported)
+ hdcp->hdcp_shim->hdcp_2_2_capable(intel_dig_port, &capable);
+
+ return capable;
+}
+
+/* Is HDCP1.4 capable on Platform and Panel */
+static inline bool intel_hdcp_capable(struct intel_connector *connector)
+{
+ return (connector->hdcp.hdcp_shim && panel_supports_hdcp(connector));
+}
+
+/* Is HDCP2.2 capable on Platform and Panel */
+static inline bool intel_hdcp2_capable(struct intel_connector *connector)
+{
+ return (connector->hdcp.hdcp2_supported &&
+ panel_supports_hdcp2(connector));
+}

static int intel_hdcp_poll_ksv_fifo(struct intel_digital_port *intel_dig_port,
const struct intel_hdcp_shim *shim)
@@ -722,20 +773,27 @@ 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->hdcp_shim)
return -ENOENT;

mutex_lock(&hdcp->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);
+ else if (intel_hdcp_capable(connector))
+ ret = _intel_hdcp_enable(connector);
+
+ if (!ret) {
+ hdcp->hdcp_value = DRM_MODE_CONTENT_PROTECTION_ENABLED;
+ schedule_work(&hdcp->hdcp_prop_work);
+ }

- hdcp->hdcp_value = DRM_MODE_CONTENT_PROTECTION_ENABLED;
- schedule_work(&hdcp->hdcp_prop_work);
-out:
mutex_unlock(&hdcp->hdcp_mutex);
return ret;
}
@@ -752,10 +810,14 @@ int intel_hdcp_disable(struct intel_connector *connector)

if (hdcp->hdcp_value != DRM_MODE_CONTENT_PROTECTION_UNDESIRED) {
hdcp->hdcp_value = DRM_MODE_CONTENT_PROTECTION_UNDESIRED;
+ if (hdcp->hdcp2_supported)
+ _intel_hdcp2_disable(connector);
+
ret = _intel_hdcp_disable(connector);
}

mutex_unlock(&hdcp->hdcp_mutex);
+ cancel_delayed_work_sync(&hdcp->hdcp2_check_work);
cancel_delayed_work_sync(&hdcp->hdcp_check_work);
return ret;
}
--
2.7.4
Ramalingam C
2018-04-03 13:57:47 UTC
Permalink
HDCP check link is invoked only on CP_IRQ detection, instead of all
short pulses.

v3:
No Changes.

Signed-off-by: Ramalingam C <***@intel.com>
---
drivers/gpu/drm/i915/intel_dp.c | 9 ++++-----
1 file changed, 4 insertions(+), 5 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
index 955a20208097..4a9f5a690528 100644
--- a/drivers/gpu/drm/i915/intel_dp.c
+++ b/drivers/gpu/drm/i915/intel_dp.c
@@ -4467,8 +4467,10 @@ intel_dp_short_pulse(struct intel_dp *intel_dp)

if (sink_irq_vector & DP_AUTOMATED_TEST_REQUEST)
intel_dp_handle_test_request(intel_dp);
- if (sink_irq_vector & (DP_CP_IRQ | DP_SINK_SPECIFIC_IRQ))
- DRM_DEBUG_DRIVER("CP or sink specific irq unhandled\n");
+ if (sink_irq_vector & DP_CP_IRQ)
+ intel_hdcp_check_link(intel_dp->attached_connector);
+ if (sink_irq_vector & DP_SINK_SPECIFIC_IRQ)
+ DRM_DEBUG_DRIVER("Sink specific irq unhandled\n");
}

/* defer to the hotplug work for link retraining if needed */
@@ -5438,9 +5440,6 @@ intel_dp_hpd_pulse(struct intel_digital_port *intel_dig_port, bool long_hpd)

handled = intel_dp_short_pulse(intel_dp);

- /* Short pulse can signify loss of hdcp authentication */
- intel_hdcp_check_link(intel_dp->attached_connector);
-
if (!handled) {
intel_dp->detect_done = false;
goto put_power;
--
2.7.4
Ramalingam C
2018-04-03 13:57:46 UTC
Permalink
When HDCP2.2 enabling fails and HDCP1.4 is supported, HDCP1.4 is
enabled.

v2:
Rebased.
v3:
No Changes.

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

diff --git a/drivers/gpu/drm/i915/intel_hdcp.c b/drivers/gpu/drm/i915/intel_hdcp.c
index 01701d7b7b07..5707830a4617 100644
--- a/drivers/gpu/drm/i915/intel_hdcp.c
+++ b/drivers/gpu/drm/i915/intel_hdcp.c
@@ -786,7 +786,9 @@ int intel_hdcp_enable(struct intel_connector *connector)
*/
if (intel_hdcp2_capable(connector))
ret = _intel_hdcp2_enable(connector);
- else if (intel_hdcp_capable(connector))
+
+ /* When HDCP2.2 fails, HDCP1.4 will be attempted */
+ if (ret && intel_hdcp_capable(connector))
ret = _intel_hdcp_enable(connector);

if (!ret) {
--
2.7.4
Ramalingam C
2018-04-03 13:57:48 UTC
Permalink
On DP HDCP1.4 and 2.2, when CP_IRQ is received, start the link
integrity check for the HDCP version that is enabled.

v2:
Rebased. Function name is changed.
v3:
No Changes.

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

diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
index 4a9f5a690528..f92c0326fff5 100644
--- a/drivers/gpu/drm/i915/intel_dp.c
+++ b/drivers/gpu/drm/i915/intel_dp.c
@@ -4468,7 +4468,7 @@ intel_dp_short_pulse(struct intel_dp *intel_dp)
if (sink_irq_vector & DP_AUTOMATED_TEST_REQUEST)
intel_dp_handle_test_request(intel_dp);
if (sink_irq_vector & DP_CP_IRQ)
- intel_hdcp_check_link(intel_dp->attached_connector);
+ intel_hdcp_handle_cp_irq(intel_dp->attached_connector);
if (sink_irq_vector & 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 2f14756b4b0e..8e60ccd0d368 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -1932,8 +1932,8 @@ 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);
+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 5707830a4617..8cf0eeb4b3f8 100644
--- a/drivers/gpu/drm/i915/intel_hdcp.c
+++ b/drivers/gpu/drm/i915/intel_hdcp.c
@@ -32,6 +32,7 @@ int intel_hdcp_read_valid_bksv(struct intel_digital_port *intel_dig_port,
const struct intel_hdcp_shim *shim, u8 *bksv);
static
struct intel_digital_port *conn_to_dig_port(struct intel_connector *connector);
+static int intel_hdcp_check_link(struct intel_connector *connector);

static inline
bool panel_supports_hdcp(struct intel_connector *connector)
@@ -79,6 +80,26 @@ static inline bool intel_hdcp2_capable(struct intel_connector *connector)
panel_supports_hdcp2(connector));
}

+static inline bool intel_hdcp_in_force(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_AUTH | HDCP_STATUS_ENC);
+}
+
+static inline bool intel_hdcp2_in_force(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 | LINK_AUTH_STATUS);
+}
+
static int intel_hdcp_poll_ksv_fifo(struct intel_digital_port *intel_dig_port,
const struct intel_hdcp_shim *shim)
{
@@ -858,7 +879,7 @@ void intel_hdcp_atomic_check(struct drm_connector *connector,
}

/* Implements Part 3 of the HDCP authorization procedure */
-int intel_hdcp_check_link(struct intel_connector *connector)
+static 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;
@@ -1734,3 +1755,11 @@ static int intel_hdcp2_init(struct intel_connector *connector)
hdcp->hdcp2_supported = false;
return ret;
}
+
+void intel_hdcp_handle_cp_irq(struct intel_connector *connector)
+{
+ if (intel_hdcp_in_force(connector))
+ intel_hdcp_check_link(connector);
+ else if (intel_hdcp2_in_force(connector))
+ intel_hdcp2_check_link(connector);
+}
--
2.7.4
Ramalingam C
2018-04-03 13:57:49 UTC
Permalink
Implements a interface for single burst read of data that is larger
than 512 Bytes through gmbus.

HDCP2.2 spec expects HDCP2.2 transmitter to read 522Bytes of HDCP
receiver certificates in single burst read. On gmbus, to read more
than 511Bytes, HW provides a workaround for burst read.

This patch passes the burst read request through gmbus read functions.
And implements the sequence of enabling and disabling the burst read.

v2:
No Changes.
v3:
No Changes.

Signed-off-by: Ramalingam C <***@intel.com>
---
drivers/gpu/drm/i915/i915_drv.h | 2 +
drivers/gpu/drm/i915/i915_reg.h | 3 +
drivers/gpu/drm/i915/intel_i2c.c | 124 +++++++++++++++++++++++++++++++++------
3 files changed, 112 insertions(+), 17 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index 6e740f6fe33f..72534a1e544b 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -3688,6 +3688,8 @@ extern void intel_teardown_gmbus(struct drm_i915_private *dev_priv);
extern bool intel_gmbus_is_valid_pin(struct drm_i915_private *dev_priv,
unsigned int pin);
extern int intel_gmbus_output_aksv(struct i2c_adapter *adapter);
+extern int intel_gmbus_burst_read(struct i2c_adapter *adapter,
+ unsigned int offset, void *buf, size_t size);

extern struct i2c_adapter *
intel_gmbus_get_adapter(struct drm_i915_private *dev_priv, unsigned int pin);
diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
index f04ad3c15abd..56979bc4e9d8 100644
--- a/drivers/gpu/drm/i915/i915_reg.h
+++ b/drivers/gpu/drm/i915/i915_reg.h
@@ -3123,6 +3123,7 @@ enum i915_power_well_id {
#define GMBUS_RATE_400KHZ (2<<8) /* reserved on Pineview */
#define GMBUS_RATE_1MHZ (3<<8) /* reserved on Pineview */
#define GMBUS_HOLD_EXT (1<<7) /* 300ns hold time, rsvd on Pineview */
+#define GMBUS_BYTE_CNT_OVERRIDE (1<<6)
#define GMBUS_PIN_DISABLED 0
#define GMBUS_PIN_SSC 1
#define GMBUS_PIN_VGADDC 2
@@ -3150,8 +3151,10 @@ enum i915_power_well_id {
#define GMBUS_CYCLE_WAIT (1<<25)
#define GMBUS_CYCLE_INDEX (2<<25)
#define GMBUS_CYCLE_STOP (4<<25)
+#define GMBUS_CYCLE_MASK (7<<25)
#define GMBUS_BYTE_COUNT_SHIFT 16
#define GMBUS_BYTE_COUNT_MAX 256U
+#define GMBUS_BYTE_COUNT_HW_MAX 511U
#define GMBUS_SLAVE_INDEX_SHIFT 8
#define GMBUS_SLAVE_ADDR_SHIFT 1
#define GMBUS_SLAVE_READ (1<<0)
diff --git a/drivers/gpu/drm/i915/intel_i2c.c b/drivers/gpu/drm/i915/intel_i2c.c
index e6875509bcd9..dcb2be0d54ee 100644
--- a/drivers/gpu/drm/i915/intel_i2c.c
+++ b/drivers/gpu/drm/i915/intel_i2c.c
@@ -364,21 +364,30 @@ gmbus_wait_idle(struct drm_i915_private *dev_priv)
static int
gmbus_xfer_read_chunk(struct drm_i915_private *dev_priv,
unsigned short addr, u8 *buf, unsigned int len,
- u32 gmbus1_index)
+ u32 gmbus1_index, bool burst_read)
{
+ unsigned int size = len;
+ int ret;
+
+ if (burst_read) {
+ /* Seq to enable Burst Read */
+ I915_WRITE_FW(GMBUS0, (I915_READ_FW(GMBUS0) |
+ GMBUS_BYTE_CNT_OVERRIDE));
+ size = GMBUS_BYTE_COUNT_HW_MAX;
+ }
+
I915_WRITE_FW(GMBUS1,
gmbus1_index |
GMBUS_CYCLE_WAIT |
- (len << GMBUS_BYTE_COUNT_SHIFT) |
+ (size << GMBUS_BYTE_COUNT_SHIFT) |
(addr << GMBUS_SLAVE_ADDR_SHIFT) |
GMBUS_SLAVE_READ | GMBUS_SW_RDY);
while (len) {
- int ret;
u32 val, loop = 0;

ret = gmbus_wait(dev_priv, GMBUS_HW_RDY, GMBUS_HW_RDY_EN);
if (ret)
- return ret;
+ goto exit;

val = I915_READ_FW(GMBUS3);
do {
@@ -387,12 +396,29 @@ gmbus_xfer_read_chunk(struct drm_i915_private *dev_priv,
} while (--len && ++loop < 4);
}

- return 0;
+exit:
+ if (burst_read) {
+
+ /* Seq to disable the Burst Read */
+ I915_WRITE_FW(GMBUS0, (I915_READ_FW(GMBUS0) &
+ ~GMBUS_BYTE_CNT_OVERRIDE));
+ I915_WRITE_FW(GMBUS1, (I915_READ_FW(GMBUS1) &
+ ~GMBUS_CYCLE_MASK) | GMBUS_CYCLE_STOP);
+
+ /*
+ * On Burst read disable, GMBUS need more time to settle
+ * down to Idle State.
+ */
+ ret = intel_wait_for_register_fw(dev_priv, GMBUS2,
+ GMBUS_ACTIVE, 0, 50);
+ }
+
+ return ret;
}

static int
gmbus_xfer_read(struct drm_i915_private *dev_priv, struct i2c_msg *msg,
- u32 gmbus1_index)
+ u32 gmbus1_index, bool burst_read)
{
u8 *buf = msg->buf;
unsigned int rx_size = msg->len;
@@ -400,10 +426,13 @@ gmbus_xfer_read(struct drm_i915_private *dev_priv, struct i2c_msg *msg,
int ret;

do {
- len = min(rx_size, GMBUS_BYTE_COUNT_MAX);
+ if (burst_read)
+ len = rx_size;
+ else
+ len = min(rx_size, GMBUS_BYTE_COUNT_MAX);

- ret = gmbus_xfer_read_chunk(dev_priv, msg->addr,
- buf, len, gmbus1_index);
+ ret = gmbus_xfer_read_chunk(dev_priv, msg->addr, buf, len,
+ gmbus1_index, burst_read);
if (ret)
return ret;

@@ -491,7 +520,8 @@ gmbus_is_index_xfer(struct i2c_msg *msgs, int i, int num)
}

static int
-gmbus_index_xfer(struct drm_i915_private *dev_priv, struct i2c_msg *msgs)
+gmbus_index_xfer(struct drm_i915_private *dev_priv, struct i2c_msg *msgs,
+ bool burst_read)
{
u32 gmbus1_index = 0;
u32 gmbus5 = 0;
@@ -509,7 +539,8 @@ gmbus_index_xfer(struct drm_i915_private *dev_priv, struct i2c_msg *msgs)
I915_WRITE_FW(GMBUS5, gmbus5);

if (msgs[1].flags & I2C_M_RD)
- ret = gmbus_xfer_read(dev_priv, &msgs[1], gmbus1_index);
+ ret = gmbus_xfer_read(dev_priv, &msgs[1],
+ gmbus1_index, burst_read);
else
ret = gmbus_xfer_write(dev_priv, &msgs[1], gmbus1_index);

@@ -522,7 +553,7 @@ gmbus_index_xfer(struct drm_i915_private *dev_priv, struct i2c_msg *msgs)

static int
do_gmbus_xfer(struct i2c_adapter *adapter, struct i2c_msg *msgs, int num,
- u32 gmbus0_source)
+ u32 gmbus0_source, bool burst_read)
{
struct intel_gmbus *bus = container_of(adapter,
struct intel_gmbus,
@@ -544,15 +575,20 @@ do_gmbus_xfer(struct i2c_adapter *adapter, struct i2c_msg *msgs, int num,
for (; i < num; i += inc) {
inc = 1;
if (gmbus_is_index_xfer(msgs, i, num)) {
- ret = gmbus_index_xfer(dev_priv, &msgs[i]);
+ ret = gmbus_index_xfer(dev_priv, &msgs[i], burst_read);
inc = 2; /* an index transmission is two msgs */
} else if (msgs[i].flags & I2C_M_RD) {
- ret = gmbus_xfer_read(dev_priv, &msgs[i], 0);
+ ret = gmbus_xfer_read(dev_priv, &msgs[i],
+ 0, burst_read);
} else {
ret = gmbus_xfer_write(dev_priv, &msgs[i], 0);
}

- if (!ret)
+ /*
+ * Burst read Sequence ends with STOP. So Dont expect
+ * HW wait phase.
+ */
+ if (!ret && !burst_read)
ret = gmbus_wait(dev_priv,
GMBUS_HW_WAIT_PHASE, GMBUS_HW_WAIT_EN);
if (ret == -ETIMEDOUT)
@@ -664,7 +700,7 @@ gmbus_xfer(struct i2c_adapter *adapter, struct i2c_msg *msgs, int num)
if (ret < 0)
bus->force_bit &= ~GMBUS_FORCE_BIT_RETRY;
} else {
- ret = do_gmbus_xfer(adapter, msgs, num, 0);
+ ret = do_gmbus_xfer(adapter, msgs, num, 0, false);
if (ret == -EAGAIN)
bus->force_bit |= GMBUS_FORCE_BIT_RETRY;
}
@@ -705,7 +741,8 @@ int intel_gmbus_output_aksv(struct i2c_adapter *adapter)
* pass the i2c command, and tell GMBUS to use the HW-provided value
* instead of sourcing GMBUS3 for the data.
*/
- ret = do_gmbus_xfer(adapter, msgs, ARRAY_SIZE(msgs), GMBUS_AKSV_SELECT);
+ ret = do_gmbus_xfer(adapter, msgs, ARRAY_SIZE(msgs),
+ GMBUS_AKSV_SELECT, false);

mutex_unlock(&dev_priv->gmbus_mutex);
intel_display_power_put(dev_priv, POWER_DOMAIN_GMBUS);
@@ -713,6 +750,59 @@ int intel_gmbus_output_aksv(struct i2c_adapter *adapter)
return ret;
}

+static inline
+bool intel_gmbus_burst_read_supported(struct drm_i915_private *dev_priv)
+{
+ if (INTEL_GEN(dev_priv) > 10 || IS_GEMINILAKE(dev_priv) ||
+ IS_KABYLAKE(dev_priv))
+ return true;
+ return false;
+}
+
+int intel_gmbus_burst_read(struct i2c_adapter *adapter, unsigned int offset,
+ void *buf, size_t size)
+{
+ struct intel_gmbus *bus = container_of(adapter, struct intel_gmbus,
+ adapter);
+ struct drm_i915_private *dev_priv = bus->dev_priv;
+ int ret;
+ u8 start = offset & 0xff;
+ struct i2c_msg msgs[] = {
+ {
+ .addr = DRM_HDCP_DDC_ADDR,
+ .flags = 0,
+ .len = 1,
+ .buf = &start,
+ },
+ {
+ .addr = DRM_HDCP_DDC_ADDR,
+ .flags = I2C_M_RD,
+ .len = size,
+ .buf = buf,
+ }
+ };
+
+ if (!intel_gmbus_burst_read_supported(dev_priv))
+ return -EINVAL;
+
+ intel_display_power_get(dev_priv, POWER_DOMAIN_GMBUS);
+ mutex_lock(&dev_priv->gmbus_mutex);
+
+ /*
+ * In order to read the complete length(More than GMBus Limit) of data,
+ * in burst mode, implement the Workaround supported in HW.
+ */
+ ret = do_gmbus_xfer(adapter, msgs, ARRAY_SIZE(msgs), 0, true);
+
+ mutex_unlock(&dev_priv->gmbus_mutex);
+ intel_display_power_put(dev_priv, POWER_DOMAIN_GMBUS);
+
+ if (ret == ARRAY_SIZE(msgs))
+ return 0;
+
+ return ret >= 0 ? -EIO : ret;
+}
+
static u32 gmbus_func(struct i2c_adapter *adapter)
{
return i2c_bit_algo.functionality(adapter) &
--
2.7.4
Daniel Vetter
2018-04-03 16:40:14 UTC
Permalink
Post by Ramalingam C
Implements a interface for single burst read of data that is larger
than 512 Bytes through gmbus.
HDCP2.2 spec expects HDCP2.2 transmitter to read 522Bytes of HDCP
receiver certificates in single burst read. On gmbus, to read more
than 511Bytes, HW provides a workaround for burst read.
This patch passes the burst read request through gmbus read functions.
And implements the sequence of enabling and disabling the burst read.
No Changes.
No Changes.
Why only enable this burst_read mode for hdcp, and not for all i2c
transactions? Seems to unecessarily complicate the code, since it requires
that you pass burst_read through the entire call chain. For other changes
we've done for hdcp (like enabling the read/write mode and other stuff)
we've enabled it for all i2c transactions. That also means more testing,
since it will be used even when HDCP is not in use.
-Daniel
Post by Ramalingam C
---
drivers/gpu/drm/i915/i915_drv.h | 2 +
drivers/gpu/drm/i915/i915_reg.h | 3 +
drivers/gpu/drm/i915/intel_i2c.c | 124 +++++++++++++++++++++++++++++++++------
3 files changed, 112 insertions(+), 17 deletions(-)
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index 6e740f6fe33f..72534a1e544b 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -3688,6 +3688,8 @@ extern void intel_teardown_gmbus(struct drm_i915_private *dev_priv);
extern bool intel_gmbus_is_valid_pin(struct drm_i915_private *dev_priv,
unsigned int pin);
extern int intel_gmbus_output_aksv(struct i2c_adapter *adapter);
+extern int intel_gmbus_burst_read(struct i2c_adapter *adapter,
+ unsigned int offset, void *buf, size_t size);
extern struct i2c_adapter *
intel_gmbus_get_adapter(struct drm_i915_private *dev_priv, unsigned int pin);
diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
index f04ad3c15abd..56979bc4e9d8 100644
--- a/drivers/gpu/drm/i915/i915_reg.h
+++ b/drivers/gpu/drm/i915/i915_reg.h
@@ -3123,6 +3123,7 @@ enum i915_power_well_id {
#define GMBUS_RATE_400KHZ (2<<8) /* reserved on Pineview */
#define GMBUS_RATE_1MHZ (3<<8) /* reserved on Pineview */
#define GMBUS_HOLD_EXT (1<<7) /* 300ns hold time, rsvd on Pineview */
+#define GMBUS_BYTE_CNT_OVERRIDE (1<<6)
#define GMBUS_PIN_DISABLED 0
#define GMBUS_PIN_SSC 1
#define GMBUS_PIN_VGADDC 2
@@ -3150,8 +3151,10 @@ enum i915_power_well_id {
#define GMBUS_CYCLE_WAIT (1<<25)
#define GMBUS_CYCLE_INDEX (2<<25)
#define GMBUS_CYCLE_STOP (4<<25)
+#define GMBUS_CYCLE_MASK (7<<25)
#define GMBUS_BYTE_COUNT_SHIFT 16
#define GMBUS_BYTE_COUNT_MAX 256U
+#define GMBUS_BYTE_COUNT_HW_MAX 511U
#define GMBUS_SLAVE_INDEX_SHIFT 8
#define GMBUS_SLAVE_ADDR_SHIFT 1
#define GMBUS_SLAVE_READ (1<<0)
diff --git a/drivers/gpu/drm/i915/intel_i2c.c b/drivers/gpu/drm/i915/intel_i2c.c
index e6875509bcd9..dcb2be0d54ee 100644
--- a/drivers/gpu/drm/i915/intel_i2c.c
+++ b/drivers/gpu/drm/i915/intel_i2c.c
@@ -364,21 +364,30 @@ gmbus_wait_idle(struct drm_i915_private *dev_priv)
static int
gmbus_xfer_read_chunk(struct drm_i915_private *dev_priv,
unsigned short addr, u8 *buf, unsigned int len,
- u32 gmbus1_index)
+ u32 gmbus1_index, bool burst_read)
{
+ unsigned int size = len;
+ int ret;
+
+ if (burst_read) {
+ /* Seq to enable Burst Read */
+ I915_WRITE_FW(GMBUS0, (I915_READ_FW(GMBUS0) |
+ GMBUS_BYTE_CNT_OVERRIDE));
+ size = GMBUS_BYTE_COUNT_HW_MAX;
+ }
+
I915_WRITE_FW(GMBUS1,
gmbus1_index |
GMBUS_CYCLE_WAIT |
- (len << GMBUS_BYTE_COUNT_SHIFT) |
+ (size << GMBUS_BYTE_COUNT_SHIFT) |
(addr << GMBUS_SLAVE_ADDR_SHIFT) |
GMBUS_SLAVE_READ | GMBUS_SW_RDY);
while (len) {
- int ret;
u32 val, loop = 0;
ret = gmbus_wait(dev_priv, GMBUS_HW_RDY, GMBUS_HW_RDY_EN);
if (ret)
- return ret;
+ goto exit;
val = I915_READ_FW(GMBUS3);
do {
@@ -387,12 +396,29 @@ gmbus_xfer_read_chunk(struct drm_i915_private *dev_priv,
} while (--len && ++loop < 4);
}
- return 0;
+ if (burst_read) {
+
+ /* Seq to disable the Burst Read */
+ I915_WRITE_FW(GMBUS0, (I915_READ_FW(GMBUS0) &
+ ~GMBUS_BYTE_CNT_OVERRIDE));
+ I915_WRITE_FW(GMBUS1, (I915_READ_FW(GMBUS1) &
+ ~GMBUS_CYCLE_MASK) | GMBUS_CYCLE_STOP);
+
+ /*
+ * On Burst read disable, GMBUS need more time to settle
+ * down to Idle State.
+ */
+ ret = intel_wait_for_register_fw(dev_priv, GMBUS2,
+ GMBUS_ACTIVE, 0, 50);
+ }
+
+ return ret;
}
static int
gmbus_xfer_read(struct drm_i915_private *dev_priv, struct i2c_msg *msg,
- u32 gmbus1_index)
+ u32 gmbus1_index, bool burst_read)
{
u8 *buf = msg->buf;
unsigned int rx_size = msg->len;
@@ -400,10 +426,13 @@ gmbus_xfer_read(struct drm_i915_private *dev_priv, struct i2c_msg *msg,
int ret;
do {
- len = min(rx_size, GMBUS_BYTE_COUNT_MAX);
+ if (burst_read)
+ len = rx_size;
+ else
+ len = min(rx_size, GMBUS_BYTE_COUNT_MAX);
- ret = gmbus_xfer_read_chunk(dev_priv, msg->addr,
- buf, len, gmbus1_index);
+ ret = gmbus_xfer_read_chunk(dev_priv, msg->addr, buf, len,
+ gmbus1_index, burst_read);
if (ret)
return ret;
@@ -491,7 +520,8 @@ gmbus_is_index_xfer(struct i2c_msg *msgs, int i, int num)
}
static int
-gmbus_index_xfer(struct drm_i915_private *dev_priv, struct i2c_msg *msgs)
+gmbus_index_xfer(struct drm_i915_private *dev_priv, struct i2c_msg *msgs,
+ bool burst_read)
{
u32 gmbus1_index = 0;
u32 gmbus5 = 0;
@@ -509,7 +539,8 @@ gmbus_index_xfer(struct drm_i915_private *dev_priv, struct i2c_msg *msgs)
I915_WRITE_FW(GMBUS5, gmbus5);
if (msgs[1].flags & I2C_M_RD)
- ret = gmbus_xfer_read(dev_priv, &msgs[1], gmbus1_index);
+ ret = gmbus_xfer_read(dev_priv, &msgs[1],
+ gmbus1_index, burst_read);
else
ret = gmbus_xfer_write(dev_priv, &msgs[1], gmbus1_index);
@@ -522,7 +553,7 @@ gmbus_index_xfer(struct drm_i915_private *dev_priv, struct i2c_msg *msgs)
static int
do_gmbus_xfer(struct i2c_adapter *adapter, struct i2c_msg *msgs, int num,
- u32 gmbus0_source)
+ u32 gmbus0_source, bool burst_read)
{
struct intel_gmbus *bus = container_of(adapter,
struct intel_gmbus,
@@ -544,15 +575,20 @@ do_gmbus_xfer(struct i2c_adapter *adapter, struct i2c_msg *msgs, int num,
for (; i < num; i += inc) {
inc = 1;
if (gmbus_is_index_xfer(msgs, i, num)) {
- ret = gmbus_index_xfer(dev_priv, &msgs[i]);
+ ret = gmbus_index_xfer(dev_priv, &msgs[i], burst_read);
inc = 2; /* an index transmission is two msgs */
} else if (msgs[i].flags & I2C_M_RD) {
- ret = gmbus_xfer_read(dev_priv, &msgs[i], 0);
+ ret = gmbus_xfer_read(dev_priv, &msgs[i],
+ 0, burst_read);
} else {
ret = gmbus_xfer_write(dev_priv, &msgs[i], 0);
}
- if (!ret)
+ /*
+ * Burst read Sequence ends with STOP. So Dont expect
+ * HW wait phase.
+ */
+ if (!ret && !burst_read)
ret = gmbus_wait(dev_priv,
GMBUS_HW_WAIT_PHASE, GMBUS_HW_WAIT_EN);
if (ret == -ETIMEDOUT)
@@ -664,7 +700,7 @@ gmbus_xfer(struct i2c_adapter *adapter, struct i2c_msg *msgs, int num)
if (ret < 0)
bus->force_bit &= ~GMBUS_FORCE_BIT_RETRY;
} else {
- ret = do_gmbus_xfer(adapter, msgs, num, 0);
+ ret = do_gmbus_xfer(adapter, msgs, num, 0, false);
if (ret == -EAGAIN)
bus->force_bit |= GMBUS_FORCE_BIT_RETRY;
}
@@ -705,7 +741,8 @@ int intel_gmbus_output_aksv(struct i2c_adapter *adapter)
* pass the i2c command, and tell GMBUS to use the HW-provided value
* instead of sourcing GMBUS3 for the data.
*/
- ret = do_gmbus_xfer(adapter, msgs, ARRAY_SIZE(msgs), GMBUS_AKSV_SELECT);
+ ret = do_gmbus_xfer(adapter, msgs, ARRAY_SIZE(msgs),
+ GMBUS_AKSV_SELECT, false);
mutex_unlock(&dev_priv->gmbus_mutex);
intel_display_power_put(dev_priv, POWER_DOMAIN_GMBUS);
@@ -713,6 +750,59 @@ int intel_gmbus_output_aksv(struct i2c_adapter *adapter)
return ret;
}
+static inline
+bool intel_gmbus_burst_read_supported(struct drm_i915_private *dev_priv)
+{
+ if (INTEL_GEN(dev_priv) > 10 || IS_GEMINILAKE(dev_priv) ||
+ IS_KABYLAKE(dev_priv))
+ return true;
+ return false;
+}
+
+int intel_gmbus_burst_read(struct i2c_adapter *adapter, unsigned int offset,
+ void *buf, size_t size)
+{
+ struct intel_gmbus *bus = container_of(adapter, struct intel_gmbus,
+ adapter);
+ struct drm_i915_private *dev_priv = bus->dev_priv;
+ int ret;
+ u8 start = offset & 0xff;
+ struct i2c_msg msgs[] = {
+ {
+ .addr = DRM_HDCP_DDC_ADDR,
+ .flags = 0,
+ .len = 1,
+ .buf = &start,
+ },
+ {
+ .addr = DRM_HDCP_DDC_ADDR,
+ .flags = I2C_M_RD,
+ .len = size,
+ .buf = buf,
+ }
+ };
+
+ if (!intel_gmbus_burst_read_supported(dev_priv))
+ return -EINVAL;
+
+ intel_display_power_get(dev_priv, POWER_DOMAIN_GMBUS);
+ mutex_lock(&dev_priv->gmbus_mutex);
+
+ /*
+ * In order to read the complete length(More than GMBus Limit) of data,
+ * in burst mode, implement the Workaround supported in HW.
+ */
+ ret = do_gmbus_xfer(adapter, msgs, ARRAY_SIZE(msgs), 0, true);
+
+ mutex_unlock(&dev_priv->gmbus_mutex);
+ intel_display_power_put(dev_priv, POWER_DOMAIN_GMBUS);
+
+ if (ret == ARRAY_SIZE(msgs))
+ return 0;
+
+ return ret >= 0 ? -EIO : ret;
+}
+
static u32 gmbus_func(struct i2c_adapter *adapter)
{
return i2c_bit_algo.functionality(adapter) &
--
2.7.4
--
Daniel Vetter
Software Engineer, Intel Corporation
http://blog.ffwll.ch
Jani Nikula
2018-04-05 09:12:15 UTC
Permalink
Post by Daniel Vetter
Post by Ramalingam C
Implements a interface for single burst read of data that is larger
than 512 Bytes through gmbus.
Where does 512 come from? Current code chunks at GMBUS_BYTE_COUNT_MAX
i.e. 256 bytes. Should GMBUS_BYTE_COUNT_MAX be platform specific?
Post by Daniel Vetter
Post by Ramalingam C
HDCP2.2 spec expects HDCP2.2 transmitter to read 522Bytes of HDCP
receiver certificates in single burst read. On gmbus, to read more
than 511Bytes, HW provides a workaround for burst read.
This patch passes the burst read request through gmbus read functions.
And implements the sequence of enabling and disabling the burst read.
No Changes.
No Changes.
Why only enable this burst_read mode for hdcp, and not for all i2c
transactions? Seems to unecessarily complicate the code, since it requires
that you pass burst_read through the entire call chain. For other changes
we've done for hdcp (like enabling the read/write mode and other stuff)
we've enabled it for all i2c transactions. That also means more testing,
since it will be used even when HDCP is not in use.
Agreed.

Shouldn't the decision to use burst read be based on the length to be
read? More than 256 bytes, use burst, otherwise not. Or are there
functional differences or benefits to using burst mode for shorter
reads?

I guess I'd still prepare to add some burst field to struct intel_gmbus,
not unlike force_bit.

Side note, I would prefer significant changes to basic plumbing like
gmbus be highlighted better. Please at least prefix the hdcp patches
with "drm/i915/hdcp" and gmbus with "drm/i915/gmbus". The patch at hand
is kind of hidden in the middle of a large topical series, and would
deserve to be looked at by people who aren't necessarily all that into
hdcp.


BR,
Jani.
Post by Daniel Vetter
-Daniel
Post by Ramalingam C
---
drivers/gpu/drm/i915/i915_drv.h | 2 +
drivers/gpu/drm/i915/i915_reg.h | 3 +
drivers/gpu/drm/i915/intel_i2c.c | 124 +++++++++++++++++++++++++++++++++------
3 files changed, 112 insertions(+), 17 deletions(-)
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index 6e740f6fe33f..72534a1e544b 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -3688,6 +3688,8 @@ extern void intel_teardown_gmbus(struct drm_i915_private *dev_priv);
extern bool intel_gmbus_is_valid_pin(struct drm_i915_private *dev_priv,
unsigned int pin);
extern int intel_gmbus_output_aksv(struct i2c_adapter *adapter);
+extern int intel_gmbus_burst_read(struct i2c_adapter *adapter,
+ unsigned int offset, void *buf, size_t size);
extern struct i2c_adapter *
intel_gmbus_get_adapter(struct drm_i915_private *dev_priv, unsigned int pin);
diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
index f04ad3c15abd..56979bc4e9d8 100644
--- a/drivers/gpu/drm/i915/i915_reg.h
+++ b/drivers/gpu/drm/i915/i915_reg.h
@@ -3123,6 +3123,7 @@ enum i915_power_well_id {
#define GMBUS_RATE_400KHZ (2<<8) /* reserved on Pineview */
#define GMBUS_RATE_1MHZ (3<<8) /* reserved on Pineview */
#define GMBUS_HOLD_EXT (1<<7) /* 300ns hold time, rsvd on Pineview */
+#define GMBUS_BYTE_CNT_OVERRIDE (1<<6)
#define GMBUS_PIN_DISABLED 0
#define GMBUS_PIN_SSC 1
#define GMBUS_PIN_VGADDC 2
@@ -3150,8 +3151,10 @@ enum i915_power_well_id {
#define GMBUS_CYCLE_WAIT (1<<25)
#define GMBUS_CYCLE_INDEX (2<<25)
#define GMBUS_CYCLE_STOP (4<<25)
+#define GMBUS_CYCLE_MASK (7<<25)
#define GMBUS_BYTE_COUNT_SHIFT 16
#define GMBUS_BYTE_COUNT_MAX 256U
+#define GMBUS_BYTE_COUNT_HW_MAX 511U
#define GMBUS_SLAVE_INDEX_SHIFT 8
#define GMBUS_SLAVE_ADDR_SHIFT 1
#define GMBUS_SLAVE_READ (1<<0)
diff --git a/drivers/gpu/drm/i915/intel_i2c.c b/drivers/gpu/drm/i915/intel_i2c.c
index e6875509bcd9..dcb2be0d54ee 100644
--- a/drivers/gpu/drm/i915/intel_i2c.c
+++ b/drivers/gpu/drm/i915/intel_i2c.c
@@ -364,21 +364,30 @@ gmbus_wait_idle(struct drm_i915_private *dev_priv)
static int
gmbus_xfer_read_chunk(struct drm_i915_private *dev_priv,
unsigned short addr, u8 *buf, unsigned int len,
- u32 gmbus1_index)
+ u32 gmbus1_index, bool burst_read)
{
+ unsigned int size = len;
+ int ret;
+
+ if (burst_read) {
+ /* Seq to enable Burst Read */
+ I915_WRITE_FW(GMBUS0, (I915_READ_FW(GMBUS0) |
+ GMBUS_BYTE_CNT_OVERRIDE));
+ size = GMBUS_BYTE_COUNT_HW_MAX;
+ }
+
I915_WRITE_FW(GMBUS1,
gmbus1_index |
GMBUS_CYCLE_WAIT |
- (len << GMBUS_BYTE_COUNT_SHIFT) |
+ (size << GMBUS_BYTE_COUNT_SHIFT) |
(addr << GMBUS_SLAVE_ADDR_SHIFT) |
GMBUS_SLAVE_READ | GMBUS_SW_RDY);
while (len) {
- int ret;
u32 val, loop = 0;
ret = gmbus_wait(dev_priv, GMBUS_HW_RDY, GMBUS_HW_RDY_EN);
if (ret)
- return ret;
+ goto exit;
val = I915_READ_FW(GMBUS3);
do {
@@ -387,12 +396,29 @@ gmbus_xfer_read_chunk(struct drm_i915_private *dev_priv,
} while (--len && ++loop < 4);
}
- return 0;
+ if (burst_read) {
+
+ /* Seq to disable the Burst Read */
+ I915_WRITE_FW(GMBUS0, (I915_READ_FW(GMBUS0) &
+ ~GMBUS_BYTE_CNT_OVERRIDE));
+ I915_WRITE_FW(GMBUS1, (I915_READ_FW(GMBUS1) &
+ ~GMBUS_CYCLE_MASK) | GMBUS_CYCLE_STOP);
+
+ /*
+ * On Burst read disable, GMBUS need more time to settle
+ * down to Idle State.
+ */
+ ret = intel_wait_for_register_fw(dev_priv, GMBUS2,
+ GMBUS_ACTIVE, 0, 50);
+ }
+
+ return ret;
}
static int
gmbus_xfer_read(struct drm_i915_private *dev_priv, struct i2c_msg *msg,
- u32 gmbus1_index)
+ u32 gmbus1_index, bool burst_read)
{
u8 *buf = msg->buf;
unsigned int rx_size = msg->len;
@@ -400,10 +426,13 @@ gmbus_xfer_read(struct drm_i915_private *dev_priv, struct i2c_msg *msg,
int ret;
do {
- len = min(rx_size, GMBUS_BYTE_COUNT_MAX);
+ if (burst_read)
+ len = rx_size;
+ else
+ len = min(rx_size, GMBUS_BYTE_COUNT_MAX);
- ret = gmbus_xfer_read_chunk(dev_priv, msg->addr,
- buf, len, gmbus1_index);
+ ret = gmbus_xfer_read_chunk(dev_priv, msg->addr, buf, len,
+ gmbus1_index, burst_read);
if (ret)
return ret;
@@ -491,7 +520,8 @@ gmbus_is_index_xfer(struct i2c_msg *msgs, int i, int num)
}
static int
-gmbus_index_xfer(struct drm_i915_private *dev_priv, struct i2c_msg *msgs)
+gmbus_index_xfer(struct drm_i915_private *dev_priv, struct i2c_msg *msgs,
+ bool burst_read)
{
u32 gmbus1_index = 0;
u32 gmbus5 = 0;
@@ -509,7 +539,8 @@ gmbus_index_xfer(struct drm_i915_private *dev_priv, struct i2c_msg *msgs)
I915_WRITE_FW(GMBUS5, gmbus5);
if (msgs[1].flags & I2C_M_RD)
- ret = gmbus_xfer_read(dev_priv, &msgs[1], gmbus1_index);
+ ret = gmbus_xfer_read(dev_priv, &msgs[1],
+ gmbus1_index, burst_read);
else
ret = gmbus_xfer_write(dev_priv, &msgs[1], gmbus1_index);
@@ -522,7 +553,7 @@ gmbus_index_xfer(struct drm_i915_private *dev_priv, struct i2c_msg *msgs)
static int
do_gmbus_xfer(struct i2c_adapter *adapter, struct i2c_msg *msgs, int num,
- u32 gmbus0_source)
+ u32 gmbus0_source, bool burst_read)
{
struct intel_gmbus *bus = container_of(adapter,
struct intel_gmbus,
@@ -544,15 +575,20 @@ do_gmbus_xfer(struct i2c_adapter *adapter, struct i2c_msg *msgs, int num,
for (; i < num; i += inc) {
inc = 1;
if (gmbus_is_index_xfer(msgs, i, num)) {
- ret = gmbus_index_xfer(dev_priv, &msgs[i]);
+ ret = gmbus_index_xfer(dev_priv, &msgs[i], burst_read);
inc = 2; /* an index transmission is two msgs */
} else if (msgs[i].flags & I2C_M_RD) {
- ret = gmbus_xfer_read(dev_priv, &msgs[i], 0);
+ ret = gmbus_xfer_read(dev_priv, &msgs[i],
+ 0, burst_read);
} else {
ret = gmbus_xfer_write(dev_priv, &msgs[i], 0);
}
- if (!ret)
+ /*
+ * Burst read Sequence ends with STOP. So Dont expect
+ * HW wait phase.
+ */
+ if (!ret && !burst_read)
ret = gmbus_wait(dev_priv,
GMBUS_HW_WAIT_PHASE, GMBUS_HW_WAIT_EN);
if (ret == -ETIMEDOUT)
@@ -664,7 +700,7 @@ gmbus_xfer(struct i2c_adapter *adapter, struct i2c_msg *msgs, int num)
if (ret < 0)
bus->force_bit &= ~GMBUS_FORCE_BIT_RETRY;
} else {
- ret = do_gmbus_xfer(adapter, msgs, num, 0);
+ ret = do_gmbus_xfer(adapter, msgs, num, 0, false);
if (ret == -EAGAIN)
bus->force_bit |= GMBUS_FORCE_BIT_RETRY;
}
@@ -705,7 +741,8 @@ int intel_gmbus_output_aksv(struct i2c_adapter *adapter)
* pass the i2c command, and tell GMBUS to use the HW-provided value
* instead of sourcing GMBUS3 for the data.
*/
- ret = do_gmbus_xfer(adapter, msgs, ARRAY_SIZE(msgs), GMBUS_AKSV_SELECT);
+ ret = do_gmbus_xfer(adapter, msgs, ARRAY_SIZE(msgs),
+ GMBUS_AKSV_SELECT, false);
mutex_unlock(&dev_priv->gmbus_mutex);
intel_display_power_put(dev_priv, POWER_DOMAIN_GMBUS);
@@ -713,6 +750,59 @@ int intel_gmbus_output_aksv(struct i2c_adapter *adapter)
return ret;
}
+static inline
+bool intel_gmbus_burst_read_supported(struct drm_i915_private *dev_priv)
+{
+ if (INTEL_GEN(dev_priv) > 10 || IS_GEMINILAKE(dev_priv) ||
+ IS_KABYLAKE(dev_priv))
+ return true;
+ return false;
+}
+
+int intel_gmbus_burst_read(struct i2c_adapter *adapter, unsigned int offset,
+ void *buf, size_t size)
+{
+ struct intel_gmbus *bus = container_of(adapter, struct intel_gmbus,
+ adapter);
+ struct drm_i915_private *dev_priv = bus->dev_priv;
+ int ret;
+ u8 start = offset & 0xff;
+ struct i2c_msg msgs[] = {
+ {
+ .addr = DRM_HDCP_DDC_ADDR,
+ .flags = 0,
+ .len = 1,
+ .buf = &start,
+ },
+ {
+ .addr = DRM_HDCP_DDC_ADDR,
+ .flags = I2C_M_RD,
+ .len = size,
+ .buf = buf,
+ }
+ };
+
+ if (!intel_gmbus_burst_read_supported(dev_priv))
+ return -EINVAL;
+
+ intel_display_power_get(dev_priv, POWER_DOMAIN_GMBUS);
+ mutex_lock(&dev_priv->gmbus_mutex);
+
+ /*
+ * In order to read the complete length(More than GMBus Limit) of data,
+ * in burst mode, implement the Workaround supported in HW.
+ */
+ ret = do_gmbus_xfer(adapter, msgs, ARRAY_SIZE(msgs), 0, true);
+
+ mutex_unlock(&dev_priv->gmbus_mutex);
+ intel_display_power_put(dev_priv, POWER_DOMAIN_GMBUS);
+
+ if (ret == ARRAY_SIZE(msgs))
+ return 0;
+
+ return ret >= 0 ? -EIO : ret;
+}
+
static u32 gmbus_func(struct i2c_adapter *adapter)
{
return i2c_bit_algo.functionality(adapter) &
--
2.7.4
--
Jani Nikula, Intel Open Source Technology Center
Ramalingam C
2018-04-05 13:44:22 UTC
Permalink
Post by Jani Nikula
Post by Daniel Vetter
Post by Ramalingam C
Implements a interface for single burst read of data that is larger
than 512 Bytes through gmbus.
Where does 512 come from? Current code chunks at GMBUS_BYTE_COUNT_MAX
i.e. 256 bytes. Should GMBUS_BYTE_COUNT_MAX be platform specific?
Actually I am not sure why 256 is the max limit for gmbus read/write
when HW allows upto 511Bytes. 24:16 9bits of GMBUS is Total byte count.
So max value could be 511Bytes.
256 is choosen because of some practical reason or any legacy platform
capability?
Post by Jani Nikula
Post by Daniel Vetter
Post by Ramalingam C
HDCP2.2 spec expects HDCP2.2 transmitter to read 522Bytes of HDCP
receiver certificates in single burst read. On gmbus, to read more
than 511Bytes, HW provides a workaround for burst read.
This patch passes the burst read request through gmbus read functions.
And implements the sequence of enabling and disabling the burst read.
No Changes.
No Changes.
Why only enable this burst_read mode for hdcp, and not for all i2c
transactions? Seems to unecessarily complicate the code, since it requires
that you pass burst_read through the entire call chain. For other changes
we've done for hdcp (like enabling the read/write mode and other stuff)
we've enabled it for all i2c transactions. That also means more testing,
since it will be used even when HDCP is not in use.
Agreed.
Shouldn't the decision to use burst read be based on the length to be
read? More than 256 bytes, use burst, otherwise not. Or are there
functional differences or benefits to using burst mode for shorter
reads?
Busrt read is enabled on few latest platforms (from KBL+ for HDCP2.2
compliance requirement,
where split I2C read of a msg(534Bytes) is not accepted)

If there is no objection, extend the single normal rd/wr to 511Bytes
from 256bytes.
And any read for more than 511 Bytes use the Burst read on capable
platforms.

Though personally I dont believe it will give much of optimization, as
burst read also brings in some
extra programming requirements. But might avoid extra driver entry point
for GMBUS like intel_gmbus_burst_read().
Post by Jani Nikula
I guess I'd still prepare to add some burst field to struct intel_gmbus,
not unlike force_bit.
Side note, I would prefer significant changes to basic plumbing like
gmbus be highlighted better. Please at least prefix the hdcp patches
with "drm/i915/hdcp" and gmbus with "drm/i915/gmbus". The patch at hand
is kind of hidden in the middle of a large topical series, and would
deserve to be looked at by people who aren't necessarily all that into
hdcp.
Sure.

--Ram
Post by Jani Nikula
BR,
Jani.
Post by Daniel Vetter
-Daniel
Post by Ramalingam C
---
drivers/gpu/drm/i915/i915_drv.h | 2 +
drivers/gpu/drm/i915/i915_reg.h | 3 +
drivers/gpu/drm/i915/intel_i2c.c | 124 +++++++++++++++++++++++++++++++++------
3 files changed, 112 insertions(+), 17 deletions(-)
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index 6e740f6fe33f..72534a1e544b 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -3688,6 +3688,8 @@ extern void intel_teardown_gmbus(struct drm_i915_private *dev_priv);
extern bool intel_gmbus_is_valid_pin(struct drm_i915_private *dev_priv,
unsigned int pin);
extern int intel_gmbus_output_aksv(struct i2c_adapter *adapter);
+extern int intel_gmbus_burst_read(struct i2c_adapter *adapter,
+ unsigned int offset, void *buf, size_t size);
extern struct i2c_adapter *
intel_gmbus_get_adapter(struct drm_i915_private *dev_priv, unsigned int pin);
diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
index f04ad3c15abd..56979bc4e9d8 100644
--- a/drivers/gpu/drm/i915/i915_reg.h
+++ b/drivers/gpu/drm/i915/i915_reg.h
@@ -3123,6 +3123,7 @@ enum i915_power_well_id {
#define GMBUS_RATE_400KHZ (2<<8) /* reserved on Pineview */
#define GMBUS_RATE_1MHZ (3<<8) /* reserved on Pineview */
#define GMBUS_HOLD_EXT (1<<7) /* 300ns hold time, rsvd on Pineview */
+#define GMBUS_BYTE_CNT_OVERRIDE (1<<6)
#define GMBUS_PIN_DISABLED 0
#define GMBUS_PIN_SSC 1
#define GMBUS_PIN_VGADDC 2
@@ -3150,8 +3151,10 @@ enum i915_power_well_id {
#define GMBUS_CYCLE_WAIT (1<<25)
#define GMBUS_CYCLE_INDEX (2<<25)
#define GMBUS_CYCLE_STOP (4<<25)
+#define GMBUS_CYCLE_MASK (7<<25)
#define GMBUS_BYTE_COUNT_SHIFT 16
#define GMBUS_BYTE_COUNT_MAX 256U
+#define GMBUS_BYTE_COUNT_HW_MAX 511U
#define GMBUS_SLAVE_INDEX_SHIFT 8
#define GMBUS_SLAVE_ADDR_SHIFT 1
#define GMBUS_SLAVE_READ (1<<0)
diff --git a/drivers/gpu/drm/i915/intel_i2c.c b/drivers/gpu/drm/i915/intel_i2c.c
index e6875509bcd9..dcb2be0d54ee 100644
--- a/drivers/gpu/drm/i915/intel_i2c.c
+++ b/drivers/gpu/drm/i915/intel_i2c.c
@@ -364,21 +364,30 @@ gmbus_wait_idle(struct drm_i915_private *dev_priv)
static int
gmbus_xfer_read_chunk(struct drm_i915_private *dev_priv,
unsigned short addr, u8 *buf, unsigned int len,
- u32 gmbus1_index)
+ u32 gmbus1_index, bool burst_read)
{
+ unsigned int size = len;
+ int ret;
+
+ if (burst_read) {
+ /* Seq to enable Burst Read */
+ I915_WRITE_FW(GMBUS0, (I915_READ_FW(GMBUS0) |
+ GMBUS_BYTE_CNT_OVERRIDE));
+ size = GMBUS_BYTE_COUNT_HW_MAX;
+ }
+
I915_WRITE_FW(GMBUS1,
gmbus1_index |
GMBUS_CYCLE_WAIT |
- (len << GMBUS_BYTE_COUNT_SHIFT) |
+ (size << GMBUS_BYTE_COUNT_SHIFT) |
(addr << GMBUS_SLAVE_ADDR_SHIFT) |
GMBUS_SLAVE_READ | GMBUS_SW_RDY);
while (len) {
- int ret;
u32 val, loop = 0;
ret = gmbus_wait(dev_priv, GMBUS_HW_RDY, GMBUS_HW_RDY_EN);
if (ret)
- return ret;
+ goto exit;
val = I915_READ_FW(GMBUS3);
do {
@@ -387,12 +396,29 @@ gmbus_xfer_read_chunk(struct drm_i915_private *dev_priv,
} while (--len && ++loop < 4);
}
- return 0;
+ if (burst_read) {
+
+ /* Seq to disable the Burst Read */
+ I915_WRITE_FW(GMBUS0, (I915_READ_FW(GMBUS0) &
+ ~GMBUS_BYTE_CNT_OVERRIDE));
+ I915_WRITE_FW(GMBUS1, (I915_READ_FW(GMBUS1) &
+ ~GMBUS_CYCLE_MASK) | GMBUS_CYCLE_STOP);
+
+ /*
+ * On Burst read disable, GMBUS need more time to settle
+ * down to Idle State.
+ */
+ ret = intel_wait_for_register_fw(dev_priv, GMBUS2,
+ GMBUS_ACTIVE, 0, 50);
+ }
+
+ return ret;
}
static int
gmbus_xfer_read(struct drm_i915_private *dev_priv, struct i2c_msg *msg,
- u32 gmbus1_index)
+ u32 gmbus1_index, bool burst_read)
{
u8 *buf = msg->buf;
unsigned int rx_size = msg->len;
@@ -400,10 +426,13 @@ gmbus_xfer_read(struct drm_i915_private *dev_priv, struct i2c_msg *msg,
int ret;
do {
- len = min(rx_size, GMBUS_BYTE_COUNT_MAX);
+ if (burst_read)
+ len = rx_size;
+ else
+ len = min(rx_size, GMBUS_BYTE_COUNT_MAX);
- ret = gmbus_xfer_read_chunk(dev_priv, msg->addr,
- buf, len, gmbus1_index);
+ ret = gmbus_xfer_read_chunk(dev_priv, msg->addr, buf, len,
+ gmbus1_index, burst_read);
if (ret)
return ret;
@@ -491,7 +520,8 @@ gmbus_is_index_xfer(struct i2c_msg *msgs, int i, int num)
}
static int
-gmbus_index_xfer(struct drm_i915_private *dev_priv, struct i2c_msg *msgs)
+gmbus_index_xfer(struct drm_i915_private *dev_priv, struct i2c_msg *msgs,
+ bool burst_read)
{
u32 gmbus1_index = 0;
u32 gmbus5 = 0;
@@ -509,7 +539,8 @@ gmbus_index_xfer(struct drm_i915_private *dev_priv, struct i2c_msg *msgs)
I915_WRITE_FW(GMBUS5, gmbus5);
if (msgs[1].flags & I2C_M_RD)
- ret = gmbus_xfer_read(dev_priv, &msgs[1], gmbus1_index);
+ ret = gmbus_xfer_read(dev_priv, &msgs[1],
+ gmbus1_index, burst_read);
else
ret = gmbus_xfer_write(dev_priv, &msgs[1], gmbus1_index);
@@ -522,7 +553,7 @@ gmbus_index_xfer(struct drm_i915_private *dev_priv, struct i2c_msg *msgs)
static int
do_gmbus_xfer(struct i2c_adapter *adapter, struct i2c_msg *msgs, int num,
- u32 gmbus0_source)
+ u32 gmbus0_source, bool burst_read)
{
struct intel_gmbus *bus = container_of(adapter,
struct intel_gmbus,
@@ -544,15 +575,20 @@ do_gmbus_xfer(struct i2c_adapter *adapter, struct i2c_msg *msgs, int num,
for (; i < num; i += inc) {
inc = 1;
if (gmbus_is_index_xfer(msgs, i, num)) {
- ret = gmbus_index_xfer(dev_priv, &msgs[i]);
+ ret = gmbus_index_xfer(dev_priv, &msgs[i], burst_read);
inc = 2; /* an index transmission is two msgs */
} else if (msgs[i].flags & I2C_M_RD) {
- ret = gmbus_xfer_read(dev_priv, &msgs[i], 0);
+ ret = gmbus_xfer_read(dev_priv, &msgs[i],
+ 0, burst_read);
} else {
ret = gmbus_xfer_write(dev_priv, &msgs[i], 0);
}
- if (!ret)
+ /*
+ * Burst read Sequence ends with STOP. So Dont expect
+ * HW wait phase.
+ */
+ if (!ret && !burst_read)
ret = gmbus_wait(dev_priv,
GMBUS_HW_WAIT_PHASE, GMBUS_HW_WAIT_EN);
if (ret == -ETIMEDOUT)
@@ -664,7 +700,7 @@ gmbus_xfer(struct i2c_adapter *adapter, struct i2c_msg *msgs, int num)
if (ret < 0)
bus->force_bit &= ~GMBUS_FORCE_BIT_RETRY;
} else {
- ret = do_gmbus_xfer(adapter, msgs, num, 0);
+ ret = do_gmbus_xfer(adapter, msgs, num, 0, false);
if (ret == -EAGAIN)
bus->force_bit |= GMBUS_FORCE_BIT_RETRY;
}
@@ -705,7 +741,8 @@ int intel_gmbus_output_aksv(struct i2c_adapter *adapter)
* pass the i2c command, and tell GMBUS to use the HW-provided value
* instead of sourcing GMBUS3 for the data.
*/
- ret = do_gmbus_xfer(adapter, msgs, ARRAY_SIZE(msgs), GMBUS_AKSV_SELECT);
+ ret = do_gmbus_xfer(adapter, msgs, ARRAY_SIZE(msgs),
+ GMBUS_AKSV_SELECT, false);
mutex_unlock(&dev_priv->gmbus_mutex);
intel_display_power_put(dev_priv, POWER_DOMAIN_GMBUS);
@@ -713,6 +750,59 @@ int intel_gmbus_output_aksv(struct i2c_adapter *adapter)
return ret;
}
+static inline
+bool intel_gmbus_burst_read_supported(struct drm_i915_private *dev_priv)
+{
+ if (INTEL_GEN(dev_priv) > 10 || IS_GEMINILAKE(dev_priv) ||
+ IS_KABYLAKE(dev_priv))
+ return true;
+ return false;
+}
+
+int intel_gmbus_burst_read(struct i2c_adapter *adapter, unsigned int offset,
+ void *buf, size_t size)
+{
+ struct intel_gmbus *bus = container_of(adapter, struct intel_gmbus,
+ adapter);
+ struct drm_i915_private *dev_priv = bus->dev_priv;
+ int ret;
+ u8 start = offset & 0xff;
+ struct i2c_msg msgs[] = {
+ {
+ .addr = DRM_HDCP_DDC_ADDR,
+ .flags = 0,
+ .len = 1,
+ .buf = &start,
+ },
+ {
+ .addr = DRM_HDCP_DDC_ADDR,
+ .flags = I2C_M_RD,
+ .len = size,
+ .buf = buf,
+ }
+ };
+
+ if (!intel_gmbus_burst_read_supported(dev_priv))
+ return -EINVAL;
+
+ intel_display_power_get(dev_priv, POWER_DOMAIN_GMBUS);
+ mutex_lock(&dev_priv->gmbus_mutex);
+
+ /*
+ * In order to read the complete length(More than GMBus Limit) of data,
+ * in burst mode, implement the Workaround supported in HW.
+ */
+ ret = do_gmbus_xfer(adapter, msgs, ARRAY_SIZE(msgs), 0, true);
+
+ mutex_unlock(&dev_priv->gmbus_mutex);
+ intel_display_power_put(dev_priv, POWER_DOMAIN_GMBUS);
+
+ if (ret == ARRAY_SIZE(msgs))
+ return 0;
+
+ return ret >= 0 ? -EIO : ret;
+}
+
static u32 gmbus_func(struct i2c_adapter *adapter)
{
return i2c_bit_algo.functionality(adapter) &
--
2.7.4
Ramalingam C
2018-04-03 13:57:51 UTC
Permalink
Implements the HDMI adapatation specific HDCP2.2 operations.

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

v2:
Rebased.
v3:
No Changes.

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

diff --git a/drivers/gpu/drm/i915/intel_hdmi.c b/drivers/gpu/drm/i915/intel_hdmi.c
index b8b1086c0cbd..a974d3e2097a 100644
--- a/drivers/gpu/drm/i915/intel_hdmi.c
+++ b/drivers/gpu/drm/i915/intel_hdmi.c
@@ -30,6 +30,7 @@
#include <linux/slab.h>
#include <linux/delay.h>
#include <linux/hdmi.h>
+#include <linux/mei_hdcp.h>
#include <drm/drmP.h>
#include <drm/drm_atomic_helper.h>
#include <drm/drm_crtc.h>
@@ -1106,6 +1107,203 @@ bool intel_hdmi_hdcp_check_link(struct intel_digital_port *intel_dig_port)
return true;
}

+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 inline
+int intel_hdmi_hdcp2_timeout_for_msg(uint8_t msg_id, bool is_paired)
+{
+ int timeout = -EINVAL;
+
+ switch (msg_id) {
+ case HDCP_2_2_AKE_SEND_CERT:
+ timeout = HDCP_2_2_CERT_TIMEOUT;
+ break;
+ case HDCP_2_2_AKE_SEND_HPRIME:
+ if (is_paired)
+ timeout = HDCP_2_2_HPRIME_PAIRED_TIMEOUT;
+ else
+ timeout = HDCP_2_2_HPRIME_NO_PAIRED_TIMEOUT;
+ break;
+ case HDCP_2_2_AKE_SEND_PARING_INFO:
+ timeout = HDCP_2_2_PAIRING_TIMEOUT;
+ break;
+ case HDCP_2_2_LC_SEND_LPRIME:
+ timeout = HDCP_2_2_HDMI_LPRIME_TIMEOUT;
+ break;
+ case HDCP_2_2_REP_SEND_RECVID_LIST:
+ timeout = HDCP_2_2_RECVID_LIST_TIMEOUT;
+ break;
+ case HDCP_2_2_REP_STREAM_READY:
+ timeout = HDCP_2_2_STREAM_READY_TIMEOUT;
+ break;
+ default:
+ DRM_ERROR("Unsupported msg_id: %d\n", (int)msg_id);
+ }
+ return timeout;
+}
+
+static inline
+int hdcp2_detect_msg_availability(struct intel_digital_port *intel_digital_port,
+ uint8_t msg_id, bool *msg_ready,
+ ssize_t *msg_sz)
+{
+ uint8_t 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;
+}
+
+/**
+ * intel_hdmi_hdcp2_wait_for_msg: Detects the hdmi hdcp2.2 msg availability
+ * @hdcp: hdcp structure
+ * @msg_id: Message ID for which we are waiting
+ *
+ * Detects the HDMI HDCP2.2 Message availability
+ *
+ * Returns -ETIMEOUT in case of timeout, Message Size on success
+ */
+static ssize_t
+intel_hdmi_hdcp2_wait_for_msg(struct intel_digital_port *intel_dig_port,
+ uint8_t msg_id, bool paired)
+{
+ bool msg_ready = false;
+ int timeout, ret;
+ ssize_t msg_sz;
+
+ timeout = intel_hdmi_hdcp2_timeout_for_msg(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_ERROR("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,
+ uint8_t msg_id, void *buf, size_t size)
+{
+ struct intel_hdmi *hdmi = &intel_dig_port->hdmi;
+ struct intel_hdcp *hdcp = &hdmi->attached_connector->hdcp;
+ struct drm_i915_private *dev_priv;
+ struct i2c_adapter *adapter;
+ 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(%d) is more than exp size(%d)\n",
+ (int)ret, (int)size);
+ return -1;
+ }
+
+ offset = HDCP_2_2_HDMI_REG_RD_MSG_OFFSET;
+
+ if (msg_id == HDCP_2_2_AKE_SEND_CERT) {
+ dev_priv = intel_dig_port->base.base.dev->dev_private;
+ adapter = intel_gmbus_get_adapter(dev_priv, hdmi->ddc_bus);
+
+ ret = intel_gmbus_burst_read(adapter, offset, buf, ret);
+ } else {
+ ret = intel_hdmi_hdcp_read(intel_dig_port, offset, buf, ret);
+ }
+
+ if (ret)
+ DRM_DEBUG_KMS("msg_id: %d, ret: %d\n", msg_id, (int)ret);
+ return ret;
+}
+
+static
+int intel_hdmi_hdcp2_check_link(struct intel_digital_port *intel_dig_port)
+{
+ uint8_t rx_status[HDCP_2_2_HDMI_RXSTATUS_LEN];
+ int ret;
+
+ ret = intel_hdmi_hdcp2_read_rx_status(intel_dig_port, rx_status);
+ if (ret)
+ return ret;
+
+ /*
+ * Re-auth request and Link Integrity Failures are represented by
+ * same bit. i.e reauth_req.
+ */
+ if (HDCP_2_2_HDMI_RXSTATUS_REAUTH_REQ(rx_status[1]))
+ ret = DRM_HDCP_REAUTH_REQUEST;
+ else if (HDCP_2_2_HDMI_RXSTATUS_READY(rx_status[1]))
+ ret = DRM_HDCP_TOPOLOGY_CHANGE;
+
+ return ret;
+}
+
+static
+int intel_hdmi_hdcp2_capable(struct intel_digital_port *intel_dig_port,
+ bool *capable)
+{
+ uint8_t hdcp2version;
+ int ret;
+
+ *capable = false;
+ ret = intel_hdmi_hdcp_read(intel_dig_port, HDCP_2_2_HDMI_REG_VER_OFFSET,
+ &hdcp2version, sizeof(hdcp2version));
+ if (!ret)
+ if (hdcp2version & HDCP_2_2_HDMI_SUPPORT_MASK)
+ *capable = true;
+
+ return ret;
+}
+
+static
+enum hdcp_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,
@@ -1117,6 +1315,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,
+ .hdcp_protocol = intel_hdmi_hdcp2_protocol,
};

static void intel_hdmi_prepare(struct intel_encoder *encoder,
--
2.7.4
Ramalingam C
2018-04-03 13:57:50 UTC
Permalink
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.

Note: Chris Wilson suggested alternate method for waiting for CP_IRQ,
than completions concept. WIP to understand and implement that,
if needed. Just to unblock the review of other changes, v2 still
continues with completions.

v2:
wait for cp_irq is merged with this patch. Rebased.
v3:
wait_queue is used for wait for cp_irq [Chris Wilson]

Signed-off-by: Ramalingam C <***@intel.com>
---
drivers/gpu/drm/i915/intel_dp.c | 352 ++++++++++++++++++++++++++++++++++++++
drivers/gpu/drm/i915/intel_drv.h | 7 +
drivers/gpu/drm/i915/intel_hdcp.c | 5 +
3 files changed, 364 insertions(+)

diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
index f92c0326fff5..e5cb54ceda38 100644
--- a/drivers/gpu/drm/i915/intel_dp.c
+++ b/drivers/gpu/drm/i915/intel_dp.c
@@ -31,6 +31,7 @@
#include <linux/types.h>
#include <linux/notifier.h>
#include <linux/reboot.h>
+#include <linux/mei_hdcp.h>
#include <asm/byteorder.h>
#include <drm/drmP.h>
#include <drm/drm_atomic_helper.h>
@@ -5070,6 +5071,28 @@ void intel_dp_encoder_suspend(struct intel_encoder *intel_encoder)
pps_unlock(intel_dp);
}

+static int 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);
+ return 0;
+ } else if (!ret) {
+ return -ETIMEDOUT;
+ }
+ return (int)ret;
+}
+
+
static
int intel_dp_hdcp_write_an_aksv(struct intel_digital_port *intel_dig_port,
u8 *an)
@@ -5288,6 +5311,329 @@ int intel_dp_hdcp_capable(struct intel_digital_port *intel_dig_port,
return 0;
}

+static inline
+int intel_dpcd_offset_for_hdcp2_msgid(uint8_t byte, unsigned int *offset)
+{
+ switch (byte) {
+ case HDCP_2_2_AKE_INIT:
+ *offset = DP_HDCP_2_2_AKE_INIT_OFFSET;
+ break;
+ case HDCP_2_2_AKE_SEND_CERT:
+ *offset = DP_HDCP_2_2_AKE_SEND_CERT_OFFSET;
+ break;
+ case HDCP_2_2_AKE_NO_STORED_KM:
+ *offset = DP_HDCP_2_2_AKE_NO_STORED_KM_OFFSET;
+ break;
+ case HDCP_2_2_AKE_STORED_KM:
+ *offset = DP_HDCP_2_2_AKE_STORED_KM_OFFSET;
+ break;
+ case HDCP_2_2_AKE_SEND_HPRIME:
+ *offset = DP_HDCP_2_2_AKE_SEND_HPRIME_OFFSET;
+ break;
+ case HDCP_2_2_AKE_SEND_PARING_INFO:
+ *offset = DP_HDCP_2_2_AKE_SEND_PARING_INFO_OFFSET;
+ break;
+ case HDCP_2_2_LC_INIT:
+ *offset = DP_HDCP_2_2_LC_INIT_OFFSET;
+ break;
+ case HDCP_2_2_LC_SEND_LPRIME:
+ *offset = DP_HDCP_2_2_LC_SEND_LPRIME_OFFSET;
+ break;
+ case HDCP_2_2_SKE_SEND_EKS:
+ *offset = DP_HDCP_2_2_SKE_SEND_EKS_OFFSET;
+ break;
+ case HDCP_2_2_REP_SEND_RECVID_LIST:
+ *offset = DP_HDCP_2_2_REP_SEND_RECVID_LIST_OFFSET;
+ break;
+ case HDCP_2_2_REP_SEND_ACK:
+ *offset = DP_HDCP_2_2_REP_SEND_ACK_OFFSET;
+ break;
+ case HDCP_2_2_REP_STREAM_MANAGE:
+ *offset = DP_HDCP_2_2_REP_STREAM_MANAGE_OFFSET;
+ break;
+ case HDCP_2_2_REP_STREAM_READY:
+ *offset = DP_HDCP_2_2_REP_STREAM_READY_OFFSET;
+ break;
+ case HDCP_2_2_ERRATA_DP_STREAM_TYPE:
+ *offset = DP_HDCP_2_2_REG_STREAM_TYPE_OFFSET;
+ break;
+ default:
+ DRM_ERROR("Unrecognized Msg ID\n");
+ return -EINVAL;
+ }
+ return 0;
+}
+
+static inline
+int intel_dp_hdcp2_read_rx_status(struct intel_digital_port *intel_dig_port,
+ uint8_t *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_ERROR("Read bstatus from DP/AUX failed (%ld)\n", ret);
+ return ret >= 0 ? -EIO : ret;
+ }
+
+ return 0;
+}
+
+static inline
+int intel_dp_hdcp2_timeout_for_msg(uint8_t msg_id, bool paired)
+{
+ int timeout = -EINVAL;
+
+ switch (msg_id) {
+ case HDCP_2_2_AKE_SEND_CERT:
+ timeout = HDCP_2_2_CERT_TIMEOUT;
+ break;
+ case HDCP_2_2_AKE_SEND_HPRIME:
+ if (paired)
+ timeout = HDCP_2_2_HPRIME_PAIRED_TIMEOUT;
+ else
+ timeout = HDCP_2_2_HPRIME_NO_PAIRED_TIMEOUT;
+ break;
+ case HDCP_2_2_AKE_SEND_PARING_INFO:
+ timeout = HDCP_2_2_PAIRING_TIMEOUT;
+ break;
+ case HDCP_2_2_LC_SEND_LPRIME:
+ timeout = HDCP_2_2_DP_LPRIME_TIMEOUT;
+ break;
+ case HDCP_2_2_REP_SEND_RECVID_LIST:
+ timeout = HDCP_2_2_RECVID_LIST_TIMEOUT;
+ break;
+ case HDCP_2_2_REP_STREAM_READY:
+ timeout = HDCP_2_2_STREAM_READY_TIMEOUT;
+ break;
+ default:
+ DRM_ERROR("Unsupported msg_id: %d\n", (int)msg_id);
+ }
+ return timeout;
+}
+
+static inline
+int hdcp2_detect_msg_availability(struct intel_digital_port *intel_dig_port,
+ uint8_t msg_id, bool *msg_ready)
+{
+ uint8_t 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_PARING_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_DEBUG_KMS("Unidentified msg_id: %d\n", (int)msg_id);
+ return -EINVAL;
+ }
+ return 0;
+}
+
+
+static inline ssize_t
+intel_dp_hdcp2_wait_for_msg(struct intel_digital_port *intel_dig_port,
+ uint8_t msg_id)
+{
+ struct intel_dp *dp = &intel_dig_port->dp;
+ struct intel_hdcp *hdcp = &dp->attached_connector->hdcp;
+ int ret, timeout;
+ bool msg_ready = false;
+
+ timeout = intel_dp_hdcp2_timeout_for_msg(msg_id, hdcp->is_paired);
+ switch (msg_id) {
+
+ /*
+ * There is no way to detect the CERT, LPRIME and STREAM_READY
+ * availability. So Wait for timeout and read the msg.
+ */
+ case HDCP_2_2_AKE_SEND_CERT:
+ case HDCP_2_2_LC_SEND_LPRIME:
+ case HDCP_2_2_REP_STREAM_READY:
+ mdelay(timeout);
+ ret = 0;
+ break;
+ case HDCP_2_2_AKE_SEND_HPRIME:
+ case HDCP_2_2_AKE_SEND_PARING_INFO:
+ case HDCP_2_2_REP_SEND_RECVID_LIST:
+ 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;
+ break;
+ default:
+ DRM_DEBUG_KMS("Unidentified msg_id: %d\n", (int)msg_id);
+ return -EINVAL;
+ }
+ if (ret)
+ DRM_ERROR("msg_id %d, ret %d, timeout(mSec): %d\n", msg_id, ret,
+ timeout);
+ return ret;
+}
+
+static
+int intel_dp_hdcp2_write_msg(struct intel_digital_port *intel_dig_port,
+ void *buf, size_t size)
+{
+ unsigned int offset;
+ uint8_t *byte = buf;
+ ssize_t ret, bytes_to_write, len;
+
+ if (intel_dpcd_offset_for_hdcp2_msgid(*byte, &offset) < 0)
+ return -EINVAL;
+
+ /* 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
+int intel_dp_hdcp2_read_msg(struct intel_digital_port *intel_dig_port,
+ uint8_t msg_id, void *buf, size_t size)
+{
+ unsigned int offset, dev_cnt;
+ uint8_t *byte = buf;
+ uint8_t rx_info[HDCP_2_2_RXINFO_LEN];
+ ssize_t ret, bytes_to_recv, len;
+
+ if (intel_dpcd_offset_for_hdcp2_msgid(msg_id, &offset) < 0)
+ return -EINVAL;
+
+ ret = intel_dp_hdcp2_wait_for_msg(intel_dig_port, msg_id);
+ if (ret < 0)
+ return ret;
+
+ /* Finding the ReceiverID List size */
+ if (msg_id == HDCP_2_2_REP_SEND_RECVID_LIST) {
+ 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;
+
+ size = sizeof(struct hdcp2_rep_send_receiverid_list) -
+ HDCP_2_2_RECEIVER_IDS_MAX_LEN +
+ (dev_cnt * HDCP_2_2_RECEIVER_ID_LEN);
+ }
+
+ bytes_to_recv = size - 1;
+
+ /* To skip the msg_id, as msgs in DP adaptation 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 %d\n", msg_id, (int)ret);
+ return ret;
+ }
+
+ bytes_to_recv -= ret;
+ byte += ret;
+ offset += ret;
+ }
+ byte = buf;
+ *byte = msg_id;
+
+ return size;
+}
+
+static
+int intel_dp_hdcp2_config_stream_type(struct intel_digital_port *intel_dig_port,
+ void *buf, size_t size)
+{
+ return intel_dp_hdcp2_write_msg(intel_dig_port, buf, size);
+}
+
+static
+int intel_dp_hdcp2_check_link(struct intel_digital_port *intel_dig_port)
+{
+ uint8_t rx_status;
+ int ret;
+
+ ret = intel_dp_hdcp2_read_rx_status(intel_dig_port, &rx_status);
+ if (ret)
+ return ret;
+
+ if (HDCP_2_2_DP_RXSTATUS_REAUTH_REQ(rx_status))
+ ret = DRM_HDCP_REAUTH_REQUEST;
+ else if (HDCP_2_2_DP_RXSTATUS_LINK_FAILED(rx_status))
+ ret = DRM_HDCP_LINK_INTEGRITY_FAILURE;
+ else if (HDCP_2_2_DP_RXSTATUS_READY(rx_status))
+ ret = DRM_HDCP_TOPOLOGY_CHANGE;
+
+ return ret;
+}
+
+static
+int intel_dp_hdcp2_capable(struct intel_digital_port *intel_dig_port,
+ bool *capable)
+{
+ uint8_t 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_RXCAPS_VERSION_VAL &&
+ HDCP_2_2_DP_HDCP_CAPABLE(rx_caps[2]))
+ *capable = true;
+
+ return 0;
+}
+
+static
+enum hdcp_protocol intel_dp_hdcp2_protocol(void)
+{
+ return HDCP_PROTOCOL_DP;
+}
+
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,
@@ -5300,6 +5646,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,
+ .hdcp_protocol = intel_dp_hdcp2_protocol,
};

static void intel_edp_panel_vdd_sanitize(struct intel_dp *intel_dp)
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index 8e60ccd0d368..37f9a0e2ea13 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -444,6 +444,13 @@ struct intel_hdcp {
struct mei_hdcp_data mei_data;
struct notifier_block mei_cldev_nb;
struct delayed_work hdcp2_check_work;
+
+ /*
+ * 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 8cf0eeb4b3f8..9386b451191e 100644
--- a/drivers/gpu/drm/i915/intel_hdcp.c
+++ b/drivers/gpu/drm/i915/intel_hdcp.c
@@ -788,6 +788,8 @@ int intel_hdcp_init(struct intel_connector *connector,
if (hdcp2_supported)
intel_hdcp2_init(connector);

+ init_waitqueue_head(&hdcp->cp_irq_queue);
+ atomic_set(&hdcp->cp_irq_recved, 0);
return 0;
}

@@ -1762,4 +1764,7 @@ void intel_hdcp_handle_cp_irq(struct intel_connector *connector)
intel_hdcp_check_link(connector);
else if (intel_hdcp2_in_force(connector))
intel_hdcp2_check_link(connector);
+
+ atomic_set(&connector->hdcp.cp_irq_recved, 1);
+ wake_up_all(&connector->hdcp.cp_irq_queue);
}
--
2.7.4
kbuild test robot
2018-04-03 19:57:52 UTC
Permalink
Hi Ramalingam,

Thank you for the patch! Perhaps something to improve:

[auto build test WARNING on drm-intel/for-linux-next]
[also build test WARNING on next-20180403]
[cannot apply to v4.16]
[if your patch is applied to the wrong git tree, please drop us a note to help improve the system]

url: https://github.com/0day-ci/linux/commits/Ramalingam-C/drm-i915-Implement-HDCP2-2/20180404-031743
base: git://anongit.freedesktop.org/drm-intel for-linux-next
config: i386-randconfig-x071-201813 (attached as .config)
compiler: gcc-7 (Debian 7.3.0-1) 7.3.0
reproduce:
# save the attached .config to linux build tree
make ARCH=i386

All warnings (new ones prefixed by >>):

In file included from include/drm/drm_mm.h:49:0,
from include/drm/drmP.h:73,
drivers/gpu/drm/i915/intel_dp.c:5377:13: warning: format '%ld' expects argument of type 'long int', but argument 2 has type 'ssize_t {aka int}' [-Wformat=]
DRM_ERROR("Read bstatus from DP/AUX failed (%ld)\n", ret);
^
include/drm/drm_print.h:239:10: note: in definition of macro 'DRM_ERROR'
drm_err(fmt, ##__VA_ARGS__)
^~~
In file included from drivers/gpu/drm/i915/intel_dp.c:34:0:
At top level:
include/linux/mei_hdcp.h:148:12: warning: 'mei_cldev_unregister_notify' defined but not used [-Wunused-function]
static int mei_cldev_unregister_notify(struct notifier_block *nb)
^~~~~~~~~~~~~~~~~~~~~~~~~~~
include/linux/mei_hdcp.h:144:12: warning: 'mei_cldev_register_notify' defined but not used [-Wunused-function]
static int mei_cldev_register_notify(struct notifier_block *nb)
^~~~~~~~~~~~~~~~~~~~~~~~~

vim +5377 drivers/gpu/drm/i915/intel_dp.c

5366
5367 static inline
5368 int intel_dp_hdcp2_read_rx_status(struct intel_digital_port *intel_dig_port,
5369 uint8_t *rx_status)
5370 {
5371 ssize_t ret;
5372
5373 ret = drm_dp_dpcd_read(&intel_dig_port->dp.aux,
5374 DP_HDCP_2_2_REG_RXSTATUS_OFFSET, rx_status,
5375 HDCP_2_2_DP_RXSTATUS_LEN);
5376 if (ret != HDCP_2_2_DP_RXSTATUS_LEN) {
5377 DRM_ERROR("Read bstatus from DP/AUX failed (%ld)\n", ret);
5378 return ret >= 0 ? -EIO : ret;
5379 }
5380
5381 return 0;
5382 }
5383

---
0-DAY kernel test infrastructure Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all Intel Corporation
kbuild test robot
2018-04-03 21:16:17 UTC
Permalink
Hi Ramalingam,

Thank you for the patch! Perhaps something to improve:

[auto build test WARNING on drm-intel/for-linux-next]
[also build test WARNING on next-20180403]
[cannot apply to v4.16]
[if your patch is applied to the wrong git tree, please drop us a note to help improve the system]

url: https://github.com/0day-ci/linux/commits/Ramalingam-C/drm-i915-Implement-HDCP2-2/20180404-031743
base: git://anongit.freedesktop.org/drm-intel for-linux-next
config: i386-randconfig-a1-201813 (attached as .config)
compiler: gcc-4.9 (Debian 4.9.4-2) 4.9.4
reproduce:
# save the attached .config to linux build tree
make ARCH=i386
drivers/gpu//drm/i915/intel_dp.c:5377:3: warning: format '%ld' expects argument of type 'long int', but argument 2 has type 'ssize_t' [-Wformat=]
DRM_ERROR("Read bstatus from DP/AUX failed (%ld)\n", ret);
^
In file included from drivers/gpu//drm/i915/intel_dp.c:34:0:
drivers/gpu//drm/i915/intel_dp.c: At top level:
include/linux/mei_hdcp.h:144:12: warning: 'mei_cldev_register_notify' defined but not used [-Wunused-function]
static int mei_cldev_register_notify(struct notifier_block *nb)
^
include/linux/mei_hdcp.h:148:12: warning: 'mei_cldev_unregister_notify' defined but not used [-Wunused-function]
static int mei_cldev_unregister_notify(struct notifier_block *nb)
^
Cyclomatic Complexity 5 include/linux/compiler.h:__read_once_size
Cyclomatic Complexity 5 include/linux/compiler.h:__write_once_size
Cyclomatic Complexity 3 include/linux/string.h:memset
Cyclomatic Complexity 4 include/linux/string.h:memcpy
Cyclomatic Complexity 1 arch/x86/include/asm/bitops.h:ffs
Cyclomatic Complexity 1 arch/x86/include/asm/bitops.h:fls
Cyclomatic Complexity 1 include/linux/log2.h:__ilog2_u32
Cyclomatic Complexity 3 include/linux/log2.h:is_power_of_2
Cyclomatic Complexity 1 include/linux/list.h:INIT_LIST_HEAD
Cyclomatic Complexity 1 include/linux/err.h:ERR_PTR
Cyclomatic Complexity 1 arch/x86/include/asm/atomic.h:atomic_read
Cyclomatic Complexity 1 arch/x86/include/asm/atomic.h:atomic_set
Cyclomatic Complexity 1 include/asm-generic/atomic-long.h:atomic_long_read
Cyclomatic Complexity 1 include/asm-generic/getorder.h:__get_order
Cyclomatic Complexity 1 include/linux/mutex.h:__mutex_owner
Cyclomatic Complexity 1 include/linux/mutex.h:mutex_is_locked
Cyclomatic Complexity 1 include/linux/jiffies.h:_msecs_to_jiffies
Cyclomatic Complexity 3 include/linux/jiffies.h:msecs_to_jiffies
Cyclomatic Complexity 1 include/linux/jiffies.h:_usecs_to_jiffies
Cyclomatic Complexity 3 include/linux/jiffies.h:usecs_to_jiffies
Cyclomatic Complexity 1 include/linux/kasan.h:kasan_kmalloc
Cyclomatic Complexity 28 include/linux/slab.h:kmalloc_index
Cyclomatic Complexity 1 include/linux/slab.h:kmem_cache_alloc_trace
Cyclomatic Complexity 1 include/linux/slab.h:kmalloc_order_trace
Cyclomatic Complexity 67 include/linux/slab.h:kmalloc_large
Cyclomatic Complexity 5 include/linux/slab.h:kmalloc
Cyclomatic Complexity 1 include/linux/slab.h:kzalloc
Cyclomatic Complexity 1 include/linux/ww_mutex.h:ww_mutex_is_locked
Cyclomatic Complexity 1 include/drm/drm_modeset_lock.h:drm_modeset_is_locked
Cyclomatic Complexity 1 include/drm/drm_modeset_helper_vtables.h:drm_connector_helper_add
Cyclomatic Complexity 1 include/drm/drm_dp_helper.h:drm_dp_max_lane_count
Cyclomatic Complexity 3 include/drm/drm_dp_helper.h:drm_dp_enhanced_frame_cap
Cyclomatic Complexity 1 include/drm/drm_dp_helper.h:drm_dp_is_branch
Cyclomatic Complexity 1 include/drm/drm_dp_helper.h:drm_dp_has_quirk
Cyclomatic Complexity 1 drivers/gpu//drm/i915/i915_reg.h:i915_mmio_reg_offset
Cyclomatic Complexity 1 drivers/gpu//drm/i915/i915_reg.h:i915_mmio_reg_equal
Cyclomatic Complexity 1 drivers/gpu//drm/i915/i915_reg.h:i915_mmio_reg_valid
Cyclomatic Complexity 2 drivers/gpu//drm/i915/i915_utils.h:onoff
Cyclomatic Complexity 1 drivers/gpu//drm/i915/i915_drv.h:intel_info
Cyclomatic Complexity 1 drivers/gpu//drm/i915/i915_drv.h:msecs_to_jiffies_timeout
Cyclomatic Complexity 1 drivers/gpu//drm/i915/intel_drv.h:intel_get_crtc_for_pipe
Cyclomatic Complexity 1 drivers/gpu//drm/i915/intel_drv.h:intel_crtc_has_type
Cyclomatic Complexity 1 drivers/gpu//drm/i915/intel_drv.h:intel_crtc_has_dp_encoder
Cyclomatic Complexity 1 drivers/gpu//drm/i915/intel_drv.h:intel_dp_unused_lane_mask
Cyclomatic Complexity 3 drivers/gpu//drm/i915/intel_dp.c:intel_dp_rate_limit_len
Cyclomatic Complexity 1 drivers/gpu//drm/i915/intel_dp.c:intel_dp_common_len_rate_limit
Cyclomatic Complexity 1 drivers/gpu//drm/i915/intel_dp.c:intel_dp_max_common_rate
Cyclomatic Complexity 3 drivers/gpu//drm/i915/intel_dp.c:intel_dp_rate_index
Cyclomatic Complexity 3 drivers/gpu//drm/i915/intel_dp.c:intel_dp_unpack_aux
Cyclomatic Complexity 1 drivers/gpu//drm/i915/intel_dp.c:vlv_pipe_has_pp_on
Cyclomatic Complexity 1 drivers/gpu//drm/i915/intel_dp.c:vlv_pipe_has_vdd_on
Cyclomatic Complexity 1 drivers/gpu//drm/i915/intel_dp.c:vlv_pipe_any
Cyclomatic Complexity 4 drivers/gpu//drm/i915/intel_dp.c:vlv_initial_pps_pipe
Cyclomatic Complexity 1 drivers/gpu//drm/i915/intel_dp.c:skl_get_aux_clock_divider
Cyclomatic Complexity 2 drivers/gpu//drm/i915/intel_dp.c:skl_get_aux_send_ctl
Cyclomatic Complexity 1 drivers/gpu//drm/i915/intel_dp.c:intel_dp_aux_header
Cyclomatic Complexity 10 drivers/gpu//drm/i915/intel_dp.c:intel_edp_compare_alt_mode
Cyclomatic Complexity 4 drivers/gpu//drm/i915/intel_dp.c:downstream_hpd_needs_d0
Cyclomatic Complexity 7 drivers/gpu//drm/i915/intel_dp.c:gen4_signal_levels
Cyclomatic Complexity 1 drivers/gpu//drm/i915/intel_dp.c:intel_dp_autotest_phy_pattern
Cyclomatic Complexity 1 drivers/gpu//drm/i915/intel_dp.c:intel_dp_hdcp_toggle_signalling
Cyclomatic Complexity 1 drivers/gpu//drm/i915/intel_dp.c:intel_dp_hdcp2_protocol
Cyclomatic Complexity 2 drivers/gpu//drm/i915/intel_drv.h:dp_to_dig_port
Cyclomatic Complexity 1 drivers/gpu//drm/i915/intel_dp.c:intel_dp_to_dev
Cyclomatic Complexity 1 drivers/gpu//drm/i915/intel_drv.h:dp_to_lspcon
Cyclomatic Complexity 1 drivers/gpu//drm/i915/intel_dp.c:intel_dp_max_common_lane_count
Cyclomatic Complexity 15 drivers/gpu//drm/i915/intel_dp.c:intel_dpcd_offset_for_hdcp2_msgid
Cyclomatic Complexity 8 drivers/gpu//drm/i915/intel_dp.c:intel_dp_hdcp2_timeout_for_msg
Cyclomatic Complexity 1 include/linux/err.h:IS_ERR
Cyclomatic Complexity 3 include/linux/err.h:IS_ERR_OR_NULL
Cyclomatic Complexity 6 drivers/gpu//drm/i915/intel_dp.c:intersect_rates
Cyclomatic Complexity 6 drivers/gpu//drm/i915/intel_dp.c:intel_dp_set_common_rates
Cyclomatic Complexity 7 drivers/gpu//drm/i915/intel_dp.c:intel_aux_power_domain
Cyclomatic Complexity 4 drivers/gpu//drm/i915/intel_dp.c:assert_edp_pll
Cyclomatic Complexity 2 drivers/gpu//drm/i915/i915_drv.h:to_i915
Cyclomatic Complexity 6 drivers/gpu//drm/i915/intel_drv.h:enc_to_dig_port
Cyclomatic Complexity 1 drivers/gpu//drm/i915/intel_drv.h:enc_to_intel_dp
Cyclomatic Complexity 8 drivers/gpu//drm/i915/intel_dp.c:intel_dp_set_clock
Cyclomatic Complexity 5 drivers/gpu//drm/i915/intel_dp.c:gm45_digital_port_connected
Cyclomatic Complexity 5 drivers/gpu//drm/i915/intel_dp.c:g4x_digital_port_connected
Cyclomatic Complexity 5 drivers/gpu//drm/i915/intel_dp.c:ibx_digital_port_connected
Cyclomatic Complexity 2 drivers/gpu//drm/i915/intel_dp.c:ilk_digital_port_connected
Cyclomatic Complexity 5 drivers/gpu//drm/i915/intel_dp.c:cpt_digital_port_connected
Cyclomatic Complexity 2 drivers/gpu//drm/i915/intel_dp.c:snb_digital_port_connected
Cyclomatic Complexity 2 drivers/gpu//drm/i915/intel_dp.c:ivb_digital_port_connected
Cyclomatic Complexity 2 drivers/gpu//drm/i915/intel_dp.c:bdw_digital_port_connected
Cyclomatic Complexity 5 drivers/gpu//drm/i915/intel_dp.c:bxt_digital_port_connected
Cyclomatic Complexity 3 drivers/gpu//drm/i915/intel_dp.c:spt_digital_port_connected
Cyclomatic Complexity 3 drivers/gpu//drm/i915/intel_dp.c:vlv_active_pipe
Cyclomatic Complexity 5 drivers/gpu//drm/i915/intel_dp.c:cnl_max_source_rate

vim +5377 drivers/gpu//drm/i915/intel_dp.c

5366
5367 static inline
5368 int intel_dp_hdcp2_read_rx_status(struct intel_digital_port *intel_dig_port,
5369 uint8_t *rx_status)
5370 {
5371 ssize_t ret;
5372
5373 ret = drm_dp_dpcd_read(&intel_dig_port->dp.aux,
5374 DP_HDCP_2_2_REG_RXSTATUS_OFFSET, rx_status,
5375 HDCP_2_2_DP_RXSTATUS_LEN);
5376 if (ret != HDCP_2_2_DP_RXSTATUS_LEN) {
5377 DRM_ERROR("Read bstatus from DP/AUX failed (%ld)\n", ret);
5378 return ret >= 0 ? -EIO : ret;
5379 }
5380
5381 return 0;
5382 }
5383

---
0-DAY kernel test infrastructure Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all Intel Corporation
Ramalingam C
2018-04-03 13:57:52 UTC
Permalink
On DP connector init, intel_hdcp_init is passed with a flag for hdcp2.2
support based on the platform capability.

v2:
Rebased.
v3:
No Changes.

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

diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
index e5cb54ceda38..43318003ce14 100644
--- a/drivers/gpu/drm/i915/intel_dp.c
+++ b/drivers/gpu/drm/i915/intel_dp.c
@@ -6733,7 +6733,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");
}
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index 37f9a0e2ea13..2bb562738964 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -1941,6 +1941,7 @@ int intel_hdcp_enable(struct intel_connector *connector);
int intel_hdcp_disable(struct intel_connector *connector);
bool is_hdcp_supported(struct drm_i915_private *dev_priv, enum port port);
void intel_hdcp_handle_cp_irq(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 9386b451191e..9d5cade3b236 100644
--- a/drivers/gpu/drm/i915/intel_hdcp.c
+++ b/drivers/gpu/drm/i915/intel_hdcp.c
@@ -1723,7 +1723,6 @@ static int mei_cldev_notify(struct notifier_block *nb, unsigned long event,
return NOTIFY_OK;
}

-static inline
bool is_hdcp2_supported(struct drm_i915_private *dev_priv)
{
return (INTEL_GEN(dev_priv) >= 10 || IS_GEMINILAKE(dev_priv) ||
--
2.7.4
Ramalingam C
2018-04-03 13:57:53 UTC
Permalink
On HDMI connector init, intel_hdcp_init is passed with a flag for hdcp2.2
support based on the platform capability.

v2:
Rebased.
v3:
No Changes.

Signed-off-by: Ramalingam C <***@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 a974d3e2097a..29689269dc80 100644
--- a/drivers/gpu/drm/i915/intel_hdmi.c
+++ b/drivers/gpu/drm/i915/intel_hdmi.c
@@ -2545,7 +2545,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
Patchwork
2018-04-03 14:26:50 UTC
Permalink
== Series Details ==

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

== Summary ==

CHK include/config/kernel.release
CHK include/generated/uapi/linux/version.h
CHK include/generated/utsrelease.h
CHK include/generated/bounds.h
CHK include/generated/timeconst.h
CHK include/generated/asm-offsets.h
CALL scripts/checksyscalls.sh
DESCEND objtool
CHK scripts/mod/devicetable-offsets.h
CHK include/generated/compile.h
CHK kernel/config_data.h
CC [M] drivers/gpu/drm/i915/i915_drv.o
In file included from drivers/gpu/drm/i915/intel_drv.h:32:0,
from drivers/gpu/drm/i915/i915_trace.h:11,
from drivers/gpu/drm/i915/i915_drv.h:2657,
from drivers/gpu/drm/i915/i915_drv.c:49:
./include/linux/mei_hdcp.h:148:12: error: ‘mei_cldev_unregister_notify’ defined but not used [-Werror=unused-function]
static int mei_cldev_unregister_notify(struct notifier_block *nb)
^~~~~~~~~~~~~~~~~~~~~~~~~~~
./include/linux/mei_hdcp.h:144:12: error: ‘mei_cldev_register_notify’ defined but not used [-Werror=unused-function]
static int mei_cldev_register_notify(struct notifier_block *nb)
^~~~~~~~~~~~~~~~~~~~~~~~~
cc1: all warnings being treated as errors
scripts/Makefile.build:324: recipe for target 'drivers/gpu/drm/i915/i915_drv.o' failed
make[4]: *** [drivers/gpu/drm/i915/i915_drv.o] Error 1
scripts/Makefile.build:583: recipe for target 'drivers/gpu/drm/i915' failed
make[3]: *** [drivers/gpu/drm/i915] Error 2
scripts/Makefile.build:583: recipe for target 'drivers/gpu/drm' failed
make[2]: *** [drivers/gpu/drm] Error 2
scripts/Makefile.build:583: recipe for target 'drivers/gpu' failed
make[1]: *** [drivers/gpu] Error 2
Makefile:1060: recipe for target 'drivers' failed
make: *** [drivers] Error 2
Loading...