*/
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));
mutex_lock(&adap->lock);
- if ((!adap->is_configured && !adap->is_configuring) ||
- kthread_should_stop()) {
+ if (kthread_should_stop()) {
cec_flush(adap);
goto unlock;
}
struct cec_data, list);
list_del_init(&data->list);
adap->transmit_queue_sz--;
+
/* Make this the current transmitting message */
adap->transmitting = data;
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)
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)
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);
}
/* 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)
return -EINVAL;
mutex_lock(&adap->lock);
- if (!adap->is_configured)
+ if (adap->is_configuring)
+ err = -ENONET;
+ else if (!adap->is_configured && (msg.msg[0] != 0xf0 || msg.reply))
err = -ENONET;
else if (cec_is_busy(adap, fh))
err = -EBUSY;
return err;
}
+ mutex_lock(&devnode->lock);
+ if (list_empty(&devnode->fhs) &&
+ adap->phys_addr == CEC_PHYS_ADDR_INVALID) {
+ err = adap->ops->adap_enable(adap, true);
+ if (err) {
+ mutex_unlock(&devnode->lock);
+ kfree(fh);
+ return err;
+ }
+ }
filp->private_data = fh;
- mutex_lock(&devnode->lock);
/* Queue up initial state events */
ev_state.state_change.phys_addr = adap->phys_addr;
ev_state.state_change.log_addr_mask = adap->log_addrs.log_addr_mask;
mutex_lock(&devnode->lock);
list_del(&fh->list);
+ if (list_empty(&devnode->fhs) &&
+ adap->phys_addr == CEC_PHYS_ADDR_INVALID) {
+ WARN_ON(adap->ops->adap_enable(adap, false));
+ }
mutex_unlock(&devnode->lock);
/* Unhook pending transmits from this filehandle. */