lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [thread-next>] [day] [month] [year] [list]
Date:   Sun, 1 Sep 2019 19:45:38 +0000
From:   Jonas Karlman <jonas@...boo.se>
To:     Hans Verkuil <hverkuil-cisco@...all.nl>
CC:     Mauro Carvalho Chehab <mchehab@...nel.org>,
        "linux-media@...r.kernel.org" <linux-media@...r.kernel.org>,
        "linux-kernel@...r.kernel.org" <linux-kernel@...r.kernel.org>,
        Jonas Karlman <jonas@...boo.se>
Subject: [PATCH] media: cec-notifier: debounce reporing of invalid phys addr

When EDID is refreshed, HDMI cable is unplugged/replugged or
an AVR is power cycled the CEC phys addr gets invalidated.

This can cause some disruption of CEC communication when
adapter is being reconfigured.

Add a debounce option that can be used to debounce setting
an invalid phys addr.

Power off AVR (debounce = 0):
[  101.536866] cec-dw_hdmi: new physical address f.f.f.f
[  102.495686] cec-dw_hdmi: new physical address 2.1.0.0
[  102.495913] cec-dw_hdmi: physical address: 2.1.0.0, claim 1 logical addresses
[  102.628574] cec-dw_hdmi: config: la 1 pa 2.1.0.0
[  105.130115] cec-dw_hdmi: new physical address f.f.f.f
[  106.979705] cec-dw_hdmi: new physical address 2.1.0.0
[  106.979872] cec-dw_hdmi: physical address: 2.1.0.0, claim 1 logical addresses
[  107.112399] cec-dw_hdmi: config: la 1 pa 2.1.0.0
[  108.979408] cec-dw_hdmi: reported physical address 2.0.0.0 for logical address 5
[  109.205386] cec-dw_hdmi: reported physical address 2.0.0.0 for logical address 11

Power on AVR (debounce = 0):
[  158.398447] cec-dw_hdmi: new physical address f.f.f.f
[  161.977714] cec-dw_hdmi: new physical address 2.1.0.0
[  161.978766] cec-dw_hdmi: physical address: 2.1.0.0, claim 1 logical addresses
[  162.115624] cec-dw_hdmi: config: la 1 pa 2.1.0.0
[  162.402750] cec-dw_hdmi: new physical address f.f.f.f
[  162.403389] cec-dw_hdmi: cec_transmit_msg_fh: adapter is unconfigured
[  162.886757] cec-dw_hdmi: new physical address 2.1.0.0
[  162.886964] cec-dw_hdmi: physical address: 2.1.0.0, claim 1 logical addresses
[  163.510725] cec-dw_hdmi: config: la 1 pa 2.1.0.0
[  173.034200] cec-dw_hdmi: message 10 89 02 05 timed out

Power off AVR (debounce = 5000):
[  251.720471] cec-dw_hdmi: reported physical address 2.0.0.0 for logical address 5
[  251.922432] cec-dw_hdmi: reported physical address 2.0.0.0 for logical address 11

Power on AVR (debounce = 5000):
[  291.154262] cec-dw_hdmi: reported physical address 2.0.0.0 for logical address 5
[  291.296199] cec-dw_hdmi: reported physical address 2.0.0.0 for logical address 11

Using a debounce of 5000 ms reconfiguring can be avoided.

Signed-off-by: Jonas Karlman <jonas@...boo.se>
---
 drivers/media/cec/cec-core.c     |  4 ++++
 drivers/media/cec/cec-notifier.c | 23 ++++++++++++++++++++++-
 drivers/media/cec/cec-priv.h     |  1 +
 3 files changed, 27 insertions(+), 1 deletion(-)

diff --git a/drivers/media/cec/cec-core.c b/drivers/media/cec/cec-core.c
index 9c610e1e99b8..c5094fd9b664 100644
--- a/drivers/media/cec/cec-core.c
+++ b/drivers/media/cec/cec-core.c
@@ -28,6 +28,10 @@ static bool debug_phys_addr;
 module_param(debug_phys_addr, bool, 0644);
 MODULE_PARM_DESC(debug_phys_addr, "add CEC_CAP_PHYS_ADDR if set");
 
+int cec_debounce;
+module_param_named(debounce, cec_debounce, int, 0644);
+MODULE_PARM_DESC(debounce, "debounce invalid phys addr");
+
 static dev_t cec_dev_t;
 
 /* Active devices */
diff --git a/drivers/media/cec/cec-notifier.c b/drivers/media/cec/cec-notifier.c
index 4d82a5522072..0157d468cfe4 100644
--- a/drivers/media/cec/cec-notifier.c
+++ b/drivers/media/cec/cec-notifier.c
@@ -12,11 +12,14 @@
 #include <linux/list.h>
 #include <linux/kref.h>
 #include <linux/of_platform.h>
+#include <linux/workqueue.h>
 
 #include <media/cec.h>
 #include <media/cec-notifier.h>
 #include <drm/drm_edid.h>
 
+#include "cec-priv.h"
+
 struct cec_notifier {
 	struct mutex lock;
 	struct list_head head;
@@ -28,11 +31,25 @@ struct cec_notifier {
 	void (*callback)(struct cec_adapter *adap, u16 pa);
 
 	u16 phys_addr;
+	struct delayed_work work;
 };
 
 static LIST_HEAD(cec_notifiers);
 static DEFINE_MUTEX(cec_notifiers_lock);
 
+static void cec_notifier_delayed_work(struct work_struct *work)
+{
+	struct cec_notifier *n =
+		container_of(to_delayed_work(work), struct cec_notifier, work);
+
+	mutex_lock(&n->lock);
+	if (n->callback)
+		n->callback(n->cec_adap, n->phys_addr);
+	else if (n->cec_adap)
+		cec_s_phys_addr(n->cec_adap, n->phys_addr, false);
+	mutex_unlock(&n->lock);
+}
+
 struct cec_notifier *
 cec_notifier_get_conn(struct device *hdmi_dev, const char *conn_name)
 {
@@ -62,6 +79,7 @@ cec_notifier_get_conn(struct device *hdmi_dev, const char *conn_name)
 	}
 	n->phys_addr = CEC_PHYS_ADDR_INVALID;
 
+	INIT_DELAYED_WORK(&n->work, cec_notifier_delayed_work);
 	mutex_init(&n->lock);
 	kref_init(&n->kref);
 	list_add_tail(&n->head, &cec_notifiers);
@@ -172,9 +190,12 @@ void cec_notifier_set_phys_addr(struct cec_notifier *n, u16 pa)
 	if (n == NULL)
 		return;
 
+	cancel_delayed_work_sync(&n->work);
 	mutex_lock(&n->lock);
 	n->phys_addr = pa;
-	if (n->callback)
+	if (cec_debounce > 0 && pa == CEC_PHYS_ADDR_INVALID)
+		schedule_delayed_work(&n->work, msecs_to_jiffies(cec_debounce));
+	else if (n->callback)
 		n->callback(n->cec_adap, n->phys_addr);
 	else if (n->cec_adap)
 		cec_s_phys_addr(n->cec_adap, n->phys_addr, false);
diff --git a/drivers/media/cec/cec-priv.h b/drivers/media/cec/cec-priv.h
index 7bdf855aaecd..65176294fcf0 100644
--- a/drivers/media/cec/cec-priv.h
+++ b/drivers/media/cec/cec-priv.h
@@ -27,6 +27,7 @@ static inline bool msg_is_raw(const struct cec_msg *msg)
 
 /* cec-core.c */
 extern int cec_debug;
+extern int cec_debounce;
 int cec_get_device(struct cec_devnode *devnode);
 void cec_put_device(struct cec_devnode *devnode);
 
-- 
2.17.1

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ