]> git.baikalelectronics.ru Git - kernel.git/commitdiff
media: cec-adap.c: reconfigure if the PA changes during configuration
authorHans Verkuil <hverkuil-cisco@xs4all.nl>
Fri, 6 May 2022 12:46:46 +0000 (14:46 +0200)
committerMauro Carvalho Chehab <mchehab@kernel.org>
Fri, 13 May 2022 09:29:16 +0000 (11:29 +0200)
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@xs4all.nl>
Signed-off-by: Mauro Carvalho Chehab <mchehab@kernel.org>
drivers/media/cec/core/cec-adap.c
include/media/cec.h

index 6c235503dd92ad0c0e699bf58e877070753f95f8..38c43a37133ddf772911b93430503b84b76652b0 100644 (file)
@@ -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 @@ configured:
                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 @@ unconfigure:
                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);
 }
 
index 6f13b0222aa369e8b9e691a535fe2a2963875381..6c9b41fe98027bc45840d50017d01c27d3356e49 100644 (file)
@@ -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;