If the physical address changes (i.e. becomes invalid, then valid again) while the adapter is still claiming free logical addresses, then trigger a reconfiguration since any claimed LAs may now be stale. Signed-off-by: Hans Verkuil <hverkuil-cisco@xxxxxxxxx> --- drivers/media/cec/core/cec-adap.c | 20 +++++++++++++++++++- include/media/cec.h | 2 ++ 2 files changed, 21 insertions(+), 1 deletion(-) diff --git a/drivers/media/cec/core/cec-adap.c b/drivers/media/cec/core/cec-adap.c index 6c235503dd92..38c43a37133d 100644 --- a/drivers/media/cec/core/cec-adap.c +++ b/drivers/media/cec/core/cec-adap.c @@ -1278,6 +1278,10 @@ static int cec_config_log_addr(struct cec_adapter *adap, if (adap->phys_addr == CEC_PHYS_ADDR_INVALID) return -EINTR; + /* Also bail out if the PA changed while configuring. */ + if (adap->must_reconfigure) + return -EINTR; + if (err) return err; @@ -1405,6 +1409,7 @@ static int cec_config_thread_func(void *arg) if (las->log_addr_type[0] == CEC_LOG_ADDR_TYPE_UNREGISTERED) goto configured; +reconfigure: for (i = 0; i < las->num_log_addrs; i++) { unsigned int type = las->log_addr_type[i]; const u8 *la_list; @@ -1427,6 +1432,13 @@ static int cec_config_thread_func(void *arg) last_la = la_list[0]; err = cec_config_log_addr(adap, i, last_la); + + if (adap->must_reconfigure) { + adap->must_reconfigure = false; + las->log_addr_mask = 0; + goto reconfigure; + } + if (err > 0) /* Reused last LA */ continue; @@ -1472,6 +1484,7 @@ static int cec_config_thread_func(void *arg) las->log_addr[i] = CEC_LOG_ADDR_INVALID; adap->is_configured = true; adap->is_configuring = false; + adap->must_reconfigure = false; cec_post_state_event(adap); /* @@ -1526,6 +1539,7 @@ static int cec_config_thread_func(void *arg) las->log_addr[i] = CEC_LOG_ADDR_INVALID; cec_adap_unconfigure(adap); adap->is_configuring = false; + adap->must_reconfigure = false; adap->kthread_config = NULL; complete(&adap->config_completion); mutex_unlock(&adap->lock); @@ -1649,7 +1663,11 @@ void __cec_s_phys_addr(struct cec_adapter *adap, u16 phys_addr, bool block) adap->phys_addr = phys_addr; cec_post_state_event(adap); - if (adap->log_addrs.num_log_addrs) + if (!adap->log_addrs.num_log_addrs) + return; + if (adap->is_configuring) + adap->must_reconfigure = true; + else cec_claim_log_addrs(adap, block); } diff --git a/include/media/cec.h b/include/media/cec.h index 6f13b0222aa3..6c9b41fe9802 100644 --- a/include/media/cec.h +++ b/include/media/cec.h @@ -184,6 +184,7 @@ struct cec_adap_ops { * in order to transmit or receive CEC messages. This is usually a HW * limitation. * @is_configuring: the CEC adapter is configuring (i.e. claiming LAs) + * @must_reconfigure: while configuring, the PA changed, so reclaim LAs * @is_configured: the CEC adapter is configured (i.e. has claimed LAs) * @cec_pin_is_high: if true then the CEC pin is high. Only used with the * CEC pin framework. @@ -243,6 +244,7 @@ struct cec_adapter { u16 phys_addr; bool needs_hpd; bool is_configuring; + bool must_reconfigure; bool is_configured; bool cec_pin_is_high; bool adap_controls_phys_addr; -- 2.34.1