diff mbox

[v2,07/42] misc/mei/hdcp: Get & Put for mei cl_device

Message ID 1520510349-8385-8-git-send-email-ramalingam.c@intel.com (mailing list archive)
State New, archived
Headers show

Commit Message

Ramalingam C March 8, 2018, 11:58 a.m. UTC
Interfaces to obtain and release the cl_device reference is developed.
Using these interfaces intel hdcp driver will get the reference to the
mei client devices, so that hdcp2.2 service calls can be routed to
that client device.

During registration, call back function will be registered with
mei_hdcp driver so that when the client device is removed intel
hdcp driver can be informed.

At a time only one reference is allowed in this interfaces.

v2:
  Rebased.

Signed-off-by: Ramalingam C <ramalingam.c@intel.com>
---
 drivers/misc/mei/hdcp/mei_hdcp.c | 55 +++++++++++++++++++++++++++++++++++++++-
 drivers/misc/mei/hdcp/mei_hdcp.h |  9 +++++++
 include/linux/mei_hdcp.h         | 47 ++++++++++++++++++++++++++++++++++
 3 files changed, 110 insertions(+), 1 deletion(-)
 create mode 100644 include/linux/mei_hdcp.h

Comments

Winkler, Tomas March 8, 2018, 1:10 p.m. UTC | #1
> Interfaces to obtain and release the cl_device reference is developed.
> Using these interfaces intel hdcp driver will get the reference to the mei
> client devices, so that hdcp2.2 service calls can be routed to that client
> device.
> 
> During registration, call back function will be registered with mei_hdcp driver
> so that when the client device is removed intel hdcp driver can be informed.
> 
> At a time only one reference is allowed in this interfaces.
> 
> v2:
>   Rebased.
Linux kernel already provide notification chain,  please use that. 
This is not needed and I'm not sure it will ever work.

Tomas

 
> Signed-off-by: Ramalingam C <ramalingam.c@intel.com>
> ---
>  drivers/misc/mei/hdcp/mei_hdcp.c | 55
> +++++++++++++++++++++++++++++++++++++++-
>  drivers/misc/mei/hdcp/mei_hdcp.h |  9 +++++++
>  include/linux/mei_hdcp.h         | 47 ++++++++++++++++++++++++++++++++++
>  3 files changed, 110 insertions(+), 1 deletion(-)  create mode 100644
> include/linux/mei_hdcp.h
> 
> diff --git a/drivers/misc/mei/hdcp/mei_hdcp.c
> b/drivers/misc/mei/hdcp/mei_hdcp.c
> index 25df7034cfb4..63f77800a6f7 100644
> --- a/drivers/misc/mei/hdcp/mei_hdcp.c
> +++ b/drivers/misc/mei/hdcp/mei_hdcp.c
> @@ -55,18 +55,71 @@ static int mei_hdcp_probe(struct mei_cl_device
> *cldev,
>  	mei_cldev_set_drvdata(cldev, &mei_hdcp);
> 
>  	ret = mei_cldev_enable(cldev);
> -	if (ret < 0)
> +	if (ret < 0) {
>  		dev_err(&cldev->dev, "mei_cldev_enable Failed. %d\n", ret);
> +		goto err;
> +	}
> +
> +	if (mei_hdcp.notify_on_cldev_change)
> +		mei_hdcp.notify_on_cldev_change(mei_hdcp.client, cldev);
> +
> +	return 0;
> +err:
> +	if (mei_hdcp.notify_on_cldev_change)
> +		mei_hdcp.notify_on_cldev_change(mei_hdcp.client, NULL);
> 
>  	return ret;
>  }
> 
>  static int mei_hdcp_remove(struct mei_cl_device *cldev)  {
> +	struct mei_hdcp *mei_hdcp = mei_cldev_get_drvdata(cldev);
> +
> +	if (mei_hdcp->notify_on_cldev_change)
> +		mei_hdcp->notify_on_cldev_change(mei_hdcp->client, NULL);
> +
>  	mei_cldev_disable(cldev);
> +
>  	return 0;
>  }
> 
> +int mei_hdcp_cldev_get_reference(void *client_data,
> +				 struct mei_cl_device **cldev,
> +				 void (*notify_change)(void *client,
> +						       struct mei_cl_device
> +						       *cldev))
> +{
> +	if (!notify_change || !client_data)
> +		return -EINVAL;
> +
> +	if (mei_hdcp.ref_cnt)
> +		return -EBUSY;
> +
> +	if (!mei_cldev_active_and_enabled(mei_hdcp.cldev)) {
> +		if (!notify_change)
> +			return -EAGAIN;
> +	} else {
> +		*cldev = mei_hdcp.cldev;
> +	}
> +
> +	mei_hdcp.ref_cnt++;
> +	mei_hdcp.client = client_data;
> +	mei_hdcp.notify_on_cldev_change = notify_change;
> +
> +	return 0;
> +}
> +EXPORT_SYMBOL(mei_hdcp_cldev_get_reference);
> +
> +void mei_hdcp_cldev_put_reference(struct mei_cl_device *cldev) {
> +	if (cldev == mei_hdcp.cldev) {
> +		mei_hdcp.ref_cnt--;
> +		mei_hdcp.client = NULL;
> +		mei_hdcp.notify_on_cldev_change = NULL;
> +	}
> +}
> +EXPORT_SYMBOL(mei_hdcp_cldev_put_reference);
> +
>  #define WIDI_HECI_CLIENT_GUID	UUID_LE(0xB638AB7E, 0x94E2,
> 0x4EA2, 0xA5, \
>  					0x52, 0xD1, 0xC5, 0x4B, \
>  					0x62, 0x7F, 0x04)
> diff --git a/drivers/misc/mei/hdcp/mei_hdcp.h
> b/drivers/misc/mei/hdcp/mei_hdcp.h
> index c06c0d767c4f..7d792b5ad703 100644
> --- a/drivers/misc/mei/hdcp/mei_hdcp.h
> +++ b/drivers/misc/mei/hdcp/mei_hdcp.h
> @@ -27,6 +27,15 @@
> 
>  struct mei_hdcp {
>  	struct mei_cl_device *cldev;
> +
> +	/* Reference to the HDCP2.2 service consumer */
> +	void *client;
> +
> +	/* Callback function for the consumer on cl_device state change */
> +	void (*notify_on_cldev_change)(void *client,
> +				      struct mei_cl_device *cldev);
> +
> +	int ref_cnt;
>  };
> 
>  #endif /* __MEI_HDCP_H__ */
> diff --git a/include/linux/mei_hdcp.h b/include/linux/mei_hdcp.h new file
> mode 100644 index 000000000000..774b26da0c26
> --- /dev/null
> +++ b/include/linux/mei_hdcp.h
> @@ -0,0 +1,47 @@
> +/*
> + * Copyright (c) 2017 Intel Corporation
> + *
> + * Permission to use, copy, modify, distribute, and sell this software
> +and its
> + * documentation for any purpose is hereby granted without fee,
> +provided that
> + * the above copyright notice appear in all copies and that both that
> +copyright
> + * notice and this permission notice appear in supporting
> +documentation, and
> + * that the name of the copyright holders not be used in advertising or
> + * publicity pertaining to distribution of the software without
> +specific,
> + * written prior permission.  The copyright holders make no
> +representations
> + * about the suitability of this software for any purpose.  It is
> +provided "as
> + * is" without express or implied warranty.
> + *
> + * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO
> THIS
> +SOFTWARE,
> + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
> FITNESS, IN
> +NO
> + * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL,
> +INDIRECT OR
> + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING
> FROM LOSS
> +OF USE,
> + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
> OR
> +OTHER
> + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE
> OR
> +PERFORMANCE
> + * OF THIS SOFTWARE.
> + */
> +
> +#ifndef _LINUX_MEI_HDCP_H
> +#define _LINUX_MEI_HDCP_H
> +
> +#ifdef CONFIG_INTEL_MEI_HDCP
> +int mei_hdcp_cldev_get_reference(void *client_data,
> +				 struct mei_cl_device **cldev,
> +				 void (*notify_change)(void *client,
> +						       struct mei_cl_device
> +						       *cldev));
> +void mei_hdcp_cldev_put_reference(struct mei_cl_device *cldev); #else
> +static inline int mei_hdcp_cldev_get_reference(void *client_data,
> +				 struct mei_cl_device **cldev,
> +				 void (*notify_change)(void *client,
> +						       struct mei_cl_device
> +						       *cldev))
> +{
> +	return -ENODEV;
> +}
> +static inline
> +void mei_hdcp_cldev_put_reference(struct mei_cl_device *cldev) {}
> +#endif /* defined (CONFIG_INTEL_MEI_HDCP) */ #endif /* defined
> +(_LINUX_MEI_HDCP_H) */
> --
> 2.7.4
Ramalingam C March 12, 2018, 11:35 a.m. UTC | #2
On Thursday 08 March 2018 06:40 PM, Winkler, Tomas wrote:
>> Interfaces to obtain and release the cl_device reference is developed.
>> Using these interfaces intel hdcp driver will get the reference to the mei
>> client devices, so that hdcp2.2 service calls can be routed to that client
>> device.
>>
>> During registration, call back function will be registered with mei_hdcp driver
>> so that when the client device is removed intel hdcp driver can be informed.
>>
>> At a time only one reference is allowed in this interfaces.
>>
>> v2:
>>    Rebased.
> Linux kernel already provide notification chain,  please use that.
Sensing a problem here. Publisher module (mei_hdcp) for the notifier 
chain is loaded later than the I915's hdcp init (subscriber to the module).
Events that we will be interested are enabled and disabled states of the 
mei_hdcp_device.

I will explore further. Thanks for the suggestion
> This is not needed and I'm not sure it will ever work.
I am not sure, why do you think like that. This might not be in good 
shape but this is completely functional.
This v2 series is tested for HDCP2.2 feature on drm-tip before publishing.

 From starting I was not comfortable with this handshaking part between 
I915 and mei_hdcp. Thanks for the suggestions.
I will work on them.

--Ram
>
> Tomas
>
>   
>> Signed-off-by: Ramalingam C <ramalingam.c@intel.com>
>> ---
>>   drivers/misc/mei/hdcp/mei_hdcp.c | 55
>> +++++++++++++++++++++++++++++++++++++++-
>>   drivers/misc/mei/hdcp/mei_hdcp.h |  9 +++++++
>>   include/linux/mei_hdcp.h         | 47 ++++++++++++++++++++++++++++++++++
>>   3 files changed, 110 insertions(+), 1 deletion(-)  create mode 100644
>> include/linux/mei_hdcp.h
>>
>> diff --git a/drivers/misc/mei/hdcp/mei_hdcp.c
>> b/drivers/misc/mei/hdcp/mei_hdcp.c
>> index 25df7034cfb4..63f77800a6f7 100644
>> --- a/drivers/misc/mei/hdcp/mei_hdcp.c
>> +++ b/drivers/misc/mei/hdcp/mei_hdcp.c
>> @@ -55,18 +55,71 @@ static int mei_hdcp_probe(struct mei_cl_device
>> *cldev,
>>   	mei_cldev_set_drvdata(cldev, &mei_hdcp);
>>
>>   	ret = mei_cldev_enable(cldev);
>> -	if (ret < 0)
>> +	if (ret < 0) {
>>   		dev_err(&cldev->dev, "mei_cldev_enable Failed. %d\n", ret);
>> +		goto err;
>> +	}
>> +
>> +	if (mei_hdcp.notify_on_cldev_change)
>> +		mei_hdcp.notify_on_cldev_change(mei_hdcp.client, cldev);
>> +
>> +	return 0;
>> +err:
>> +	if (mei_hdcp.notify_on_cldev_change)
>> +		mei_hdcp.notify_on_cldev_change(mei_hdcp.client, NULL);
>>
>>   	return ret;
>>   }
>>
>>   static int mei_hdcp_remove(struct mei_cl_device *cldev)  {
>> +	struct mei_hdcp *mei_hdcp = mei_cldev_get_drvdata(cldev);
>> +
>> +	if (mei_hdcp->notify_on_cldev_change)
>> +		mei_hdcp->notify_on_cldev_change(mei_hdcp->client, NULL);
>> +
>>   	mei_cldev_disable(cldev);
>> +
>>   	return 0;
>>   }
>>
>> +int mei_hdcp_cldev_get_reference(void *client_data,
>> +				 struct mei_cl_device **cldev,
>> +				 void (*notify_change)(void *client,
>> +						       struct mei_cl_device
>> +						       *cldev))
>> +{
>> +	if (!notify_change || !client_data)
>> +		return -EINVAL;
>> +
>> +	if (mei_hdcp.ref_cnt)
>> +		return -EBUSY;
>> +
>> +	if (!mei_cldev_active_and_enabled(mei_hdcp.cldev)) {
>> +		if (!notify_change)
>> +			return -EAGAIN;
>> +	} else {
>> +		*cldev = mei_hdcp.cldev;
>> +	}
>> +
>> +	mei_hdcp.ref_cnt++;
>> +	mei_hdcp.client = client_data;
>> +	mei_hdcp.notify_on_cldev_change = notify_change;
>> +
>> +	return 0;
>> +}
>> +EXPORT_SYMBOL(mei_hdcp_cldev_get_reference);
>> +
>> +void mei_hdcp_cldev_put_reference(struct mei_cl_device *cldev) {
>> +	if (cldev == mei_hdcp.cldev) {
>> +		mei_hdcp.ref_cnt--;
>> +		mei_hdcp.client = NULL;
>> +		mei_hdcp.notify_on_cldev_change = NULL;
>> +	}
>> +}
>> +EXPORT_SYMBOL(mei_hdcp_cldev_put_reference);
>> +
>>   #define WIDI_HECI_CLIENT_GUID	UUID_LE(0xB638AB7E, 0x94E2,
>> 0x4EA2, 0xA5, \
>>   					0x52, 0xD1, 0xC5, 0x4B, \
>>   					0x62, 0x7F, 0x04)
>> diff --git a/drivers/misc/mei/hdcp/mei_hdcp.h
>> b/drivers/misc/mei/hdcp/mei_hdcp.h
>> index c06c0d767c4f..7d792b5ad703 100644
>> --- a/drivers/misc/mei/hdcp/mei_hdcp.h
>> +++ b/drivers/misc/mei/hdcp/mei_hdcp.h
>> @@ -27,6 +27,15 @@
>>
>>   struct mei_hdcp {
>>   	struct mei_cl_device *cldev;
>> +
>> +	/* Reference to the HDCP2.2 service consumer */
>> +	void *client;
>> +
>> +	/* Callback function for the consumer on cl_device state change */
>> +	void (*notify_on_cldev_change)(void *client,
>> +				      struct mei_cl_device *cldev);
>> +
>> +	int ref_cnt;
>>   };
>>
>>   #endif /* __MEI_HDCP_H__ */
>> diff --git a/include/linux/mei_hdcp.h b/include/linux/mei_hdcp.h new file
>> mode 100644 index 000000000000..774b26da0c26
>> --- /dev/null
>> +++ b/include/linux/mei_hdcp.h
>> @@ -0,0 +1,47 @@
>> +/*
>> + * Copyright (c) 2017 Intel Corporation
>> + *
>> + * Permission to use, copy, modify, distribute, and sell this software
>> +and its
>> + * documentation for any purpose is hereby granted without fee,
>> +provided that
>> + * the above copyright notice appear in all copies and that both that
>> +copyright
>> + * notice and this permission notice appear in supporting
>> +documentation, and
>> + * that the name of the copyright holders not be used in advertising or
>> + * publicity pertaining to distribution of the software without
>> +specific,
>> + * written prior permission.  The copyright holders make no
>> +representations
>> + * about the suitability of this software for any purpose.  It is
>> +provided "as
>> + * is" without express or implied warranty.
>> + *
>> + * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO
>> THIS
>> +SOFTWARE,
>> + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
>> FITNESS, IN
>> +NO
>> + * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL,
>> +INDIRECT OR
>> + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING
>> FROM LOSS
>> +OF USE,
>> + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
>> OR
>> +OTHER
>> + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE
>> OR
>> +PERFORMANCE
>> + * OF THIS SOFTWARE.
>> + */
>> +
>> +#ifndef _LINUX_MEI_HDCP_H
>> +#define _LINUX_MEI_HDCP_H
>> +
>> +#ifdef CONFIG_INTEL_MEI_HDCP
>> +int mei_hdcp_cldev_get_reference(void *client_data,
>> +				 struct mei_cl_device **cldev,
>> +				 void (*notify_change)(void *client,
>> +						       struct mei_cl_device
>> +						       *cldev));
>> +void mei_hdcp_cldev_put_reference(struct mei_cl_device *cldev); #else
>> +static inline int mei_hdcp_cldev_get_reference(void *client_data,
>> +				 struct mei_cl_device **cldev,
>> +				 void (*notify_change)(void *client,
>> +						       struct mei_cl_device
>> +						       *cldev))
>> +{
>> +	return -ENODEV;
>> +}
>> +static inline
>> +void mei_hdcp_cldev_put_reference(struct mei_cl_device *cldev) {}
>> +#endif /* defined (CONFIG_INTEL_MEI_HDCP) */ #endif /* defined
>> +(_LINUX_MEI_HDCP_H) */
>> --
>> 2.7.4
diff mbox

Patch

diff --git a/drivers/misc/mei/hdcp/mei_hdcp.c b/drivers/misc/mei/hdcp/mei_hdcp.c
index 25df7034cfb4..63f77800a6f7 100644
--- a/drivers/misc/mei/hdcp/mei_hdcp.c
+++ b/drivers/misc/mei/hdcp/mei_hdcp.c
@@ -55,18 +55,71 @@  static int mei_hdcp_probe(struct mei_cl_device *cldev,
 	mei_cldev_set_drvdata(cldev, &mei_hdcp);
 
 	ret = mei_cldev_enable(cldev);
-	if (ret < 0)
+	if (ret < 0) {
 		dev_err(&cldev->dev, "mei_cldev_enable Failed. %d\n", ret);
+		goto err;
+	}
+
+	if (mei_hdcp.notify_on_cldev_change)
+		mei_hdcp.notify_on_cldev_change(mei_hdcp.client, cldev);
+
+	return 0;
+err:
+	if (mei_hdcp.notify_on_cldev_change)
+		mei_hdcp.notify_on_cldev_change(mei_hdcp.client, NULL);
 
 	return ret;
 }
 
 static int mei_hdcp_remove(struct mei_cl_device *cldev)
 {
+	struct mei_hdcp *mei_hdcp = mei_cldev_get_drvdata(cldev);
+
+	if (mei_hdcp->notify_on_cldev_change)
+		mei_hdcp->notify_on_cldev_change(mei_hdcp->client, NULL);
+
 	mei_cldev_disable(cldev);
+
 	return 0;
 }
 
+int mei_hdcp_cldev_get_reference(void *client_data,
+				 struct mei_cl_device **cldev,
+				 void (*notify_change)(void *client,
+						       struct mei_cl_device
+						       *cldev))
+{
+	if (!notify_change || !client_data)
+		return -EINVAL;
+
+	if (mei_hdcp.ref_cnt)
+		return -EBUSY;
+
+	if (!mei_cldev_active_and_enabled(mei_hdcp.cldev)) {
+		if (!notify_change)
+			return -EAGAIN;
+	} else {
+		*cldev = mei_hdcp.cldev;
+	}
+
+	mei_hdcp.ref_cnt++;
+	mei_hdcp.client = client_data;
+	mei_hdcp.notify_on_cldev_change = notify_change;
+
+	return 0;
+}
+EXPORT_SYMBOL(mei_hdcp_cldev_get_reference);
+
+void mei_hdcp_cldev_put_reference(struct mei_cl_device *cldev)
+{
+	if (cldev == mei_hdcp.cldev) {
+		mei_hdcp.ref_cnt--;
+		mei_hdcp.client = NULL;
+		mei_hdcp.notify_on_cldev_change = NULL;
+	}
+}
+EXPORT_SYMBOL(mei_hdcp_cldev_put_reference);
+
 #define WIDI_HECI_CLIENT_GUID	UUID_LE(0xB638AB7E, 0x94E2, 0x4EA2, 0xA5, \
 					0x52, 0xD1, 0xC5, 0x4B, \
 					0x62, 0x7F, 0x04)
diff --git a/drivers/misc/mei/hdcp/mei_hdcp.h b/drivers/misc/mei/hdcp/mei_hdcp.h
index c06c0d767c4f..7d792b5ad703 100644
--- a/drivers/misc/mei/hdcp/mei_hdcp.h
+++ b/drivers/misc/mei/hdcp/mei_hdcp.h
@@ -27,6 +27,15 @@ 
 
 struct mei_hdcp {
 	struct mei_cl_device *cldev;
+
+	/* Reference to the HDCP2.2 service consumer */
+	void *client;
+
+	/* Callback function for the consumer on cl_device state change */
+	void (*notify_on_cldev_change)(void *client,
+				      struct mei_cl_device *cldev);
+
+	int ref_cnt;
 };
 
 #endif /* __MEI_HDCP_H__ */
diff --git a/include/linux/mei_hdcp.h b/include/linux/mei_hdcp.h
new file mode 100644
index 000000000000..774b26da0c26
--- /dev/null
+++ b/include/linux/mei_hdcp.h
@@ -0,0 +1,47 @@ 
+/*
+ * Copyright (c) 2017 Intel Corporation
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that copyright
+ * notice and this permission notice appear in supporting documentation, and
+ * that the name of the copyright holders not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission.  The copyright holders make no representations
+ * about the suitability of this software for any purpose.  It is provided "as
+ * is" without express or implied warranty.
+ *
+ * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
+ * OF THIS SOFTWARE.
+ */
+
+#ifndef _LINUX_MEI_HDCP_H
+#define _LINUX_MEI_HDCP_H
+
+#ifdef CONFIG_INTEL_MEI_HDCP
+int mei_hdcp_cldev_get_reference(void *client_data,
+				 struct mei_cl_device **cldev,
+				 void (*notify_change)(void *client,
+						       struct mei_cl_device
+						       *cldev));
+void mei_hdcp_cldev_put_reference(struct mei_cl_device *cldev);
+#else
+static inline
+int mei_hdcp_cldev_get_reference(void *client_data,
+				 struct mei_cl_device **cldev,
+				 void (*notify_change)(void *client,
+						       struct mei_cl_device
+						       *cldev))
+{
+	return -ENODEV;
+}
+static inline
+void mei_hdcp_cldev_put_reference(struct mei_cl_device *cldev)
+{}
+#endif /* defined (CONFIG_INTEL_MEI_HDCP) */
+#endif /* defined (_LINUX_MEI_HDCP_H) */