diff options
author | Weizhung Ding <weizhungding@google.com> | 2023-09-21 08:27:54 +0000 |
---|---|---|
committer | Ji Soo Shin <jisshin@google.com> | 2023-10-18 17:32:26 +0000 |
commit | a41c9219ba1ac53591b28d4f7ada1b10c9463f14 (patch) | |
tree | 8194bc6ba0b7911e2300ab7a61e4bc07171079e6 | |
parent | 47212ce550245a8d89380905d5dfb1e4aa2996f2 (diff) | |
download | samsung-a41c9219ba1ac53591b28d4f7ada1b10c9463f14.tar.gz |
hdcp: Add DisplayPort statistics for max and current HDCP version.
Bug: 266898132
Test: cat /sys/devices/platform/hdcp/hdcp1_success_count
Change-Id: I9c604c3a37b848b64970c4a325b40d2d4c06e8d9
Signed-off-by: Weizhung Ding <weizhungding@google.com>
-rw-r--r-- | Documentation/ABI/testing/sysfs-devices-platform-hdcp | 47 | ||||
-rw-r--r-- | auth-control.c | 56 | ||||
-rw-r--r-- | auth-control.h | 6 | ||||
-rw-r--r-- | auth13.c | 4 | ||||
-rw-r--r-- | auth22.c | 1 | ||||
-rw-r--r-- | hdcp.h | 23 | ||||
-rw-r--r-- | main.c | 91 |
7 files changed, 208 insertions, 20 deletions
diff --git a/Documentation/ABI/testing/sysfs-devices-platform-hdcp b/Documentation/ABI/testing/sysfs-devices-platform-hdcp new file mode 100644 index 0000000..d424eef --- /dev/null +++ b/Documentation/ABI/testing/sysfs-devices-platform-hdcp @@ -0,0 +1,47 @@ +What: /sys/devices/platform/hdcp/hdcp2_success_count +Date: October 2023 +KernelVersion: 5.15 +Contact: "Ji Soo Shin" <jisshin@google.com> +Description: + DisplayPort stats uses this interface to count the number of + successful HDCP2 connection. + +What: /sys/devices/platform/hdcp/hdcp2_fallback_count +Date: October 2023 +KernelVersion: 5.15 +Contact: "Ji Soo Shin" <jisshin@google.com> +Description: + DisplayPort stats uses this interface to count the number of + HDCP2 connection attempt that resorted to HDCP1 instead. + +What: /sys/devices/platform/hdcp/hdcp2_fail_count +Date: October 2023 +KernelVersion: 5.15 +Contact: "Ji Soo Shin" <jisshin@google.com> +Description: + DisplayPort stats uses this interface to count the number of + HDCP2 connection attempt that failed. + +What: /sys/devices/platform/hdcp/hdcp1_success_count +Date: October 2023 +KernelVersion: 5.15 +Contact: "Ji Soo Shin" <jisshin@google.com> +Description: + DisplayPort stats uses this interface to count the number of + successful HDCP1 connection. + +What: /sys/devices/platform/hdcp/hdcp1_fail_count +Date: October 2023 +KernelVersion: 5.15 +Contact: "Ji Soo Shin" <jisshin@google.com> +Description: + DisplayPort stats uses this interface to count the number of + HDCP1 connection attempt that failed. + +What: /sys/devices/platform/hdcp/hdcp0_count +Date: October 2023 +KernelVersion: 5.15 +Contact: "Ji Soo Shin" <jisshin@google.com> +Description: + DisplayPort stats uses this interface to count the number of + connections that is incapable of HDCP. diff --git a/auth-control.c b/auth-control.c index bcd2d2d..00df17b 100644 --- a/auth-control.c +++ b/auth-control.c @@ -17,12 +17,13 @@ #include "auth-control.h" #include "auth13.h" #include "auth22.h" +#include "hdcp.h" #include "hdcp-log.h" #include "teeif.h" #define HDCP_SCHEDULE_DELAY_MSEC (5000) -static struct delayed_work hdcp_work; +static struct hdcp_device *hdcp_dev; static enum auth_state state; @@ -49,7 +50,7 @@ static int run_hdcp2_auth(void) { hdcp_tee_enable_enc_22(); return 0; } else if (ret != -EAGAIN) { - return -EIO; + return ret; } hdcp_info("HDCP22 Retry...\n"); } @@ -58,12 +59,22 @@ static int run_hdcp2_auth(void) { } static void hdcp_worker(struct work_struct *work) { + int ret; + bool hdcp2_capable = false; + bool hdcp1_capable = false; + + struct hdcp_device *hdcp_dev = + container_of(work, struct hdcp_device, hdcp_work.work); + if (max_ver >= 2) { hdcp_info("Trying HDCP22...\n"); - if (run_hdcp2_auth() == 0) { + ret = run_hdcp2_auth(); + if (ret == 0) { hdcp_info("HDCP22 Authentication Success\n"); + hdcp_dev->hdcp2_success_count++; return; } + hdcp2_capable = (ret != -EOPNOTSUPP); hdcp_info("HDCP22 Authentication Failed.\n"); } else { hdcp_info("Not trying HDCP22. max_ver is %lu\n", max_ver); @@ -72,29 +83,37 @@ static void hdcp_worker(struct work_struct *work) { if (max_ver >= 1) { hdcp_info("Trying HDCP13...\n"); state = HDCP1_AUTH_PROGRESS; - if (hdcp13_dplink_authenticate() == 0) { + ret = hdcp13_dplink_authenticate(); + if (ret == 0) { hdcp_info("HDCP13 Authentication Success\n"); state = HDCP1_AUTH_DONE; + hdcp_dev->hdcp2_fallback_count += hdcp2_capable; + hdcp_dev->hdcp1_success_count += !hdcp2_capable; return; } state = HDCP_AUTH_IDLE; + hdcp1_capable = (ret != -EOPNOTSUPP); hdcp_info("HDCP13 Authentication Failed.\n"); } else { hdcp_info("Not trying HDCP13. max_ver is %lu\n", max_ver); } + + hdcp_dev->hdcp2_fail_count += (hdcp2_capable); + hdcp_dev->hdcp1_fail_count += (!hdcp2_capable && hdcp1_capable); + hdcp_dev->hdcp0_count += (!hdcp2_capable && !hdcp1_capable); } void hdcp_dplink_handle_irq(void) { if (state == HDCP2_AUTH_PROGRESS || state == HDCP2_AUTH_DONE) { if (hdcp22_dplink_handle_irq() == -EAGAIN) - schedule_delayed_work(&hdcp_work, 0); + schedule_delayed_work(&hdcp_dev->hdcp_work, 0); return; } if (state == HDCP1_AUTH_DONE) { if (hdcp13_dplink_handle_irq() == -EAGAIN) - schedule_delayed_work(&hdcp_work, 0); + schedule_delayed_work(&hdcp_dev->hdcp_work, 0); return; } } @@ -109,20 +128,31 @@ void hdcp_dplink_connect_state(enum dp_state dp_hdcp_state) { hdcp22_dplink_abort(); hdcp_tee_disable_enc(); state = HDCP_AUTH_IDLE; - if (delayed_work_pending(&hdcp_work)) - cancel_delayed_work(&hdcp_work); + if (delayed_work_pending(&hdcp_dev->hdcp_work)) + cancel_delayed_work(&hdcp_dev->hdcp_work); return; } - schedule_delayed_work(&hdcp_work, msecs_to_jiffies(HDCP_SCHEDULE_DELAY_MSEC)); + schedule_delayed_work(&hdcp_dev->hdcp_work, + msecs_to_jiffies(HDCP_SCHEDULE_DELAY_MSEC)); return; } EXPORT_SYMBOL_GPL(hdcp_dplink_connect_state); -void hdcp_auth_worker_init(void) { - INIT_DELAYED_WORK(&hdcp_work, hdcp_worker); +int hdcp_auth_worker_init(struct hdcp_device *dev) { + if (hdcp_dev) + return -EACCES; + + hdcp_dev = dev; + INIT_DELAYED_WORK(&hdcp_dev->hdcp_work, hdcp_worker); + return 0; } -void hdcp_auth_worker_deinit(void) { - cancel_delayed_work_sync(&hdcp_work); +int hdcp_auth_worker_deinit(struct hdcp_device *dev) { + if (hdcp_dev != dev) + return -EACCES; + + cancel_delayed_work_sync(&hdcp_dev->hdcp_work); + hdcp_dev = NULL; + return 0; } diff --git a/auth-control.h b/auth-control.h index 340a778..6bd753e 100644 --- a/auth-control.h +++ b/auth-control.h @@ -11,6 +11,8 @@ #ifndef __EXYNOS_HDCP_AUTH_CONTROL_H__ #define __EXYNOS_HDCP_AUTH_CONTROL_H__ +struct hdcp_device; + enum auth_state { HDCP_AUTH_IDLE, HDCP1_AUTH_PROGRESS, @@ -21,7 +23,7 @@ enum auth_state { int hdcp_get_auth_state(void); -void hdcp_auth_worker_init(void); -void hdcp_auth_worker_deinit(void); +int hdcp_auth_worker_init(struct hdcp_device *dev); +int hdcp_auth_worker_deinit(struct hdcp_device *dev); #endif @@ -188,12 +188,12 @@ int hdcp13_dplink_authenticate(void) ret = hdcp_dplink_recv(DP_AUX_HDCP_BCAPS, &bcaps, sizeof(bcaps)); if (ret) { hdcp_err("BCaps Read failure (%d)\n", ret); - return -EIO; + return -EOPNOTSUPP; } if (!(bcaps & DP_BCAPS_HDCP_CAPABLE)) { hdcp_err("HDCP13 is not supported\n"); - return -EIO; + return -EOPNOTSUPP; } ret = hdcp_dplink_recv(DP_AUX_HDCP_BKSV, (uint8_t*)&bksv, HDCP_BKSV_SIZE); @@ -82,6 +82,7 @@ int hdcp22_dplink_authenticate(void) UPDATE_LINK_STATE(lk_data, LINK_ST_A1_EXCHANGE_MASTER_KEY); } else { UPDATE_LINK_STATE(lk_data, LINK_ST_H1_TX_LOW_VALUE_CONTENT); + return -EOPNOTSUPP; } break; case LINK_ST_A1_EXCHANGE_MASTER_KEY: @@ -0,0 +1,23 @@ +/* SPDX-License-Identifier: GPL-2.0-only + * + * HDCP platform device headerpanel common utility header + * + * Copyright (c) 2022 Google LLC + */ +#ifndef __EXYNOS_HDCP_H__ +#define __EXYNOS_HDCP_H__ + +struct hdcp_device { + struct device *dev; + struct delayed_work hdcp_work; + + /* HDCP Telemetry */ + uint32_t hdcp2_success_count; + uint32_t hdcp2_fallback_count; + uint32_t hdcp2_fail_count; + uint32_t hdcp1_success_count; + uint32_t hdcp1_fail_count; + uint32_t hdcp0_count; +}; + +#endif @@ -26,6 +26,7 @@ #include "exynos-hdcp-interface.h" #include "auth-control.h" +#include "hdcp.h" #include "hdcp-log.h" #include "selftest.h" #include "teeif.h" @@ -48,8 +49,94 @@ static ssize_t hdcp_read(struct file *filp, char __user *buf, return 0; } +static ssize_t hdcp2_success_count_show(struct device *dev, struct device_attribute *attr, + char *buf) +{ + struct hdcp_device *hdcp = dev_get_drvdata(dev); + + return sysfs_emit(buf, "%u\n", hdcp->hdcp2_success_count); +} +static DEVICE_ATTR_RO(hdcp2_success_count); + +static ssize_t hdcp2_fallback_count_show(struct device *dev, struct device_attribute *attr, + char *buf) +{ + struct hdcp_device *hdcp = dev_get_drvdata(dev); + + return sysfs_emit(buf, "%u\n", hdcp->hdcp2_fallback_count); +} +static DEVICE_ATTR_RO(hdcp2_fallback_count); + +static ssize_t hdcp2_fail_count_show(struct device *dev, struct device_attribute *attr, + char *buf) +{ + struct hdcp_device *hdcp = dev_get_drvdata(dev); + + return sysfs_emit(buf, "%u\n", hdcp->hdcp2_fail_count); +} +static DEVICE_ATTR_RO(hdcp2_fail_count); + +static ssize_t hdcp1_success_count_show(struct device *dev, struct device_attribute *attr, + char *buf) +{ + struct hdcp_device *hdcp = dev_get_drvdata(dev); + + return sysfs_emit(buf, "%u\n", hdcp->hdcp1_success_count); +} +static DEVICE_ATTR_RO(hdcp1_success_count); + +static ssize_t hdcp1_fail_count_show(struct device *dev, struct device_attribute *attr, + char *buf) +{ + struct hdcp_device *hdcp = dev_get_drvdata(dev); + + return sysfs_emit(buf, "%u\n", hdcp->hdcp1_fail_count); +} +static DEVICE_ATTR_RO(hdcp1_fail_count); + +static ssize_t hdcp0_count_show(struct device *dev, struct device_attribute *attr, + char *buf) +{ + struct hdcp_device *hdcp = dev_get_drvdata(dev); + + return sysfs_emit(buf, "%u\n", hdcp->hdcp0_count); +} +static DEVICE_ATTR_RO(hdcp0_count); + +static const struct attribute *hdcp_attrs[] = { + &dev_attr_hdcp2_success_count.attr, + &dev_attr_hdcp2_fallback_count.attr, + &dev_attr_hdcp2_fail_count.attr, + &dev_attr_hdcp1_success_count.attr, + &dev_attr_hdcp1_fail_count.attr, + &dev_attr_hdcp0_count.attr, + NULL }; + static int exynos_hdcp_probe(struct platform_device *pdev) { + struct device *dev = &pdev->dev; + struct hdcp_device *hdcp_dev = NULL; + int ret = 0; + + hdcp_dev = devm_kzalloc(dev, sizeof(struct hdcp_device), GFP_KERNEL); + if (!hdcp_dev) { + return -ENOMEM; + } + hdcp_dev->dev = dev; + platform_set_drvdata(pdev, hdcp_dev); + hdcp_auth_worker_init(hdcp_dev); + + ret = sysfs_create_files(&dev->kobj, hdcp_attrs); + if (ret) + dev_err(dev, "failed to create hdcp sysfs files\n"); + + return 0; +} + +static int exynos_hdcp_remove(struct platform_device *pdev) +{ + struct hdcp_device *hdcp_dev = platform_get_drvdata(pdev); + hdcp_auth_worker_deinit(hdcp_dev); return 0; } @@ -60,6 +147,7 @@ static const struct of_device_id exynos_hdcp_of_match_table[] = { static struct platform_driver exynos_hdcp_driver = { .probe = exynos_hdcp_probe, + .remove = exynos_hdcp_remove, .driver = { .name = "exynos-hdcp", .owner = THIS_MODULE, @@ -81,8 +169,6 @@ static int __init hdcp_init(void) } hdcp_tee_init(); - hdcp_auth_worker_init(); - return platform_driver_register(&exynos_hdcp_driver); } @@ -90,7 +176,6 @@ static void __exit hdcp_exit(void) { misc_deregister(&hdcp); hdcp_tee_close(); - hdcp_auth_worker_deinit(); platform_driver_unregister(&exynos_hdcp_driver); } |