Message ID | 20190405084302.5548-14-ramalingam.c@intel.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | HDCP2.2 Phase II | expand |
On 2019-04-05 at 14:13:02 +0530, Ramalingam C wrote: > Implements drm blob property content_protection_downstream_info > property on HDCP capable connectors. > > Downstream topology info is gathered across authentication stages > and stored in intel_hdcp. When HDCP authentication is complete, > new blob with latest downstream topology information is updated to > content_protection_downstream_info property. > > v2: > %s/cp_downstream/content_protection_downstream [daniel] > v3: > %s/content_protection_downstream/hdcp_topology [daniel] > v4: > Rebased. Daniel, Hope I have done enough explicit padding struct hdcp_topology_info. Please correct me if i am still missing something. For populating the structure for the blob, as you sugegsted this patch is not using the separate functions. IMHO I feel usage is very minimal, separate functions might not be justified here. Hope you are fine with that. -Ram > > Signed-off-by: Ramalingam C <ramalingam.c@intel.com> > --- > drivers/gpu/drm/i915/intel_drv.h | 2 + > drivers/gpu/drm/i915/intel_hdcp.c | 87 ++++++++++++++++++++++++++----- > include/drm/drm_hdcp.h | 1 + > 3 files changed, 76 insertions(+), 14 deletions(-) > > diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h > index e387e842f414..6a321a56ce42 100644 > --- a/drivers/gpu/drm/i915/intel_drv.h > +++ b/drivers/gpu/drm/i915/intel_drv.h > @@ -482,6 +482,8 @@ struct intel_hdcp { > wait_queue_head_t cp_irq_queue; > atomic_t cp_irq_count; > int cp_irq_count_cached; > + > + struct hdcp_topology_info *topology_info; > }; > > struct intel_connector { > diff --git a/drivers/gpu/drm/i915/intel_hdcp.c b/drivers/gpu/drm/i915/intel_hdcp.c > index f70f1e98e4ae..6993bb9ecd0b 100644 > --- a/drivers/gpu/drm/i915/intel_hdcp.c > +++ b/drivers/gpu/drm/i915/intel_hdcp.c > @@ -490,9 +490,10 @@ int intel_hdcp_validate_v_prime(struct intel_digital_port *intel_dig_port, > > /* Implements Part 2 of the HDCP authorization procedure */ > static > -int intel_hdcp_auth_downstream(struct intel_digital_port *intel_dig_port, > - const struct intel_hdcp_shim *shim) > +int intel_hdcp_auth_downstream(struct intel_hdcp *hdcp, > + struct intel_digital_port *intel_dig_port) > { > + const struct intel_hdcp_shim *shim = hdcp->shim; > u8 bstatus[2], num_downstream, *ksv_fifo; > int ret, i, tries = 3; > > @@ -523,6 +524,9 @@ int intel_hdcp_auth_downstream(struct intel_digital_port *intel_dig_port, > if (num_downstream == 0) > return -EINVAL; > > + hdcp->topology_info->device_count = num_downstream; > + hdcp->topology_info->depth = DRM_HDCP_DEPTH(bstatus[1]); > + > ksv_fifo = kcalloc(DRM_HDCP_KSV_LEN, num_downstream, GFP_KERNEL); > if (!ksv_fifo) > return -ENOMEM; > @@ -536,6 +540,8 @@ int intel_hdcp_auth_downstream(struct intel_digital_port *intel_dig_port, > return -EPERM; > } > > + memcpy(hdcp->topology_info->ksv_list, ksv_fifo, > + num_downstream * DRM_HDCP_KSV_LEN); > /* > * When V prime mismatches, DP Spec mandates re-read of > * V prime atleast twice. > @@ -562,9 +568,11 @@ int intel_hdcp_auth_downstream(struct intel_digital_port *intel_dig_port, > } > > /* Implements Part 1 of the HDCP authorization procedure */ > -static int intel_hdcp_auth(struct intel_digital_port *intel_dig_port, > - const struct intel_hdcp_shim *shim) > +static int intel_hdcp_auth(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->shim; > struct drm_i915_private *dev_priv; > enum port port; > unsigned long r0_prime_gen_start; > @@ -635,15 +643,20 @@ static int intel_hdcp_auth(struct intel_digital_port *intel_dig_port, > return -EPERM; > } > > + hdcp->topology_info->ver_in_force = DRM_MODE_HDCP14_IN_FORCE; > + memcpy(hdcp->topology_info->bksv, bksv.shim, DRM_MODE_HDCP_KSV_LEN); > + > I915_WRITE(PORT_HDCP_BKSVLO(port), bksv.reg[0]); > I915_WRITE(PORT_HDCP_BKSVHI(port), bksv.reg[1]); > > ret = shim->repeater_present(intel_dig_port, &repeater_present); > if (ret) > return ret; > - if (repeater_present) > + if (repeater_present) { > I915_WRITE(HDCP_REP_CTL, > intel_hdcp_get_repeater_ctl(intel_dig_port)); > + hdcp->topology_info->is_repeater = true; > + } > > ret = shim->toggle_signalling(intel_dig_port, true); > if (ret) > @@ -708,7 +721,7 @@ static int intel_hdcp_auth(struct intel_digital_port *intel_dig_port, > */ > > if (repeater_present) > - return intel_hdcp_auth_downstream(intel_dig_port, shim); > + return intel_hdcp_auth_downstream(hdcp, intel_dig_port); > > DRM_DEBUG_KMS("HDCP is enabled (no repeater present)\n"); > return 0; > @@ -739,13 +752,18 @@ static int _intel_hdcp_disable(struct intel_connector *connector) > return ret; > } > > + memset(hdcp->topology_info, 0, sizeof(struct hdcp_topology_info)); > + > + if (drm_connector_update_hdcp_topology_property(&connector->base, > + connector->hdcp.topology_info)) > + DRM_ERROR("Downstream_info update failed.\n"); > + > DRM_DEBUG_KMS("HDCP is disabled\n"); > return 0; > } > > 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; > > @@ -770,9 +788,13 @@ 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); > + ret = intel_hdcp_auth(connector); > if (!ret) { > - hdcp->hdcp_encrypted = true; > + connector->hdcp.hdcp_encrypted = true; > + if (drm_connector_update_hdcp_topology_property( > + &connector->base, > + connector->hdcp.topology_info)) > + DRM_ERROR("Downstream_info update failed.\n"); > return 0; > } > > @@ -1206,6 +1228,12 @@ static int hdcp2_authentication_key_exchange(struct intel_connector *connector) > return -EPERM; > } > > + hdcp->topology_info->ver_in_force = DRM_MODE_HDCP22_IN_FORCE; > + hdcp->topology_info->content_type = hdcp->content_type; > + memcpy(hdcp->topology_info->bksv, msgs.send_cert.cert_rx.receiver_id, > + HDCP_2_2_RECEIVER_ID_LEN); > + hdcp->topology_info->is_repeater = hdcp->is_repeater; > + > /* > * Here msgs.no_stored_km will hold msgs corresponding to the km > * stored also. > @@ -1397,6 +1425,11 @@ int hdcp2_authenticate_repeater_topology(struct intel_connector *connector) > return -EPERM; > } > > + hdcp->topology_info->device_count = device_cnt; > + hdcp->topology_info->depth = HDCP_2_2_DEPTH(rx_info[0]); > + memcpy(hdcp->topology_info->ksv_list, msgs.recvid_list.receiver_ids, > + device_cnt * HDCP_2_2_RECEIVER_ID_LEN); > + > ret = hdcp2_verify_rep_topology_prepare_ack(connector, > &msgs.recvid_list, > &msgs.rep_ack); > @@ -1583,6 +1616,12 @@ static int _intel_hdcp2_enable(struct intel_connector *connector) > if (ret) { > DRM_DEBUG_KMS("HDCP2 Type%d Enabling Failed. (%d)\n", > hdcp->content_type, ret); > + > + memset(hdcp->topology_info, 0, > + sizeof(struct hdcp_topology_info)); > + drm_connector_update_hdcp_topology_property(&connector->base, > + hdcp->topology_info); > + > return ret; > } > > @@ -1590,12 +1629,16 @@ static int _intel_hdcp2_enable(struct intel_connector *connector) > connector->base.name, connector->base.base.id, > hdcp->content_type); > > + drm_connector_update_hdcp_topology_property(&connector->base, > + hdcp->topology_info); > hdcp->hdcp2_encrypted = true; > + > return 0; > } > > static int _intel_hdcp2_disable(struct intel_connector *connector) > { > + struct intel_hdcp *hdcp = &connector->hdcp; > int ret; > > DRM_DEBUG_KMS("[%s:%d] HDCP2.2 is being Disabled\n", > @@ -1606,8 +1649,11 @@ static int _intel_hdcp2_disable(struct intel_connector *connector) > if (hdcp2_deauthenticate_port(connector) < 0) > DRM_DEBUG_KMS("Port deauth failed.\n"); > > - connector->hdcp.hdcp2_encrypted = false; > + hdcp->hdcp2_encrypted = false; > > + memset(hdcp->topology_info, 0, sizeof(struct hdcp_topology_info)); > + drm_connector_update_hdcp_topology_property(&connector->base, > + hdcp->topology_info); > return ret; > } > > @@ -1824,10 +1870,17 @@ int intel_hdcp_init(struct intel_connector *connector, > ret = > drm_connector_attach_content_protection_property(&connector->base, > hdcp->hdcp2_supported); > - if (ret) { > - hdcp->hdcp2_supported = false; > - kfree(hdcp->port_data.streams); > - return ret; > + if (ret) > + goto err_exit; > + > + ret = drm_connector_attach_hdcp_topology_property(&connector->base); > + if (ret) > + goto err_exit; > + > + hdcp->topology_info = kzalloc(sizeof(*hdcp->topology_info), GFP_KERNEL); > + if (!hdcp->topology_info) { > + ret = -ENOMEM; > + goto err_exit; > } > > hdcp->shim = shim; > @@ -1837,6 +1890,12 @@ int intel_hdcp_init(struct intel_connector *connector, > init_waitqueue_head(&hdcp->cp_irq_queue); > > return 0; > + > +err_exit: > + hdcp->hdcp2_supported = false; > + kfree(hdcp->port_data.streams); > + > + return ret; > } > > int intel_hdcp_enable(struct intel_connector *connector, u8 content_type) > diff --git a/include/drm/drm_hdcp.h b/include/drm/drm_hdcp.h > index fdd65a14f4db..330e34715aa4 100644 > --- a/include/drm/drm_hdcp.h > +++ b/include/drm/drm_hdcp.h > @@ -23,6 +23,7 @@ > #define DRM_HDCP_V_PRIME_PART_LEN 4 > #define DRM_HDCP_V_PRIME_NUM_PARTS 5 > #define DRM_HDCP_NUM_DOWNSTREAM(x) (x & 0x7f) > +#define DRM_HDCP_DEPTH(x) ((x) & 0x7) > #define DRM_HDCP_MAX_CASCADE_EXCEEDED(x) (x & BIT(3)) > #define DRM_HDCP_MAX_DEVICE_EXCEEDED(x) (x & BIT(7)) > > -- > 2.19.1 >
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index e387e842f414..6a321a56ce42 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -482,6 +482,8 @@ struct intel_hdcp { wait_queue_head_t cp_irq_queue; atomic_t cp_irq_count; int cp_irq_count_cached; + + struct hdcp_topology_info *topology_info; }; struct intel_connector { diff --git a/drivers/gpu/drm/i915/intel_hdcp.c b/drivers/gpu/drm/i915/intel_hdcp.c index f70f1e98e4ae..6993bb9ecd0b 100644 --- a/drivers/gpu/drm/i915/intel_hdcp.c +++ b/drivers/gpu/drm/i915/intel_hdcp.c @@ -490,9 +490,10 @@ int intel_hdcp_validate_v_prime(struct intel_digital_port *intel_dig_port, /* Implements Part 2 of the HDCP authorization procedure */ static -int intel_hdcp_auth_downstream(struct intel_digital_port *intel_dig_port, - const struct intel_hdcp_shim *shim) +int intel_hdcp_auth_downstream(struct intel_hdcp *hdcp, + struct intel_digital_port *intel_dig_port) { + const struct intel_hdcp_shim *shim = hdcp->shim; u8 bstatus[2], num_downstream, *ksv_fifo; int ret, i, tries = 3; @@ -523,6 +524,9 @@ int intel_hdcp_auth_downstream(struct intel_digital_port *intel_dig_port, if (num_downstream == 0) return -EINVAL; + hdcp->topology_info->device_count = num_downstream; + hdcp->topology_info->depth = DRM_HDCP_DEPTH(bstatus[1]); + ksv_fifo = kcalloc(DRM_HDCP_KSV_LEN, num_downstream, GFP_KERNEL); if (!ksv_fifo) return -ENOMEM; @@ -536,6 +540,8 @@ int intel_hdcp_auth_downstream(struct intel_digital_port *intel_dig_port, return -EPERM; } + memcpy(hdcp->topology_info->ksv_list, ksv_fifo, + num_downstream * DRM_HDCP_KSV_LEN); /* * When V prime mismatches, DP Spec mandates re-read of * V prime atleast twice. @@ -562,9 +568,11 @@ int intel_hdcp_auth_downstream(struct intel_digital_port *intel_dig_port, } /* Implements Part 1 of the HDCP authorization procedure */ -static int intel_hdcp_auth(struct intel_digital_port *intel_dig_port, - const struct intel_hdcp_shim *shim) +static int intel_hdcp_auth(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->shim; struct drm_i915_private *dev_priv; enum port port; unsigned long r0_prime_gen_start; @@ -635,15 +643,20 @@ static int intel_hdcp_auth(struct intel_digital_port *intel_dig_port, return -EPERM; } + hdcp->topology_info->ver_in_force = DRM_MODE_HDCP14_IN_FORCE; + memcpy(hdcp->topology_info->bksv, bksv.shim, DRM_MODE_HDCP_KSV_LEN); + I915_WRITE(PORT_HDCP_BKSVLO(port), bksv.reg[0]); I915_WRITE(PORT_HDCP_BKSVHI(port), bksv.reg[1]); ret = shim->repeater_present(intel_dig_port, &repeater_present); if (ret) return ret; - if (repeater_present) + if (repeater_present) { I915_WRITE(HDCP_REP_CTL, intel_hdcp_get_repeater_ctl(intel_dig_port)); + hdcp->topology_info->is_repeater = true; + } ret = shim->toggle_signalling(intel_dig_port, true); if (ret) @@ -708,7 +721,7 @@ static int intel_hdcp_auth(struct intel_digital_port *intel_dig_port, */ if (repeater_present) - return intel_hdcp_auth_downstream(intel_dig_port, shim); + return intel_hdcp_auth_downstream(hdcp, intel_dig_port); DRM_DEBUG_KMS("HDCP is enabled (no repeater present)\n"); return 0; @@ -739,13 +752,18 @@ static int _intel_hdcp_disable(struct intel_connector *connector) return ret; } + memset(hdcp->topology_info, 0, sizeof(struct hdcp_topology_info)); + + if (drm_connector_update_hdcp_topology_property(&connector->base, + connector->hdcp.topology_info)) + DRM_ERROR("Downstream_info update failed.\n"); + DRM_DEBUG_KMS("HDCP is disabled\n"); return 0; } 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; @@ -770,9 +788,13 @@ 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); + ret = intel_hdcp_auth(connector); if (!ret) { - hdcp->hdcp_encrypted = true; + connector->hdcp.hdcp_encrypted = true; + if (drm_connector_update_hdcp_topology_property( + &connector->base, + connector->hdcp.topology_info)) + DRM_ERROR("Downstream_info update failed.\n"); return 0; } @@ -1206,6 +1228,12 @@ static int hdcp2_authentication_key_exchange(struct intel_connector *connector) return -EPERM; } + hdcp->topology_info->ver_in_force = DRM_MODE_HDCP22_IN_FORCE; + hdcp->topology_info->content_type = hdcp->content_type; + memcpy(hdcp->topology_info->bksv, msgs.send_cert.cert_rx.receiver_id, + HDCP_2_2_RECEIVER_ID_LEN); + hdcp->topology_info->is_repeater = hdcp->is_repeater; + /* * Here msgs.no_stored_km will hold msgs corresponding to the km * stored also. @@ -1397,6 +1425,11 @@ int hdcp2_authenticate_repeater_topology(struct intel_connector *connector) return -EPERM; } + hdcp->topology_info->device_count = device_cnt; + hdcp->topology_info->depth = HDCP_2_2_DEPTH(rx_info[0]); + memcpy(hdcp->topology_info->ksv_list, msgs.recvid_list.receiver_ids, + device_cnt * HDCP_2_2_RECEIVER_ID_LEN); + ret = hdcp2_verify_rep_topology_prepare_ack(connector, &msgs.recvid_list, &msgs.rep_ack); @@ -1583,6 +1616,12 @@ static int _intel_hdcp2_enable(struct intel_connector *connector) if (ret) { DRM_DEBUG_KMS("HDCP2 Type%d Enabling Failed. (%d)\n", hdcp->content_type, ret); + + memset(hdcp->topology_info, 0, + sizeof(struct hdcp_topology_info)); + drm_connector_update_hdcp_topology_property(&connector->base, + hdcp->topology_info); + return ret; } @@ -1590,12 +1629,16 @@ static int _intel_hdcp2_enable(struct intel_connector *connector) connector->base.name, connector->base.base.id, hdcp->content_type); + drm_connector_update_hdcp_topology_property(&connector->base, + hdcp->topology_info); hdcp->hdcp2_encrypted = true; + return 0; } static int _intel_hdcp2_disable(struct intel_connector *connector) { + struct intel_hdcp *hdcp = &connector->hdcp; int ret; DRM_DEBUG_KMS("[%s:%d] HDCP2.2 is being Disabled\n", @@ -1606,8 +1649,11 @@ static int _intel_hdcp2_disable(struct intel_connector *connector) if (hdcp2_deauthenticate_port(connector) < 0) DRM_DEBUG_KMS("Port deauth failed.\n"); - connector->hdcp.hdcp2_encrypted = false; + hdcp->hdcp2_encrypted = false; + memset(hdcp->topology_info, 0, sizeof(struct hdcp_topology_info)); + drm_connector_update_hdcp_topology_property(&connector->base, + hdcp->topology_info); return ret; } @@ -1824,10 +1870,17 @@ int intel_hdcp_init(struct intel_connector *connector, ret = drm_connector_attach_content_protection_property(&connector->base, hdcp->hdcp2_supported); - if (ret) { - hdcp->hdcp2_supported = false; - kfree(hdcp->port_data.streams); - return ret; + if (ret) + goto err_exit; + + ret = drm_connector_attach_hdcp_topology_property(&connector->base); + if (ret) + goto err_exit; + + hdcp->topology_info = kzalloc(sizeof(*hdcp->topology_info), GFP_KERNEL); + if (!hdcp->topology_info) { + ret = -ENOMEM; + goto err_exit; } hdcp->shim = shim; @@ -1837,6 +1890,12 @@ int intel_hdcp_init(struct intel_connector *connector, init_waitqueue_head(&hdcp->cp_irq_queue); return 0; + +err_exit: + hdcp->hdcp2_supported = false; + kfree(hdcp->port_data.streams); + + return ret; } int intel_hdcp_enable(struct intel_connector *connector, u8 content_type) diff --git a/include/drm/drm_hdcp.h b/include/drm/drm_hdcp.h index fdd65a14f4db..330e34715aa4 100644 --- a/include/drm/drm_hdcp.h +++ b/include/drm/drm_hdcp.h @@ -23,6 +23,7 @@ #define DRM_HDCP_V_PRIME_PART_LEN 4 #define DRM_HDCP_V_PRIME_NUM_PARTS 5 #define DRM_HDCP_NUM_DOWNSTREAM(x) (x & 0x7f) +#define DRM_HDCP_DEPTH(x) ((x) & 0x7) #define DRM_HDCP_MAX_CASCADE_EXCEEDED(x) (x & BIT(3)) #define DRM_HDCP_MAX_DEVICE_EXCEEDED(x) (x & BIT(7))
Implements drm blob property content_protection_downstream_info property on HDCP capable connectors. Downstream topology info is gathered across authentication stages and stored in intel_hdcp. When HDCP authentication is complete, new blob with latest downstream topology information is updated to content_protection_downstream_info property. v2: %s/cp_downstream/content_protection_downstream [daniel] v3: %s/content_protection_downstream/hdcp_topology [daniel] v4: Rebased. Signed-off-by: Ramalingam C <ramalingam.c@intel.com> --- drivers/gpu/drm/i915/intel_drv.h | 2 + drivers/gpu/drm/i915/intel_hdcp.c | 87 ++++++++++++++++++++++++++----- include/drm/drm_hdcp.h | 1 + 3 files changed, 76 insertions(+), 14 deletions(-)