diff --git a/doc/nrf/releases_and_maturity/releases/release-notes-changelog.rst b/doc/nrf/releases_and_maturity/releases/release-notes-changelog.rst index fc3a932ba1eb..fdb7da884e9a 100644 --- a/doc/nrf/releases_and_maturity/releases/release-notes-changelog.rst +++ b/doc/nrf/releases_and_maturity/releases/release-notes-changelog.rst @@ -424,8 +424,11 @@ Modem libraries * :ref:`nrf_modem_lib_readme`: - * Fixed a rare bug that caused a deadlock between two threads when one thread sent data while the other received a lot of data quickly. - * Updated the :c:func:`nrf_modem_lib_shutdown` function to allow the modem to be in flight mode (``CFUN=4``) when shutting down the modem. + Updated: + + * The :c:func:`nrf_modem_lib_shutdown` function to allow the modem to be in flight mode (``CFUN=4``) when shutting down the modem. + * The trace backends can now return ``-EAGAIN`` if the write operation can be retried. + * Fixed a rare bug that caused a deadlock between two threads when one thread sent data while the other received a lot of data quickly. * :ref:`lib_location` library: diff --git a/include/modem/trace_backend.h b/include/modem/trace_backend.h index 418ba32c1232..38eb0d6592aa 100644 --- a/include/modem/trace_backend.h +++ b/include/modem/trace_backend.h @@ -58,6 +58,8 @@ struct nrf_modem_lib_trace_backend { * -ENOSPC if no space is available and the backend has to be cleared before * tracing can continue. For some trace backends, space is also cleared * when performing the read operation. + * -EAGAIN if no data were written due to e.g. flow control and the operation + * should be retried. */ int (*write)(const void *data, size_t len); diff --git a/lib/nrf_modem_lib/nrf_modem_lib_trace.c b/lib/nrf_modem_lib/nrf_modem_lib_trace.c index 6973597dd412..77a0b31b4fa5 100644 --- a/lib/nrf_modem_lib/nrf_modem_lib_trace.c +++ b/lib/nrf_modem_lib/nrf_modem_lib_trace.c @@ -204,6 +204,21 @@ static int trace_fragment_write(struct nrf_modem_trace_data *frag) __ASSERT(ret != 0, "Trace backend wrote 0 bytes"); + /* We handle this here and not in the trace_thread_handler as we might not write the + * entire trace fragment in the same write operation. If we get EAGAIN on the + * second, third, ..., we would repeat sending the first section of the trace + * fragment. + */ + if (ret == -EAGAIN) { + /* We don't allow retrying if the modem is shut down as that can block + * a new modem init. + */ + if (!nrf_modem_is_initialized()) { + return -ESHUTDOWN; + } + continue; + } + if (ret < 0) { LOG_ERR("trace_backend.write failed with err: %d", ret); return ret; diff --git a/lib/nrf_modem_lib/trace_backends/uart/uart.c b/lib/nrf_modem_lib/trace_backends/uart/uart.c index 7f7889defcb2..c87ebf78dfe0 100644 --- a/lib/nrf_modem_lib/trace_backends/uart/uart.c +++ b/lib/nrf_modem_lib/trace_backends/uart/uart.c @@ -158,6 +158,11 @@ int trace_backend_write(const void *data, size_t len) ret = len - remaining_bytes; out: k_sem_give(&tx_sem); + + if (ret == 0) { + return -EAGAIN; + } + return ret; }