mirror of
https://github.com/torvalds/linux.git
synced 2026-09-22 04:34:03 +02:00
media: cec-pin: Fix event FIFO ordering
cec_pin_update() fills work_pin_events[] and work_pin_ts[], then
increments work_pin_num_events. cec_pin_thread_func() uses that counter
to decide when to read the FIFO entries.
Do not let the counter update be observed without the event update. Also
do not let a freed slot be reused before the thread has finished reading
it. Use release operations when publishing an entry and releasing a slot,
and acquire operations when consuming those counter updates.
Leave the other work_pin_num_events users as they do not participate in
this FIFO publication path.
Fixes: ea5c8ef296 ("media: cec-pin: add low-level pin hardware support")
Signed-off-by: Gui-Dong Han <hanguidong02@gmail.com>
Signed-off-by: Hans Verkuil <hverkuil+cisco@kernel.org>
This commit is contained in:
parent
3bc2e4a264
commit
a1d83d1b81
|
|
@ -115,7 +115,7 @@ static void cec_pin_update(struct cec_pin *pin, bool v, bool force)
|
|||
return;
|
||||
|
||||
pin->adap->cec_pin_is_high = v;
|
||||
if (atomic_read(&pin->work_pin_num_events) < CEC_NUM_PIN_EVENTS) {
|
||||
if (atomic_read_acquire(&pin->work_pin_num_events) < CEC_NUM_PIN_EVENTS) {
|
||||
u8 ev = v;
|
||||
|
||||
if (pin->work_pin_events_dropped) {
|
||||
|
|
@ -126,7 +126,7 @@ static void cec_pin_update(struct cec_pin *pin, bool v, bool force)
|
|||
pin->work_pin_ts[pin->work_pin_events_wr] = ktime_get();
|
||||
pin->work_pin_events_wr =
|
||||
(pin->work_pin_events_wr + 1) % CEC_NUM_PIN_EVENTS;
|
||||
atomic_inc(&pin->work_pin_num_events);
|
||||
atomic_inc_return_release(&pin->work_pin_num_events);
|
||||
} else {
|
||||
pin->work_pin_events_dropped = true;
|
||||
pin->work_pin_events_dropped_cnt++;
|
||||
|
|
@ -1101,7 +1101,7 @@ static int cec_pin_thread_func(void *_adap)
|
|||
pin->work_tx_ts);
|
||||
}
|
||||
|
||||
while (atomic_read(&pin->work_pin_num_events)) {
|
||||
while (atomic_read_acquire(&pin->work_pin_num_events)) {
|
||||
unsigned int idx = pin->work_pin_events_rd;
|
||||
u8 v = pin->work_pin_events[idx];
|
||||
|
||||
|
|
@ -1110,7 +1110,7 @@ static int cec_pin_thread_func(void *_adap)
|
|||
v & CEC_PIN_EVENT_FL_DROPPED,
|
||||
pin->work_pin_ts[idx]);
|
||||
pin->work_pin_events_rd = (idx + 1) % CEC_NUM_PIN_EVENTS;
|
||||
atomic_dec(&pin->work_pin_num_events);
|
||||
atomic_dec_return_release(&pin->work_pin_num_events);
|
||||
}
|
||||
|
||||
switch (atomic_xchg(&pin->work_irq_change,
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user