summaryrefslogtreecommitdiff
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
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>
-rw-r--r--zephyr/emul/tcpc/emul_tcpci_partner_common.c54
-rw-r--r--zephyr/include/emul/tcpc/emul_tcpci_partner_common.h6
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 */