media: cec/core: handle core events like normal events

Currently there is a distinction between core events
(CEC_EVENT_STATE_CHANGE and CEC_EVENT_LOST_MSGS) and other
events. The core events do not require memory allocations,
so are a bit faster, but they are also limited to just a
single event: if a new event comes in, then that replaces
the old one.

It's all overly complicated, and with only one state change
event it is easy to miss state changes.

So just drop that optimization, and allow for up to 3
state change events.

Signed-off-by: Hans Verkuil <hverkuil+cisco@kernel.org>
Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
This commit is contained in:
Hans Verkuil 2026-07-10 13:07:31 +02:00 committed by Mauro Carvalho Chehab
parent 0c138a5d50
commit 67d9598720
3 changed files with 18 additions and 23 deletions

View File

@ -80,9 +80,9 @@ void cec_queue_event_fh(struct cec_fh *fh,
const struct cec_event *new_ev, u64 ts)
{
static const u16 max_events[CEC_NUM_EVENTS] = {
1, 1, 800, 800, 8, 8, 8, 8
3, 1, 800, 800, 8, 8, 8, 8
};
struct cec_event_entry *entry;
struct cec_event_entry *new_entry, *entry;
unsigned int ev_idx = new_ev->event - 1;
if (WARN_ON(ev_idx >= ARRAY_SIZE(fh->events)))
@ -92,36 +92,34 @@ void cec_queue_event_fh(struct cec_fh *fh,
ts = ktime_get_ns();
mutex_lock(&fh->lock);
if (ev_idx < CEC_NUM_CORE_EVENTS)
entry = &fh->core_events[ev_idx];
else
entry = kmalloc_obj(*entry);
if (entry) {
new_entry = kmalloc_obj(*new_entry);
if (new_entry) {
if (new_ev->event == CEC_EVENT_LOST_MSGS &&
fh->queued_events[ev_idx]) {
entry = list_first_entry(&fh->events[ev_idx],
struct cec_event_entry, list);
entry->ev.lost_msgs.lost_msgs +=
new_ev->lost_msgs.lost_msgs;
kfree(new_entry);
goto unlock;
}
entry->ev = *new_ev;
entry->ev.ts = ts;
new_entry->ev = *new_ev;
new_entry->ev.ts = ts;
if (fh->queued_events[ev_idx] < max_events[ev_idx]) {
/* Add new msg at the end of the queue */
list_add_tail(&entry->list, &fh->events[ev_idx]);
list_add_tail(&new_entry->list, &fh->events[ev_idx]);
fh->queued_events[ev_idx]++;
fh->total_queued_events++;
goto unlock;
}
if (ev_idx >= CEC_NUM_CORE_EVENTS) {
list_add_tail(&entry->list, &fh->events[ev_idx]);
/* drop the oldest event */
entry = list_first_entry(&fh->events[ev_idx],
struct cec_event_entry, list);
list_del(&entry->list);
kfree(entry);
}
list_add_tail(&new_entry->list, &fh->events[ev_idx]);
/* drop the oldest event */
entry = list_first_entry(&fh->events[ev_idx],
struct cec_event_entry, list);
list_del(&entry->list);
kfree(entry);
}
/* Mark that events were lost */
entry = list_first_entry_or_null(&fh->events[ev_idx],

View File

@ -345,8 +345,7 @@ static long cec_dqevent(struct cec_adapter *adap, struct cec_fh *fh,
if (copy_to_user(parg, &ev->ev, sizeof(ev->ev)))
err = -EFAULT;
if (ev_idx >= CEC_NUM_CORE_EVENTS)
kfree(ev);
kfree(ev);
fh->queued_events[ev_idx]--;
fh->total_queued_events--;
@ -673,7 +672,7 @@ static int cec_release(struct inode *inode, struct file *filp)
list_del(&entry->list);
kfree(entry);
}
for (i = CEC_NUM_CORE_EVENTS; i < CEC_NUM_EVENTS; i++) {
for (i = 0; i < CEC_NUM_EVENTS; i++) {
while (!list_empty(&fh->events[i])) {
struct cec_event_entry *entry =
list_first_entry(&fh->events[i],

View File

@ -85,7 +85,6 @@ struct cec_event_entry {
struct cec_event ev;
};
#define CEC_NUM_CORE_EVENTS 2
#define CEC_NUM_EVENTS CEC_EVENT_PIN_5V_HIGH
struct cec_fh {
@ -101,7 +100,6 @@ struct cec_fh {
struct list_head events[CEC_NUM_EVENTS]; /* queued events */
u16 queued_events[CEC_NUM_EVENTS];
unsigned int total_queued_events;
struct cec_event_entry core_events[CEC_NUM_CORE_EVENTS];
struct list_head msgs; /* queued messages */
unsigned int queued_msgs;
};