From: Hans Verkuil Date: Fri, 7 Jul 2023 11:26:39 +0000 (+0200) Subject: media: cec-pin: improve interrupt handling X-Git-Tag: v6.6.7~2014^2~177 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=9b79d776a2b3b2c6c121bd9e0faa71ba06ecd613;p=platform%2Fkernel%2Flinux-starfive.git media: cec-pin: improve interrupt handling The CEC pin framework needs a bit more control over the interrupt handling: make sure that the disable_irq op is called even if the device node is unregistered, log the state of the interrupt in debugfs, and disable the interrupt when the kernel thread is stopped. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- diff --git a/drivers/media/cec/core/cec-pin-priv.h b/drivers/media/cec/core/cec-pin-priv.h index 8eb5819..156a9f8 100644 --- a/drivers/media/cec/core/cec-pin-priv.h +++ b/drivers/media/cec/core/cec-pin-priv.h @@ -183,6 +183,7 @@ struct cec_pin { u16 la_mask; bool monitor_all; bool rx_eom; + bool enabled_irq; bool enable_irq_failed; enum cec_pin_state state; struct cec_msg tx_msg; diff --git a/drivers/media/cec/core/cec-pin.c b/drivers/media/cec/core/cec-pin.c index 68353c5..8a3921f 100644 --- a/drivers/media/cec/core/cec-pin.c +++ b/drivers/media/cec/core/cec-pin.c @@ -1033,8 +1033,9 @@ static int cec_pin_thread_func(void *_adap) { struct cec_adapter *adap = _adap; struct cec_pin *pin = adap->pin; - bool irq_enabled = false; + pin->enabled_irq = false; + pin->enable_irq_failed = false; for (;;) { wait_event_interruptible(pin->kthread_waitq, kthread_should_stop() || @@ -1088,9 +1089,10 @@ static int cec_pin_thread_func(void *_adap) switch (atomic_xchg(&pin->work_irq_change, CEC_PIN_IRQ_UNCHANGED)) { case CEC_PIN_IRQ_DISABLE: - if (irq_enabled) { - call_void_pin_op(pin, disable_irq); - irq_enabled = false; + if (pin->enabled_irq) { + pin->ops->disable_irq(adap); + pin->enabled_irq = false; + pin->enable_irq_failed = false; } cec_pin_high(pin); if (pin->state == CEC_ST_OFF) @@ -1100,21 +1102,29 @@ static int cec_pin_thread_func(void *_adap) HRTIMER_MODE_REL); break; case CEC_PIN_IRQ_ENABLE: - if (irq_enabled) + if (pin->enabled_irq || !pin->ops->enable_irq || + pin->adap->devnode.unregistered) break; - pin->enable_irq_failed = !call_pin_op(pin, enable_irq); + pin->enable_irq_failed = !pin->ops->enable_irq(adap); if (pin->enable_irq_failed) { cec_pin_to_idle(pin); hrtimer_start(&pin->timer, ns_to_ktime(0), HRTIMER_MODE_REL); } else { - irq_enabled = true; + pin->enabled_irq = true; } break; default: break; } } + + if (pin->enabled_irq) { + pin->ops->disable_irq(pin->adap); + pin->enabled_irq = false; + pin->enable_irq_failed = false; + cec_pin_high(pin); + } return 0; } @@ -1215,7 +1225,9 @@ static void cec_pin_adap_status(struct cec_adapter *adap, seq_printf(file, "cec pin: %d\n", call_pin_op(pin, read)); seq_printf(file, "cec pin events dropped: %u\n", pin->work_pin_events_dropped_cnt); - seq_printf(file, "irq failed: %d\n", pin->enable_irq_failed); + if (pin->ops->enable_irq) + seq_printf(file, "irq %s\n", pin->enabled_irq ? "enabled" : + (pin->enable_irq_failed ? "failed" : "disabled")); if (pin->timer_100us_overruns) { seq_printf(file, "timer overruns > 100us: %u of %u\n", pin->timer_100us_overruns, pin->timer_cnt);