diff options
-rw-r--r-- | drivers/media/cec/cec-adap.c | 27 | ||||
-rw-r--r-- | include/media/cec.h | 1 |
2 files changed, 19 insertions, 9 deletions
diff --git a/drivers/media/cec/cec-adap.c b/drivers/media/cec/cec-adap.c index 5b7fe4796022..f1261cc2b6fa 100644 --- a/drivers/media/cec/cec-adap.c +++ b/drivers/media/cec/cec-adap.c @@ -455,7 +455,7 @@ int cec_thread_func(void *_adap) (adap->needs_hpd && (!adap->is_configured && !adap->is_configuring)) || kthread_should_stop() || - (!adap->transmitting && + (!adap->transmit_in_progress && !list_empty(&adap->transmit_queue)), msecs_to_jiffies(CEC_XFER_TIMEOUT_MS)); timeout = err == 0; @@ -463,7 +463,7 @@ int cec_thread_func(void *_adap) /* Otherwise we just wait for something to happen. */ wait_event_interruptible(adap->kthread_waitq, kthread_should_stop() || - (!adap->transmitting && + (!adap->transmit_in_progress && !list_empty(&adap->transmit_queue))); } @@ -488,6 +488,7 @@ int cec_thread_func(void *_adap) pr_warn("cec-%s: message %*ph timed out\n", adap->name, adap->transmitting->msg.len, adap->transmitting->msg.msg); + adap->transmit_in_progress = false; adap->tx_timeouts++; /* Just give up on this. */ cec_data_cancel(adap->transmitting, @@ -499,7 +500,7 @@ int cec_thread_func(void *_adap) * If we are still transmitting, or there is nothing new to * transmit, then just continue waiting. */ - if (adap->transmitting || list_empty(&adap->transmit_queue)) + if (adap->transmit_in_progress || list_empty(&adap->transmit_queue)) goto unlock; /* Get a new message to transmit */ @@ -545,6 +546,8 @@ int cec_thread_func(void *_adap) if (adap->ops->adap_transmit(adap, data->attempts, signal_free_time, &data->msg)) cec_data_cancel(data, CEC_TX_STATUS_ABORTED); + else + adap->transmit_in_progress = true; unlock: mutex_unlock(&adap->lock); @@ -575,14 +578,17 @@ void cec_transmit_done_ts(struct cec_adapter *adap, u8 status, data = adap->transmitting; if (!data) { /* - * This can happen if a transmit was issued and the cable is + * This might happen if a transmit was issued and the cable is * unplugged while the transmit is ongoing. Ignore this * transmit in that case. */ - dprintk(1, "%s was called without an ongoing transmit!\n", - __func__); - goto unlock; + if (!adap->transmit_in_progress) + dprintk(1, "%s was called without an ongoing transmit!\n", + __func__); + adap->transmit_in_progress = false; + goto wake_thread; } + adap->transmit_in_progress = false; msg = &data->msg; @@ -648,7 +654,6 @@ wake_thread: * for transmitting or to retry the current message. */ wake_up_interruptible(&adap->kthread_waitq); -unlock: mutex_unlock(&adap->lock); } EXPORT_SYMBOL_GPL(cec_transmit_done_ts); @@ -1503,8 +1508,11 @@ void __cec_s_phys_addr(struct cec_adapter *adap, u16 phys_addr, bool block) if (adap->monitor_all_cnt) WARN_ON(call_op(adap, adap_monitor_all_enable, false)); mutex_lock(&adap->devnode.lock); - if (adap->needs_hpd || list_empty(&adap->devnode.fhs)) + if (adap->needs_hpd || list_empty(&adap->devnode.fhs)) { WARN_ON(adap->ops->adap_enable(adap, false)); + adap->transmit_in_progress = false; + wake_up_interruptible(&adap->kthread_waitq); + } mutex_unlock(&adap->devnode.lock); if (phys_addr == CEC_PHYS_ADDR_INVALID) return; @@ -1512,6 +1520,7 @@ void __cec_s_phys_addr(struct cec_adapter *adap, u16 phys_addr, bool block) mutex_lock(&adap->devnode.lock); adap->last_initiator = 0xff; + adap->transmit_in_progress = false; if ((adap->needs_hpd || list_empty(&adap->devnode.fhs)) && adap->ops->adap_enable(adap, true)) { diff --git a/include/media/cec.h b/include/media/cec.h index 3fe5e5d2bb7e..707411ef8ba2 100644 --- a/include/media/cec.h +++ b/include/media/cec.h @@ -155,6 +155,7 @@ struct cec_adapter { unsigned int transmit_queue_sz; struct list_head wait_queue; struct cec_data *transmitting; + bool transmit_in_progress; struct task_struct *kthread_config; struct completion config_completion; |