]> git.karo-electronics.de Git - karo-tx-linux.git/blobdiff - drivers/media/cec/cec-adap.c
[media] cec: allow specific messages even when unconfigured
[karo-tx-linux.git] / drivers / media / cec / cec-adap.c
index 421472b492ee87c28a1c78deeb371252ceeb2b8a..78a85c44d96efaf6393d928c4cdfd63b8b2e0447 100644 (file)
@@ -367,7 +367,6 @@ int cec_thread_func(void *_adap)
                         */
                        err = wait_event_interruptible_timeout(adap->kthread_waitq,
                                kthread_should_stop() ||
-                               (!adap->is_configured && !adap->is_configuring) ||
                                (!adap->transmitting &&
                                 !list_empty(&adap->transmit_queue)),
                                msecs_to_jiffies(CEC_XFER_TIMEOUT_MS));
@@ -382,8 +381,7 @@ int cec_thread_func(void *_adap)
 
                mutex_lock(&adap->lock);
 
-               if ((!adap->is_configured && !adap->is_configuring) ||
-                   kthread_should_stop()) {
+               if (kthread_should_stop()) {
                        cec_flush(adap);
                        goto unlock;
                }
@@ -414,6 +412,7 @@ int cec_thread_func(void *_adap)
                                        struct cec_data, list);
                list_del_init(&data->list);
                adap->transmit_queue_sz--;
+
                /* Make this the current transmitting message */
                adap->transmitting = data;
 
@@ -647,7 +646,8 @@ int cec_transmit_msg_fh(struct cec_adapter *adap, struct cec_msg *msg,
                        cec_msg_initiator(msg));
                return -EINVAL;
        }
-       if (!adap->is_configured && !adap->is_configuring)
+       if (!adap->is_configured && !adap->is_configuring &&
+           (msg->msg[0] != 0xf0 || msg->reply))
                return -ENONET;
 
        if (adap->transmit_queue_sz >= CEC_MAX_MSG_TX_QUEUE_SZ)
@@ -696,6 +696,7 @@ int cec_transmit_msg_fh(struct cec_adapter *adap, struct cec_msg *msg,
 
        if (fh)
                list_add_tail(&data->xfer_list, &fh->xfer_list);
+
        list_add_tail(&data->list, &adap->transmit_queue);
        adap->transmit_queue_sz++;
        if (!adap->transmitting)
@@ -1121,6 +1122,7 @@ static void cec_adap_unconfigure(struct cec_adapter *adap)
        adap->is_configuring = false;
        adap->is_configured = false;
        memset(adap->phys_addrs, 0xff, sizeof(adap->phys_addrs));
+       cec_flush(adap);
        wake_up_interruptible(&adap->kthread_waitq);
        cec_post_state_event(adap);
 }
@@ -1352,19 +1354,30 @@ void __cec_s_phys_addr(struct cec_adapter *adap, u16 phys_addr, bool block)
                /* Disabling monitor all mode should always succeed */
                if (adap->monitor_all_cnt)
                        WARN_ON(call_op(adap, adap_monitor_all_enable, false));
-               WARN_ON(adap->ops->adap_enable(adap, false));
+               mutex_lock(&adap->devnode.lock);
+               if (list_empty(&adap->devnode.fhs))
+                       WARN_ON(adap->ops->adap_enable(adap, false));
+               mutex_unlock(&adap->devnode.lock);
                if (phys_addr == CEC_PHYS_ADDR_INVALID)
                        return;
        }
 
-       if (adap->ops->adap_enable(adap, true))
+       mutex_lock(&adap->devnode.lock);
+       if (list_empty(&adap->devnode.fhs) &&
+           adap->ops->adap_enable(adap, true)) {
+               mutex_unlock(&adap->devnode.lock);
                return;
+       }
 
        if (adap->monitor_all_cnt &&
            call_op(adap, adap_monitor_all_enable, true)) {
-               WARN_ON(adap->ops->adap_enable(adap, false));
+               if (list_empty(&adap->devnode.fhs))
+                       WARN_ON(adap->ops->adap_enable(adap, false));
+               mutex_unlock(&adap->devnode.lock);
                return;
        }
+       mutex_unlock(&adap->devnode.lock);
+
        adap->phys_addr = phys_addr;
        cec_post_state_event(adap);
        if (adap->log_addrs.num_log_addrs)