summaryrefslogtreecommitdiff
path: root/zephyr/emul
diff options
context:
space:
mode:
authorTomasz Michalec <tm@semihalf.com>2022-01-05 16:56:40 +0100
committerCommit Bot <commit-bot@chromium.org>2022-01-14 23:06:54 +0000
commit986675c62fd45eb53c0d316c8f6fa7124e913f34 (patch)
tree5dc5fd9fa9c675fe94e320fa4b81311190ac2086 /zephyr/emul
parentd51254bcfeedeae83dd59170af31436e9f0c5126 (diff)
downloadchrome-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>
Diffstat (limited to 'zephyr/emul')
-rw-r--r--zephyr/emul/tcpc/emul_tcpci_partner_common.c54
1 files changed, 47 insertions, 7 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);
}