Browse Source

Merge "driver : hdcp_qseecom: Retry HDCP key verify when Qseecomd down"

qctecmdr 1 year ago
parent
commit
b263ab047a
4 changed files with 115 additions and 22 deletions
  1. 34 14
      hdcp/hdcp_main.c
  2. 6 0
      hdcp/hdcp_main.h
  3. 55 8
      hdcp/hdcp_qseecom.c
  4. 20 0
      hdcp/hdcp_qseecom.h

+ 34 - 14
hdcp/hdcp_main.c

@@ -105,7 +105,7 @@ bool hdcp2_feature_supported(void *data)
 
 	return ret;
 }
-EXPORT_SYMBOL(hdcp2_feature_supported);
+EXPORT_SYMBOL_GPL(hdcp2_feature_supported);
 
 int hdcp2_force_encryption(void *ctx, uint32_t enable)
 {
@@ -117,7 +117,7 @@ int hdcp2_force_encryption(void *ctx, uint32_t enable)
 
 	return ret;
 }
-EXPORT_SYMBOL(hdcp2_force_encryption);
+EXPORT_SYMBOL_GPL(hdcp2_force_encryption);
 
 int hdcp2_app_comm(void *ctx, enum hdcp2_app_cmd cmd,
 				   struct hdcp2_app_data *app_data)
@@ -168,7 +168,7 @@ error:
 	mutex_unlock(&hdcp2_mutex_g);
 	return ret;
 }
-EXPORT_SYMBOL(hdcp2_app_comm);
+EXPORT_SYMBOL_GPL(hdcp2_app_comm);
 
 int hdcp2_open_stream(void *ctx, uint8_t vc_payload_id, uint8_t stream_number,
 		  uint32_t *stream_id)
@@ -182,7 +182,7 @@ int hdcp2_open_stream(void *ctx, uint8_t vc_payload_id, uint8_t stream_number,
 
 	return ret;
 }
-EXPORT_SYMBOL(hdcp2_open_stream);
+EXPORT_SYMBOL_GPL(hdcp2_open_stream);
 
 int hdcp2_close_stream(void *ctx, uint32_t stream_id)
 {
@@ -194,7 +194,7 @@ int hdcp2_close_stream(void *ctx, uint32_t stream_id)
 
 	return ret;
 }
-EXPORT_SYMBOL(hdcp2_close_stream);
+EXPORT_SYMBOL_GPL(hdcp2_close_stream);
 
 void *hdcp2_init(u32 device_type)
 {
@@ -206,13 +206,23 @@ void *hdcp2_init(u32 device_type)
 
 	return data;
 }
-EXPORT_SYMBOL(hdcp2_init);
+EXPORT_SYMBOL_GPL(hdcp2_init);
+
+void hdcp2_set_hdcp_key_verify_retries(void *ctx, u32 max_hdcp_key_verify_retries)
+{
+	struct hdcp2_qsee_handle *handle = ctx;
+
+	handle->max_hdcp_key_verify_retries = max_hdcp_key_verify_retries;
+
+	pr_debug("hdcp2 max_hdcp_key_verify_retries %d\n", handle->max_hdcp_key_verify_retries);
+}
+EXPORT_SYMBOL_GPL(hdcp2_set_hdcp_key_verify_retries);
 
 void hdcp2_deinit(void *ctx)
 {
 	ta_interface.trusted_app_hdcp2_deinit(ctx);
 }
-EXPORT_SYMBOL(hdcp2_deinit);
+EXPORT_SYMBOL_GPL(hdcp2_deinit);
 
 void *hdcp1_init(void)
 {
@@ -224,13 +234,23 @@ void *hdcp1_init(void)
 
 	return data;
 }
-EXPORT_SYMBOL(hdcp1_init);
+EXPORT_SYMBOL_GPL(hdcp1_init);
+
+void hdcp1_set_hdcp_key_verify_retries(void *ctx, u32 max_hdcp_key_verify_retries)
+{
+	struct hdcp1_qsee_handle *handle = ctx;
+
+	handle->max_hdcp_key_verify_retries = max_hdcp_key_verify_retries;
+
+	pr_debug("hdcp1 max_hdcp_key_verify_retries %d\n", handle->max_hdcp_key_verify_retries);
+}
+EXPORT_SYMBOL_GPL(hdcp1_set_hdcp_key_verify_retries);
 
 void hdcp1_deinit(void *data)
 {
 	kfree(data);
 }
-EXPORT_SYMBOL(hdcp1_deinit);
+EXPORT_SYMBOL_GPL(hdcp1_deinit);
 
 bool hdcp1_feature_supported(void *data)
 {
@@ -242,7 +262,7 @@ bool hdcp1_feature_supported(void *data)
 
 	return supported;
 }
-EXPORT_SYMBOL(hdcp1_feature_supported);
+EXPORT_SYMBOL_GPL(hdcp1_feature_supported);
 
 int hdcp1_set_enc(void *data, bool enable)
 {
@@ -254,7 +274,7 @@ int hdcp1_set_enc(void *data, bool enable)
 
 	return ret;
 }
-EXPORT_SYMBOL(hdcp1_set_enc);
+EXPORT_SYMBOL_GPL(hdcp1_set_enc);
 
 int hdcp1_ops_notify(void *data, void *topo, bool is_authenticated)
 {
@@ -264,7 +284,7 @@ int hdcp1_ops_notify(void *data, void *topo, bool is_authenticated)
 
 	return ret;
 }
-EXPORT_SYMBOL(hdcp1_ops_notify);
+EXPORT_SYMBOL_GPL(hdcp1_ops_notify);
 
 int hdcp1_start(void *data, u32 *aksv_msb, u32 *aksv_lsb)
 {
@@ -276,7 +296,7 @@ int hdcp1_start(void *data, u32 *aksv_msb, u32 *aksv_lsb)
 
 	return ret;
 }
-EXPORT_SYMBOL(hdcp1_start);
+EXPORT_SYMBOL_GPL(hdcp1_start);
 
 void hdcp1_stop(void *data)
 {
@@ -284,7 +304,7 @@ void hdcp1_stop(void *data)
 	ta_interface.trusted_app_hdcp1_stop(data);
 	mutex_unlock(&hdcp1_mutex_g);
 }
-EXPORT_SYMBOL(hdcp1_stop);
+EXPORT_SYMBOL_GPL(hdcp1_stop);
 
 static int __init hdcp_module_init(void)
 {

+ 6 - 0
hdcp/hdcp_main.h

@@ -56,6 +56,12 @@
 /* Wait 200ms after authentication */
 #define SLEEP_FORCE_ENCRYPTION_MS 200
 
+/* Error code when Qseecomd is not up at boot time */
+#define QSEECOMD_ERROR -4103
+
+/* Wait for 100ms on every retry to check if Qseecomd is up */
+#define SLEEP_QSEECOMD_WAIT_MS 100
+
 #define SLEEP_SET_HW_KEY_MS 300
 
 /* flags set by tz in response message */

+ 55 - 8
hdcp/hdcp_qseecom.c

@@ -323,6 +323,12 @@ static int hdcp1_verify_key(struct hdcp1_qsee_handle *hdcp1_handle)
 	}
 
 	rc = key_verify_rsp->ret;
+
+	if (rc == QSEECOMD_ERROR)
+		qseecomd_down = true;
+	else
+		qseecomd_down = false;
+
 	if (rc) {
 		pr_err("key_verify failed, rsp=%d\n", key_verify_rsp->ret);
 		return -EINVAL;
@@ -385,6 +391,11 @@ static int hdcp2_verify_key(struct hdcp2_qsee_handle *handle)
 	rc = hdcp2_app_process_cmd(verify_key);
 	pr_debug("verify_key = %d\n", rc);
 
+	if (rsp_buf->status == QSEECOMD_ERROR)
+		qseecomd_down = true;
+	else
+		qseecomd_down = false;
+
 error:
 	return rc;
 }
@@ -468,6 +479,7 @@ bool hdcp1_feature_supported_qseecom(void *data)
 	bool supported = false;
 	struct hdcp1_qsee_handle *handle = data;
 	int rc = 0;
+	int retry = 0;
 
 	if (!handle) {
 		pr_err("invalid handle\n");
@@ -480,11 +492,31 @@ bool hdcp1_feature_supported_qseecom(void *data)
 	}
 
 	rc = hdcp1_app_load(handle);
+
+	/* Other than in SUCCESS case, if there is a FAILURE when
+	 * handle is NULL, the hdcp1_app_load will return zero.
+	 * Checking the hdcp_state will ensure that the conditional
+	 * is ONLY true when hdcp1_app_load had no Failures.
+	 */
 	if (!rc && (handle->hdcp_state & HDCP_STATE_APP_LOADED)) {
-		if (!hdcp1_verify_key(handle)) {
-			pr_debug("HDCP 1.x supported\n");
-			handle->feature_supported = true;
-			supported = true;
+		do {
+			if (!hdcp1_verify_key(handle)) {
+				pr_debug("HDCP 1.x supported\n");
+				pr_debug("hdcp1_verify_key succeeded on %d retry.\n", retry);
+				handle->feature_supported = true;
+				supported = true;
+				break;
+			} else if (qseecomd_down) {
+				pr_debug("Qseecomd is not up. Going to sleep.\n");
+				msleep(SLEEP_QSEECOMD_WAIT_MS);
+				retry++;
+			} else
+				break;
+		} while (handle->max_hdcp_key_verify_retries >= retry);
+
+		if (qseecomd_down) {
+			pr_err("hdcp1_verify_key failed after %d retries as Qseecomd is not up.\n",
+				handle->max_hdcp_key_verify_retries);
 		}
 		hdcp1_app_unload(handle);
 	}
@@ -1252,6 +1284,7 @@ error:
 bool hdcp2_feature_supported_qseecom(void *ctx)
 {
 	int rc = 0;
+	int retry = 0;
 	bool supported = false;
 	struct hdcp2_qsee_handle *handle = (struct hdcp2_qsee_handle *)ctx;
 
@@ -1268,10 +1301,24 @@ bool hdcp2_feature_supported_qseecom(void *ctx)
 
 	rc = hdcp2_app_load(handle);
 	if (!rc) {
-		if (!hdcp2_verify_key(handle)) {
-			pr_debug("HDCP 2.2 supported\n");
-			handle->feature_supported = true;
-			supported = true;
+		do {
+			if (!hdcp2_verify_key(handle)) {
+				pr_debug("HDCP 2.2 supported.\n");
+				pr_debug("hdcp2_verify_key succeeded on %d retry.\n", retry);
+				handle->feature_supported = true;
+				supported = true;
+				break;
+			} else if (qseecomd_down) {
+				pr_debug("Qseecomd is not up. Going to sleep.\n");
+				msleep(SLEEP_QSEECOMD_WAIT_MS);
+				retry++;
+			} else
+				break;
+		} while (handle->max_hdcp_key_verify_retries >= retry);
+
+		if (qseecomd_down) {
+			pr_err("hdcp2_verify_key failed after %d retries as Qseecomd is not up.\n",
+				handle->max_hdcp_key_verify_retries);
 		}
 		hdcp2_app_unload(handle);
 	}

+ 20 - 0
hdcp/hdcp_qseecom.h

@@ -13,6 +13,11 @@
 
 #include "hdcp_main.h"
 
+/*
+ * @max_hdcp_key_verify_retries - Max number of retries by default set to 0 which
+ *                                is equivalent to 0MS. Actual value will be the one
+ *                                from the dtsi file.
+ */
 struct hdcp1_qsee_handle {
 	struct qseecom_handle *qseecom_handle;
 	struct qseecom_handle *hdcpops_handle;
@@ -20,8 +25,22 @@ struct hdcp1_qsee_handle {
 	uint32_t device_type;
 	enum hdcp_state hdcp_state;
 	char *app_name;
+	uint32_t max_hdcp_key_verify_retries;
 };
 
+/*
+ * If Qseecomd starts late and hdcp key
+ * verification has already started, qseecomd_down
+ * flag will be set to true. It will be set to false
+ * once the Qseecomd is up. Initial assumption is
+ * that the Qseecomd will start in time.
+ */
+static bool qseecomd_down;
+/*
+ * @max_hdcp_key_verify_retries - Max number of retries by default set to 0 which
+ *                                is equivalent to 0MS. Actual value will be the one
+ *                                from the dtsi file.
+ */
 struct hdcp2_qsee_handle {
 	struct hdcp2_app_data app_data;
 	uint32_t tz_ctxhandle;
@@ -37,6 +56,7 @@ struct hdcp2_qsee_handle {
 	unsigned char *res_buf;
 	int (*app_init)(struct hdcp2_qsee_handle *handle);
 	int (*tx_init)(struct hdcp2_qsee_handle *handle);
+	uint32_t max_hdcp_key_verify_retries;
 };
 
 struct hdcp1_key_set_req {