adap->is_configured || adap->monitor_all_cnt)
break;
/* Switch to interrupt mode */
- pin->work_enable_irq = true;
+ atomic_set(&pin->work_irq_change, CEC_PIN_IRQ_ENABLE);
pin->state = CEC_ST_RX_IRQ;
wake_up_interruptible(&pin->kthread_waitq);
return HRTIMER_NORESTART;
kthread_should_stop() ||
pin->work_rx_msg.len ||
pin->work_tx_status ||
- pin->work_enable_irq ||
+ atomic_read(&pin->work_irq_change) ||
atomic_read(&pin->work_pin_events));
if (pin->work_rx_msg.len) {
cec_transmit_attempt_done_ts(adap, tx_status,
pin->work_tx_ts);
}
+
while (atomic_read(&pin->work_pin_events)) {
unsigned int idx = pin->work_pin_events_rd;
pin->work_pin_events_rd = (idx + 1) % CEC_NUM_PIN_EVENTS;
atomic_dec(&pin->work_pin_events);
}
- if (pin->work_enable_irq) {
- pin->work_enable_irq = false;
+
+ switch (atomic_xchg(&pin->work_irq_change,
+ CEC_PIN_IRQ_UNCHANGED)) {
+ case CEC_PIN_IRQ_DISABLE:
+ pin->ops->disable_irq(adap);
+ cec_pin_high(pin);
+ cec_pin_to_idle(pin);
+ hrtimer_start(&pin->timer, 0, HRTIMER_MODE_REL);
+ break;
+ case CEC_PIN_IRQ_ENABLE:
pin->enable_irq_failed = !pin->ops->enable_irq(adap);
if (pin->enable_irq_failed) {
cec_pin_to_idle(pin);
hrtimer_start(&pin->timer, 0, HRTIMER_MODE_REL);
}
+ break;
+ default:
+ break;
}
+
if (kthread_should_stop())
break;
}
cec_pin_to_idle(pin);
pin->tx_msg.len = 0;
pin->timer_ts = 0;
- pin->work_enable_irq = false;
+ atomic_set(&pin->work_irq_change, CEC_PIN_IRQ_UNCHANGED);
pin->kthread = kthread_run(cec_pin_thread_func, adap,
"cec-pin");
if (IS_ERR(pin->kthread)) {
pin->work_tx_status = 0;
pin->tx_bit = 0;
if (pin->state == CEC_ST_RX_IRQ) {
- pin->work_enable_irq = false;
+ atomic_set(&pin->work_irq_change, CEC_PIN_IRQ_UNCHANGED);
pin->ops->disable_irq(adap);
cec_pin_high(pin);
cec_pin_to_idle(pin);
cec_pin_update(pin, value, false);
if (!value && (adap->is_configuring || adap->is_configured ||
- adap->monitor_all_cnt)) {
- pin->work_enable_irq = false;
- pin->ops->disable_irq(adap);
- cec_pin_high(pin);
- cec_pin_to_idle(pin);
- hrtimer_start(&pin->timer, 0, HRTIMER_MODE_REL);
- }
+ adap->monitor_all_cnt))
+ atomic_set(&pin->work_irq_change, CEC_PIN_IRQ_DISABLE);
}
EXPORT_SYMBOL_GPL(cec_pin_changed);
#define CEC_NUM_PIN_EVENTS 128
+#define CEC_PIN_IRQ_UNCHANGED 0
+#define CEC_PIN_IRQ_DISABLE 1
+#define CEC_PIN_IRQ_ENABLE 2
+
struct cec_pin {
struct cec_adapter *adap;
const struct cec_pin_ops *ops;
struct cec_msg work_rx_msg;
u8 work_tx_status;
- bool work_enable_irq;
ktime_t work_tx_ts;
+ atomic_t work_irq_change;
atomic_t work_pin_events;
unsigned int work_pin_events_wr;
unsigned int work_pin_events_rd;