From patchwork Wed Jun 27 08:40:06 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ramalingam C X-Patchwork-Id: 10490905 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id EB60160230 for ; Wed, 27 Jun 2018 08:52:03 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id D9C181FE8A for ; Wed, 27 Jun 2018 08:52:03 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id CDAE8285EC; Wed, 27 Jun 2018 08:52:03 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-5.2 required=2.0 tests=BAYES_00, MAILING_LIST_MULTI, RCVD_IN_DNSWL_MED autolearn=ham version=3.3.1 Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) (using TLSv1.2 with cipher DHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id 62F3F1FE8A for ; Wed, 27 Jun 2018 08:52:03 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id 3F8EA6E7C4; Wed, 27 Jun 2018 08:50:55 +0000 (UTC) X-Original-To: intel-gfx@lists.freedesktop.org Delivered-To: intel-gfx@lists.freedesktop.org Received: from mga12.intel.com (mga12.intel.com [192.55.52.136]) by gabe.freedesktop.org (Postfix) with ESMTPS id 812156E7B2; Wed, 27 Jun 2018 08:50:50 +0000 (UTC) X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from orsmga004.jf.intel.com ([10.7.209.38]) by fmsmga106.fm.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 27 Jun 2018 01:50:50 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.51,278,1526367600"; d="scan'208";a="211536010" Received: from mint-dev.iind.intel.com ([10.223.25.164]) by orsmga004.jf.intel.com with ESMTP; 27 Jun 2018 01:50:33 -0700 From: Ramalingam C To: intel-gfx@lists.freedesktop.org, dri-devel@lists.freedesktop.org, daniel@ffwll.ch, tomas.winkler@intel.com, alexander.usyskin@intel.com, uma.shankar@intel.com Date: Wed, 27 Jun 2018 14:10:06 +0530 Message-Id: <1530088829-11730-18-git-send-email-ramalingam.c@intel.com> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1530088829-11730-1-git-send-email-ramalingam.c@intel.com> References: <1530088829-11730-1-git-send-email-ramalingam.c@intel.com> Subject: [Intel-gfx] [PATCH v5 17/40] drm/i915: Implement HDCP2.2 link integrity check X-BeenThere: intel-gfx@lists.freedesktop.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: Intel graphics driver community testing & development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Errors-To: intel-gfx-bounces@lists.freedesktop.org Sender: "Intel-gfx" X-Virus-Scanned: ClamAV using ClamSMTP 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. v4: enum check_link_response is used check the link status [Uma] v5: Rebased as part of patch reordering. Signed-off-by: Ramalingam C --- drivers/gpu/drm/i915/intel_hdcp.c | 82 +++++++++++++++++++++++++++++++++++++++ include/drm/drm_hdcp.h | 8 ++++ 2 files changed, 90 insertions(+) diff --git a/drivers/gpu/drm/i915/intel_hdcp.c b/drivers/gpu/drm/i915/intel_hdcp.c index cf1c5f20b62e..ec840c1178bb 100644 --- a/drivers/gpu/drm/i915/intel_hdcp.c +++ b/drivers/gpu/drm/i915/intel_hdcp.c @@ -25,6 +25,8 @@ static int intel_hdcp2_init(struct intel_connector *connector); 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_read_valid_bksv(struct intel_digital_port *intel_dig_port, const struct intel_hdcp_shim *shim, u8 *bksv); @@ -841,6 +843,7 @@ 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) @@ -1709,6 +1712,8 @@ static int _intel_hdcp2_enable(struct intel_connector *connector) hdcp->hdcp2_in_use = true; 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; } @@ -1914,3 +1919,80 @@ static int intel_hdcp2_init(struct intel_connector *connector) exit: return ret; } + +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 == DRM_HDCP_LINK_PROTECTED) { + 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_ERROR("[%s:%d] HDCP2.2 link failed, retrying auth\n", + connector->base.name, connector->base.base.id); + + ret = _intel_hdcp2_disable(connector); + if (ret) { + DRM_ERROR("[%s:%d] Failed to disable hdcp2.2 (%d)\n", + connector->base.name, connector->base.base.id, ret); + + hdcp->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 0c222b5b685c..76c84d60202f 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