diff options
author | Tomasz Michalec <tm@semihalf.com> | 2022-01-05 16:56:40 +0100 |
---|---|---|
committer | Commit Bot <commit-bot@chromium.org> | 2022-01-14 23:06:54 +0000 |
commit | 986675c62fd45eb53c0d316c8f6fa7124e913f34 (patch) | |
tree | 5dc5fd9fa9c675fe94e320fa4b81311190ac2086 | |
parent | d51254bcfeedeae83dd59170af31436e9f0c5126 (diff) | |
download | chrome-ec-986675c62fd45eb53c0d316c8f6fa7124e913f34.tar.gz |
zephyr: emul: Use thread for sending delayed TCPCI messages
Work queue which was used before doesn't guarantee that scheduled work
will execute at given time. Because of that some messages were delayed
by much more time then expected, which may cause hard reset in TCPM.
To fix that, separate thread is created, that is responsible to send
delayed TCPCI partner message as soon as possible after timer expire. It
allows to schedule messages with accuracy of +/- 1 ms, which is
acceptable for TCPCI partner emulators.
BUG=none
BRANCH=none
TEST=make configure --test zephyr/test/drivers
Signed-off-by: Tomasz Michalec <tm@semihalf.com>
Change-Id: I74bd2b965f29b940c001a441e6faad7abd80f84e
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/3368264
Reviewed-by: Sam Hurst <shurst@google.com>
Tested-by: Tomasz Michalec <tmichalec@google.com>
Commit-Queue: Tomasz Michalec <tmichalec@google.com>
-rw-r--r-- | zephyr/emul/tcpc/emul_tcpci_partner_common.c | 54 | ||||
-rw-r--r-- | zephyr/include/emul/tcpc/emul_tcpci_partner_common.h | 6 |
2 files changed, 51 insertions, 9 deletions
diff --git a/zephyr/emul/tcpc/emul_tcpci_partner_common.c b/zephyr/emul/tcpc/emul_tcpci_partner_common.c index e14337df5d..abd86ed890 100644 --- a/zephyr/emul/tcpc/emul_tcpci_partner_common.c +++ b/zephyr/emul/tcpc/emul_tcpci_partner_common.c @@ -72,11 +72,10 @@ void tcpci_partner_set_header(struct tcpci_partner_data *data, * * @param work Pointer to work structure */ -static void tcpci_partner_delayed_send(struct k_work *work) +static void tcpci_partner_delayed_send(void *fifo_data) { - struct k_work_delayable *kwd = k_work_delayable_from_work(work); struct tcpci_partner_data *data = - CONTAINER_OF(kwd, struct tcpci_partner_data, delayed_send); + CONTAINER_OF(fifo_data, struct tcpci_partner_data, fifo_data); struct tcpci_partner_msg *msg; uint64_t now; int ret; @@ -105,7 +104,8 @@ static void tcpci_partner_delayed_send(struct k_work *work) K_FOREVER); } while (ret); } else { - k_work_reschedule(kwd, K_MSEC(msg->time - now)); + k_timer_start(&data->delayed_send, + K_MSEC(msg->time - now), K_NO_WAIT); break; } } @@ -113,6 +113,45 @@ static void tcpci_partner_delayed_send(struct k_work *work) k_mutex_unlock(&data->to_send_mutex); } +/** FIFO to schedule TCPCI partners that needs to send message */ +K_FIFO_DEFINE(delayed_send_fifo); + +/** + * @brief Thread which sends delayed messages for TCPCI partners + * + * @param a unused + * @param b unused + * @param c unused + */ +static void tcpci_partner_delayed_send_thread(void *a, void *b, void *c) +{ + void *fifo_data; + + while (1) { + fifo_data = k_fifo_get(&delayed_send_fifo, K_FOREVER); + tcpci_partner_delayed_send(fifo_data); + } +} + +/** Thread for sending delayed messages */ +K_THREAD_DEFINE(tcpci_partner_delayed_send_tid, 512 /* stack size */, + tcpci_partner_delayed_send_thread, NULL, NULL, NULL, + 0 /* priority */, 0, 0); + +/** + * @brief Timeout handler which adds TCPCI partner that has pending delayed + * message to send + * + * @param timer Pointer to timer which triggered timeout + */ +static void tcpci_partner_delayed_send_timer(struct k_timer *timer) +{ + struct tcpci_partner_data *data = + CONTAINER_OF(timer, struct tcpci_partner_data, delayed_send); + + k_fifo_put(&delayed_send_fifo, &data->fifo_data); +} + /** Check description in emul_common_tcpci_partner.h */ int tcpci_partner_send_msg(struct tcpci_partner_data *data, struct tcpci_partner_msg *msg, uint64_t delay) @@ -147,7 +186,7 @@ int tcpci_partner_send_msg(struct tcpci_partner_data *data, /* Current message should be sent first */ if (prev_msg == NULL || prev_msg->time > msg->time) { sys_slist_prepend(&data->to_send, &msg->node); - k_work_reschedule(&data->delayed_send, K_MSEC(delay)); + k_timer_start(&data->delayed_send, K_MSEC(delay), K_NO_WAIT); k_mutex_unlock(&data->to_send_mutex); return 0; } @@ -219,7 +258,7 @@ int tcpci_partner_clear_msg_queue(struct tcpci_partner_data *data) struct tcpci_partner_msg *msg; int ret; - k_work_cancel_delayable(&data->delayed_send); + k_timer_stop(&data->delayed_send); ret = k_mutex_lock(&data->to_send_mutex, K_FOREVER); if (ret) { @@ -240,7 +279,8 @@ int tcpci_partner_clear_msg_queue(struct tcpci_partner_data *data) /** Check description in emul_common_tcpci_partner.h */ void tcpci_partner_init(struct tcpci_partner_data *data) { - k_work_init_delayable(&data->delayed_send, tcpci_partner_delayed_send); + k_timer_init(&data->delayed_send, tcpci_partner_delayed_send_timer, + NULL); sys_slist_init(&data->to_send); k_mutex_init(&data->to_send_mutex); } diff --git a/zephyr/include/emul/tcpc/emul_tcpci_partner_common.h b/zephyr/include/emul/tcpc/emul_tcpci_partner_common.h index 0275161d73..3337316453 100644 --- a/zephyr/include/emul/tcpc/emul_tcpci_partner_common.h +++ b/zephyr/include/emul/tcpc/emul_tcpci_partner_common.h @@ -29,8 +29,10 @@ /** Common data for TCPCI partner device emulators */ struct tcpci_partner_data { - /** Work used to send message with delay */ - struct k_work_delayable delayed_send; + /** Timer used to send message with delay */ + struct k_timer delayed_send; + /** Reserved for fifo, used for scheduling messages */ + void *fifo_data; /** Pointer to connected TCPCI emulator */ const struct emul *tcpci_emul; /** Queue for delayed messages */ |