From: Tomas Winkler tomas.winkler@intel.com
commit 1e8d19d9b0dfcf11b61bac627203a290577e807a upstream.
The mei device and i915 must reside on the same PCH in order for HDCP to work. Make the component matching function enforce this requirement.
hdcp | i915 mei | | +----= PCH =----+
Cc: stable@vger.kernel.org v5.0+ Cc: Ramalingam C ramalingam.c@intel.com Signed-off-by: Tomas Winkler tomas.winkler@intel.com Reviewed-by: Alexander Usyskin alexander.usyskin@intel.com Link: https://lore.kernel.org/r/20191212084103.2893-1-tomas.winkler@intel.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org
--- drivers/misc/mei/hdcp/mei_hdcp.c | 33 ++++++++++++++++++++++++++++++--- 1 file changed, 30 insertions(+), 3 deletions(-)
--- a/drivers/misc/mei/hdcp/mei_hdcp.c +++ b/drivers/misc/mei/hdcp/mei_hdcp.c @@ -757,11 +757,38 @@ static const struct component_master_ops .unbind = mei_component_master_unbind, };
+/** + * mei_hdcp_component_match - compare function for matching mei hdcp. + * + * The function checks if the driver is i915, the subcomponent is HDCP + * and the grand parent of hdcp and the parent of i915 are the same + * PCH device. + * + * @dev: master device + * @subcomponent: subcomponent to match (I915_COMPONENT_HDCP) + * @data: compare data (mei hdcp device) + * + * Return: + * * 1 - if components match + * * 0 - otherwise + */ static int mei_hdcp_component_match(struct device *dev, int subcomponent, void *data) { - return !strcmp(dev->driver->name, "i915") && - subcomponent == I915_COMPONENT_HDCP; + struct device *base = data; + + if (strcmp(dev->driver->name, "i915") || + subcomponent != I915_COMPONENT_HDCP) + return 0; + + base = base->parent; + if (!base) + return 0; + + base = base->parent; + dev = dev->parent; + + return (base && dev && dev == base); }
static int mei_hdcp_probe(struct mei_cl_device *cldev, @@ -785,7 +812,7 @@ static int mei_hdcp_probe(struct mei_cl_
master_match = NULL; component_match_add_typed(&cldev->dev, &master_match, - mei_hdcp_component_match, comp_master); + mei_hdcp_component_match, &cldev->dev); if (IS_ERR_OR_NULL(master_match)) { ret = -ENOMEM; goto err_exit;