diff options
author | Hans Verkuil <hverkuil-cisco@xs4all.nl> | 2023-10-11 11:17:59 +0300 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@kernel.org> | 2023-11-23 14:59:24 +0300 |
commit | 632b8b044a940e415c6d9bd5235778b0db28add1 (patch) | |
tree | 879ce71e7763b96600414dbcebd810bed7283c25 | |
parent | bbd267daf4fc831f58bf4a2530a8b64881779e6a (diff) | |
download | linux-632b8b044a940e415c6d9bd5235778b0db28add1.tar.xz |
media: cec: core: count low-drive, error and arb-lost conditions
Count how many Low Drive, Error and Arbitration Lost transmit
status errors occurred, and expose that in debugfs.
Also log the first 8 transmits that result in Low Drive or Error
conditions. That really should not happen with well-behaved CEC devices
and good HDMI cables.
This is useful to detect and debug HDMI cable issues.
Signed-off-by: Hans Verkuil <hverkuil-cisco@xs4all.nl>
Signed-off-by: Mauro Carvalho Chehab <mchehab@kernel.org>
-rw-r--r-- | drivers/media/cec/core/cec-adap.c | 54 | ||||
-rw-r--r-- | include/media/cec.h | 22 |
2 files changed, 69 insertions, 7 deletions
diff --git a/drivers/media/cec/core/cec-adap.c b/drivers/media/cec/core/cec-adap.c index 6bb49bb3f98c..5741adf09a2e 100644 --- a/drivers/media/cec/core/cec-adap.c +++ b/drivers/media/cec/core/cec-adap.c @@ -511,7 +511,7 @@ int cec_thread_func(void *_adap) pr_warn("cec-%s: transmit timed out\n", adap->name); } adap->transmit_in_progress = false; - adap->tx_timeouts++; + adap->tx_timeout_cnt++; goto unlock; } @@ -625,6 +625,33 @@ void cec_transmit_done_ts(struct cec_adapter *adap, u8 status, msg->tx_low_drive_cnt += low_drive_cnt; msg->tx_error_cnt += error_cnt; + adap->tx_arb_lost_cnt += arb_lost_cnt; + adap->tx_low_drive_cnt += low_drive_cnt; + adap->tx_error_cnt += error_cnt; + + /* + * Low Drive transmission errors should really not happen for + * well-behaved CEC devices and proper HDMI cables. + * + * Ditto for the 'Error' status. + * + * For the first few times that this happens, log this. + * Stop logging after that, since that will not add any more + * useful information and instead it will just flood the kernel log. + */ + if (done && adap->tx_low_drive_log_cnt < 8 && msg->tx_low_drive_cnt) { + adap->tx_low_drive_log_cnt++; + dprintk(0, "low drive counter: %u (seq %u: %*ph)\n", + msg->tx_low_drive_cnt, msg->sequence, + msg->len, msg->msg); + } + if (done && adap->tx_error_log_cnt < 8 && msg->tx_error_cnt) { + adap->tx_error_log_cnt++; + dprintk(0, "error counter: %u (seq %u: %*ph)\n", + msg->tx_error_cnt, msg->sequence, + msg->len, msg->msg); + } + /* Mark that we're done with this transmit */ adap->transmitting = NULL; @@ -1607,6 +1634,8 @@ int cec_adap_enable(struct cec_adapter *adap) if (enable) { adap->last_initiator = 0xff; adap->transmit_in_progress = false; + adap->tx_low_drive_log_cnt = 0; + adap->tx_error_log_cnt = 0; ret = adap->ops->adap_enable(adap, true); if (!ret) { /* @@ -2265,10 +2294,25 @@ int cec_adap_status(struct seq_file *file, void *priv) if (adap->monitor_pin_cnt) seq_printf(file, "file handles in Monitor Pin mode: %u\n", adap->monitor_pin_cnt); - if (adap->tx_timeouts) { - seq_printf(file, "transmit timeouts: %u\n", - adap->tx_timeouts); - adap->tx_timeouts = 0; + if (adap->tx_timeout_cnt) { + seq_printf(file, "transmit timeout count: %u\n", + adap->tx_timeout_cnt); + adap->tx_timeout_cnt = 0; + } + if (adap->tx_low_drive_cnt) { + seq_printf(file, "transmit low drive count: %u\n", + adap->tx_low_drive_cnt); + adap->tx_low_drive_cnt = 0; + } + if (adap->tx_arb_lost_cnt) { + seq_printf(file, "transmit arbitration lost count: %u\n", + adap->tx_arb_lost_cnt); + adap->tx_arb_lost_cnt = 0; + } + if (adap->tx_error_cnt) { + seq_printf(file, "transmit error count: %u\n", + adap->tx_error_cnt); + adap->tx_error_cnt = 0; } data = adap->transmitting; if (data) diff --git a/include/media/cec.h b/include/media/cec.h index 53e4b2eb2b26..d77982685116 100644 --- a/include/media/cec.h +++ b/include/media/cec.h @@ -207,7 +207,20 @@ struct cec_adap_ops { * passthrough mode. * @log_addrs: current logical addresses * @conn_info: current connector info - * @tx_timeouts: number of transmit timeouts + * @tx_timeout_cnt: count the number of Timed Out transmits. + * Reset to 0 when this is reported in cec_adap_status(). + * @tx_low_drive_cnt: count the number of Low Drive transmits. + * Reset to 0 when this is reported in cec_adap_status(). + * @tx_error_cnt: count the number of Error transmits. + * Reset to 0 when this is reported in cec_adap_status(). + * @tx_arb_lost_cnt: count the number of Arb Lost transmits. + * Reset to 0 when this is reported in cec_adap_status(). + * @tx_low_drive_log_cnt: number of logged Low Drive transmits since the + * adapter was enabled. Used to avoid flooding the kernel + * log if this happens a lot. + * @tx_error_log_cnt: number of logged Error transmits since the adapter was + * enabled. Used to avoid flooding the kernel log if this + * happens a lot. * @notifier: CEC notifier * @pin: CEC pin status struct * @cec_dir: debugfs cec directory @@ -262,7 +275,12 @@ struct cec_adapter { struct cec_log_addrs log_addrs; struct cec_connector_info conn_info; - u32 tx_timeouts; + u32 tx_timeout_cnt; + u32 tx_low_drive_cnt; + u32 tx_error_cnt; + u32 tx_arb_lost_cnt; + u32 tx_low_drive_log_cnt; + u32 tx_error_log_cnt; #ifdef CONFIG_CEC_NOTIFIER struct cec_notifier *notifier; |