mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-11-11 04:18:39 +08:00
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 <hverkuil-cisco@xs4all.nl> Signed-off-by: Mauro Carvalho Chehab <mchehab@kernel.org>
This commit is contained in:
parent
3b7dab49c4
commit
9b79d776a2
@ -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;
|
||||
|
@ -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);
|
||||
|
Loading…
Reference in New Issue
Block a user