From 516af3cb8432fd8fde2b10b8f7e78486d51b69d4 Mon Sep 17 00:00:00 2001 From: Bjarki Arge Andreasen Date: Wed, 22 Nov 2023 06:59:44 +0100 Subject: [PATCH] modem: pipe: Add TRANSMIT_IDLE event Add transmit idle event to modem_pipe_event enum. This will allow modules to await transmit idle before trying to transmit more data, instead of blindly calling modem_pipe_transmit in a loop until all data has been accepted. This will reduce the time spent trying to transmit data while the backend is blocked. Similarly to the RECEIVE_READY event, backends will call modem_pipe_notify_transmit_idle() to indicate that transmit is idle, and the TRANSMIT_IDLE event will be reinvoked when the modem pipe is attached to synchronize the state of the pipe with the user of it. Additionally, the TRANSMIT_IDLE event is also invoked when the modem is opened to further help synchronization with the user of the pipe. Signed-off-by: Bjarki Arge Andreasen --- include/zephyr/modem/pipe.h | 13 ++++++++++++- subsys/modem/modem_pipe.c | 21 +++++++++++++++++++++ 2 files changed, 33 insertions(+), 1 deletion(-) diff --git a/include/zephyr/modem/pipe.h b/include/zephyr/modem/pipe.h index abf8d74918e..a741a94a34c 100644 --- a/include/zephyr/modem/pipe.h +++ b/include/zephyr/modem/pipe.h @@ -25,6 +25,7 @@ extern "C" { enum modem_pipe_event { MODEM_PIPE_EVENT_OPENED = 0, MODEM_PIPE_EVENT_RECEIVE_READY, + MODEM_PIPE_EVENT_TRANSMIT_IDLE, MODEM_PIPE_EVENT_CLOSED, }; @@ -73,7 +74,8 @@ struct modem_pipe { enum modem_pipe_state state; struct k_mutex lock; struct k_condvar condvar; - bool receive_ready_pending; + uint8_t receive_ready_pending : 1; + uint8_t transmit_idle_pending : 1; }; /** @@ -213,6 +215,15 @@ void modem_pipe_notify_closed(struct modem_pipe *pipe); */ void modem_pipe_notify_receive_ready(struct modem_pipe *pipe); +/** + * @brief Notify user of pipe that pipe has no more data to transmit + * + * @param pipe Pipe instance + * + * @note Invoked from instance which initialized the pipe instance + */ +void modem_pipe_notify_transmit_idle(struct modem_pipe *pipe); + /** * @endcond */ diff --git a/subsys/modem/modem_pipe.c b/subsys/modem/modem_pipe.c index 01bdac50d3a..b0088fdefed 100644 --- a/subsys/modem/modem_pipe.c +++ b/subsys/modem/modem_pipe.c @@ -21,6 +21,7 @@ void modem_pipe_init(struct modem_pipe *pipe, void *data, struct modem_pipe_api pipe->user_data = NULL; pipe->state = MODEM_PIPE_STATE_CLOSED; pipe->receive_ready_pending = false; + pipe->transmit_idle_pending = true; k_mutex_init(&pipe->lock); k_condvar_init(&pipe->condvar); @@ -82,6 +83,10 @@ void modem_pipe_attach(struct modem_pipe *pipe, modem_pipe_api_callback callback pipe->callback(pipe, MODEM_PIPE_EVENT_RECEIVE_READY, pipe->user_data); } + if (pipe->transmit_idle_pending && (pipe->callback != NULL)) { + pipe->callback(pipe, MODEM_PIPE_EVENT_TRANSMIT_IDLE, pipe->user_data); + } + k_mutex_unlock(&pipe->lock); } @@ -97,6 +102,7 @@ int modem_pipe_transmit(struct modem_pipe *pipe, const uint8_t *buf, size_t size } ret = pipe->api->transmit(pipe->data, buf, size); + pipe->transmit_idle_pending = false; k_mutex_unlock(&pipe->lock); return ret; } @@ -179,6 +185,7 @@ void modem_pipe_notify_opened(struct modem_pipe *pipe) if (pipe->callback != NULL) { pipe->callback(pipe, MODEM_PIPE_EVENT_OPENED, pipe->user_data); + pipe->callback(pipe, MODEM_PIPE_EVENT_TRANSMIT_IDLE, pipe->user_data); } k_condvar_signal(&pipe->condvar); @@ -190,6 +197,7 @@ void modem_pipe_notify_closed(struct modem_pipe *pipe) k_mutex_lock(&pipe->lock, K_FOREVER); pipe->state = MODEM_PIPE_STATE_CLOSED; pipe->receive_ready_pending = false; + pipe->transmit_idle_pending = true; if (pipe->callback != NULL) { pipe->callback(pipe, MODEM_PIPE_EVENT_CLOSED, pipe->user_data); @@ -211,3 +219,16 @@ void modem_pipe_notify_receive_ready(struct modem_pipe *pipe) k_mutex_unlock(&pipe->lock); } + +void modem_pipe_notify_transmit_idle(struct modem_pipe *pipe) +{ + k_mutex_lock(&pipe->lock, K_FOREVER); + + pipe->transmit_idle_pending = true; + + if (pipe->callback != NULL) { + pipe->callback(pipe, MODEM_PIPE_EVENT_TRANSMIT_IDLE, pipe->user_data); + } + + k_mutex_unlock(&pipe->lock); +}