On Thu, Jan 31, 2019 at 12:29:23PM +0530, Ramalingam C wrote:
> "hdcp_encrypted" flag is defined to denote the HDCP1.4 encryption status.
> This SW tracking is used to determine the need for real hdcp1.4 disable
> and hdcp_check_link upon CP_IRQ.
> 
> On CP_IRQ we filter the CP_IRQ related to the states like Link failure
> and reauthentication req etc and handle them in hdcp_check_link.
> CP_IRQ corresponding to the authentication msg availability are ignored.
> 
> WARN_ON is added for the abrupt stop of HDCP encryption of a port.
> 
> v2:
>   bool is used in struct for the cleaner coding. [Daniel]
>   check_link work_fn is scheduled for cp_irq handling [Daniel]

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

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

> 
> Signed-off-by: Ramalingam C <ramalinga...@intel.com>
> ---
>  drivers/gpu/drm/i915/intel_dp.c   |  2 +-
>  drivers/gpu/drm/i915/intel_drv.h  |  5 ++-
>  drivers/gpu/drm/i915/intel_hdcp.c | 73 
> ++++++++++++++++++++++++++++-----------
>  3 files changed, 58 insertions(+), 22 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
> index 815ee68efa2f..9ce05819fc11 100644
> --- a/drivers/gpu/drm/i915/intel_dp.c
> +++ b/drivers/gpu/drm/i915/intel_dp.c
> @@ -4776,7 +4776,7 @@ static void intel_dp_check_service_irq(struct intel_dp 
> *intel_dp)
>               intel_dp_handle_test_request(intel_dp);
>  
>       if (val & DP_CP_IRQ)
> -             intel_hdcp_check_link(intel_dp->attached_connector);
> +             intel_hdcp_handle_cp_irq(intel_dp->attached_connector);
>  
>       if (val & DP_SINK_SPECIFIC_IRQ)
>               DRM_DEBUG_DRIVER("Sink specific irq unhandled\n");
> diff --git a/drivers/gpu/drm/i915/intel_drv.h 
> b/drivers/gpu/drm/i915/intel_drv.h
> index 63e009286d5f..13a41e8cf4ff 100644
> --- a/drivers/gpu/drm/i915/intel_drv.h
> +++ b/drivers/gpu/drm/i915/intel_drv.h
> @@ -399,6 +399,9 @@ struct intel_hdcp {
>       struct delayed_work check_work;
>       struct work_struct prop_work;
>  
> +     /* HDCP1.4 Encryption status */
> +     bool hdcp_encrypted;
> +
>       /* HDCP2.2 related definitions */
>       /* Flag indicates whether this connector supports HDCP2.2 or not. */
>       bool hdcp2_supported;
> @@ -2073,10 +2076,10 @@ int intel_hdcp_init(struct intel_connector *connector,
>                   bool hdcp2_supported);
>  int intel_hdcp_enable(struct intel_connector *connector);
>  int intel_hdcp_disable(struct intel_connector *connector);
> -int intel_hdcp_check_link(struct intel_connector *connector);
>  bool is_hdcp_supported(struct drm_i915_private *dev_priv, enum port port);
>  bool intel_hdcp_capable(struct intel_connector *connector);
>  bool is_hdcp2_supported(struct drm_i915_private *dev_priv);
> +void intel_hdcp_handle_cp_irq(struct intel_connector *connector);
>  
>  /* intel_psr.c */
>  #define CAN_PSR(dev_priv) (HAS_PSR(dev_priv) && dev_priv->psr.sink_support)
> diff --git a/drivers/gpu/drm/i915/intel_hdcp.c 
> b/drivers/gpu/drm/i915/intel_hdcp.c
> index e0bb5f32ba90..c1b057f1501b 100644
> --- a/drivers/gpu/drm/i915/intel_hdcp.c
> +++ b/drivers/gpu/drm/i915/intel_hdcp.c
> @@ -74,6 +74,16 @@ bool intel_hdcp_capable(struct intel_connector *connector)
>       return capable;
>  }
>  
> +static inline bool intel_hdcp_in_use(struct intel_connector *connector)
> +{
> +     struct drm_i915_private *dev_priv = to_i915(connector->base.dev);
> +     enum port port = connector->encoder->port;
> +     u32 reg;
> +
> +     reg = I915_READ(PORT_HDCP_STATUS(port));
> +     return reg & HDCP_STATUS_ENC;
> +}
> +
>  static int intel_hdcp_poll_ksv_fifo(struct intel_digital_port 
> *intel_dig_port,
>                                   const struct intel_hdcp_shim *shim)
>  {
> @@ -668,6 +678,7 @@ static int _intel_hdcp_disable(struct intel_connector 
> *connector)
>       DRM_DEBUG_KMS("[%s:%d] HDCP is being disabled...\n",
>                     connector->base.name, connector->base.base.id);
>  
> +     hdcp->hdcp_encrypted = false;
>       I915_WRITE(PORT_HDCP_CONF(port), 0);
>       if (intel_wait_for_register(dev_priv, PORT_HDCP_STATUS(port), ~0, 0,
>                                   ENCRYPT_STATUS_CHANGE_TIMEOUT_MS)) {
> @@ -713,8 +724,10 @@ static int _intel_hdcp_enable(struct intel_connector 
> *connector)
>       /* Incase of authentication failures, HDCP spec expects reauth. */
>       for (i = 0; i < tries; i++) {
>               ret = intel_hdcp_auth(conn_to_dig_port(connector), hdcp->shim);
> -             if (!ret)
> +             if (!ret) {
> +                     hdcp->hdcp_encrypted = true;
>                       return 0;
> +             }
>  
>               DRM_DEBUG_KMS("HDCP Auth failure (%d)\n", ret);
>  
> @@ -741,16 +754,17 @@ int intel_hdcp_check_link(struct intel_connector 
> *connector)
>       enum port port = intel_dig_port->base.port;
>       int ret = 0;
>  
> -     if (!hdcp->shim)
> -             return -ENOENT;
> -
>       mutex_lock(&hdcp->mutex);
>  
> -     if (hdcp->value == DRM_MODE_CONTENT_PROTECTION_UNDESIRED)
> +     /* Check_link valid only when HDCP1.4 is enabled */
> +     if (hdcp->value != DRM_MODE_CONTENT_PROTECTION_ENABLED ||
> +         !hdcp->hdcp_encrypted) {
> +             ret = -EINVAL;
>               goto out;
> +     }
>  
> -     if (!(I915_READ(PORT_HDCP_STATUS(port)) & HDCP_STATUS_ENC)) {
> -             DRM_ERROR("%s:%d HDCP check failed: link is not encrypted,%x\n",
> +     if (WARN_ON(!intel_hdcp_in_use(connector))) {
> +             DRM_ERROR("%s:%d HDCP link stopped encryption,%x\n",
>                         connector->base.name, connector->base.base.id,
>                         I915_READ(PORT_HDCP_STATUS(port)));
>               ret = -ENXIO;
> @@ -791,18 +805,6 @@ int intel_hdcp_check_link(struct intel_connector 
> *connector)
>       return ret;
>  }
>  
> -static void intel_hdcp_check_work(struct work_struct *work)
> -{
> -     struct intel_hdcp *hdcp = container_of(to_delayed_work(work),
> -                                            struct intel_hdcp,
> -                                            check_work);
> -     struct intel_connector *connector = intel_hdcp_to_connector(hdcp);
> -
> -     if (!intel_hdcp_check_link(connector))
> -             schedule_delayed_work(&hdcp->check_work,
> -                                   DRM_HDCP_CHECK_PERIOD_MS);
> -}
> -
>  static void intel_hdcp_prop_work(struct work_struct *work)
>  {
>       struct intel_hdcp *hdcp = container_of(work, struct intel_hdcp,
> @@ -1120,6 +1122,18 @@ int hdcp2_deauthenticate_port(struct intel_connector 
> *connector)
>       return hdcp2_close_mei_session(connector);
>  }
>  
> +static void intel_hdcp_check_work(struct work_struct *work)
> +{
> +     struct intel_hdcp *hdcp = container_of(to_delayed_work(work),
> +                                            struct intel_hdcp,
> +                                            check_work);
> +     struct intel_connector *connector = intel_hdcp_to_connector(hdcp);
> +
> +     if (!intel_hdcp_check_link(connector))
> +             schedule_delayed_work(&hdcp->check_work,
> +                                   DRM_HDCP_CHECK_PERIOD_MS);
> +}
> +
>  static int i915_hdcp_component_bind(struct device *i915_kdev,
>                                   struct device *mei_kdev, void *data)
>  {
> @@ -1288,7 +1302,8 @@ int intel_hdcp_disable(struct intel_connector 
> *connector)
>  
>       if (hdcp->value != DRM_MODE_CONTENT_PROTECTION_UNDESIRED) {
>               hdcp->value = DRM_MODE_CONTENT_PROTECTION_UNDESIRED;
> -             ret = _intel_hdcp_disable(connector);
> +             if (hdcp->hdcp_encrypted)
> +                     ret = _intel_hdcp_disable(connector);
>       }
>  
>       mutex_unlock(&hdcp->mutex);
> @@ -1328,3 +1343,21 @@ void intel_hdcp_atomic_check(struct drm_connector 
> *connector,
>                                                  new_state->crtc);
>       crtc_state->mode_changed = true;
>  }
> +
> +/* Handles the CP_IRQ raised from the DP HDCP sink */
> +void intel_hdcp_handle_cp_irq(struct intel_connector *connector)
> +{
> +     struct intel_hdcp *hdcp = &connector->hdcp;
> +
> +     if (!hdcp->shim)
> +             return;
> +
> +     /*
> +      * CP_IRQ could be triggered due to 1. HDCP2.2 auth msgs availability,
> +      * 2. link failure and 3. repeater reauth request. At present we dont
> +      * handle the CP_IRQ for the HDCP2.2 auth msg availability for read.
> +      * To handle other two causes for CP_IRQ we have the work_fn which is
> +      * scheduled here.
> +      */
> +     schedule_delayed_work(&hdcp->check_work, 0);
> +}
> -- 
> 2.7.4
> 

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

Reply via email to