]> git.ipfire.org Git - people/arne_f/kernel.git/commitdiff
mei: hdcp: bind only with i915 on the same PCH
authorTomas Winkler <tomas.winkler@intel.com>
Thu, 12 Dec 2019 08:41:03 +0000 (10:41 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Sat, 1 Feb 2020 09:32:54 +0000 (09:32 +0000)
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

index 93027fd96c71655e3d5f0d60cf5ec83c1ca1f357..4c596c646ac0978e4295a9731d67a63983b627df 100644 (file)
@@ -757,11 +757,38 @@ static const struct component_master_ops mei_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_device *cldev,
 
        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;