diff --git a/drivers/adc/adc_mcux_adc16.c b/drivers/adc/adc_mcux_adc16.c index cf721b8baea..7ab59b02f2f 100644 --- a/drivers/adc/adc_mcux_adc16.c +++ b/drivers/adc/adc_mcux_adc16.c @@ -76,7 +76,7 @@ struct mcux_adc16_data { #ifdef CONFIG_ADC_MCUX_ADC16_ENABLE_EDMA static void adc_dma_callback(const struct device *dma_dev, void *callback_arg, - uint32_t channel, int error_code) + uint32_t channel, int status) { const struct device *dev = (const struct device *)callback_arg; struct mcux_adc16_data *data = dev->data; diff --git a/drivers/adc/adc_stm32.c b/drivers/adc/adc_stm32.c index cace4eeaf6f..aceeea425db 100644 --- a/drivers/adc/adc_stm32.c +++ b/drivers/adc/adc_stm32.c @@ -782,9 +782,9 @@ static void dma_callback(const struct device *dev, void *user_data, if (channel == data->dma.channel) { #if !defined(CONFIG_SOC_SERIES_STM32F1X) - if (LL_ADC_IsActiveFlag_OVR(adc) || (status == 0)) { + if (LL_ADC_IsActiveFlag_OVR(adc) || (status >= 0)) { #else - if (status == 0) { + if (status >= 0) { #endif /* !defined(CONFIG_SOC_SERIES_STM32F1X) */ data->samples_count = data->channel_count; data->buffer += data->channel_count; @@ -801,7 +801,7 @@ static void dma_callback(const struct device *dev, void *user_data, * the address is in a non-cacheable SRAM region. */ adc_context_on_sampling_done(&data->ctx, dev); - } else { + } else if (status < 0) { LOG_ERR("DMA sampling complete, but DMA reported error %d", status); data->dma_error = status; LL_ADC_REG_StopConversion(adc); diff --git a/drivers/dma/dma_dw_common.c b/drivers/dma/dma_dw_common.c index 70b820b345f..722272e58e4 100644 --- a/drivers/dma/dma_dw_common.c +++ b/drivers/dma/dma_dw_common.c @@ -70,7 +70,7 @@ void dw_dma_isr(const struct device *dev) */ chan_data->dma_blkcallback(dev, chan_data->blkuser_data, - channel, 0); + channel, DMA_STATUS_BLOCK); } } @@ -89,7 +89,7 @@ void dw_dma_isr(const struct device *dev) LOG_DBG("Dispatching transfer callback"); chan_data->dma_tfrcallback(dev, chan_data->tfruser_data, - channel, 0); + channel, DMA_STATUS_COMPLETE); } } } diff --git a/drivers/dma/dma_iproc_pax_v1.c b/drivers/dma/dma_iproc_pax_v1.c index f8fc4a694f3..ba1450d6d8e 100644 --- a/drivers/dma/dma_iproc_pax_v1.c +++ b/drivers/dma/dma_iproc_pax_v1.c @@ -467,7 +467,7 @@ static int process_cmpl_event(const struct device *dev, enum ring_idx idx, uint32_t pl_len) { struct dma_iproc_pax_data *pd = dev->data; - uint32_t wr_offs, rd_offs, ret = 0; + uint32_t wr_offs, rd_offs, ret = DMA_STATUS_COMPLETE; struct dma_iproc_pax_ring_data *ring = &(pd->ring[idx]); struct cmpl_pkt *c; uint32_t is_outstanding; diff --git a/drivers/dma/dma_mcux_edma.c b/drivers/dma/dma_mcux_edma.c index 30baae4884f..ac56036b70c 100644 --- a/drivers/dma/dma_mcux_edma.c +++ b/drivers/dma/dma_mcux_edma.c @@ -120,14 +120,14 @@ static bool data_size_valid(const size_t data_size) static void nxp_edma_callback(edma_handle_t *handle, void *param, bool transferDone, uint32_t tcds) { - int ret = 1; + int ret = -EIO; struct call_back *data = (struct call_back *)param; uint32_t channel = handle->channel; if (transferDone) { /* DMA is no longer busy when there are no remaining TCDs to transfer */ data->busy = (handle->tcdPool != NULL) && (handle->tcdUsed > 0); - ret = 0; + ret = DMA_STATUS_COMPLETE; } LOG_DBG("transfer %d", tcds); data->dma_callback(data->dev, data->user_data, channel, ret); diff --git a/drivers/dma/dma_mcux_lpc.c b/drivers/dma/dma_mcux_lpc.c index 49ead1fc64e..027fe627965 100644 --- a/drivers/dma/dma_mcux_lpc.c +++ b/drivers/dma/dma_mcux_lpc.c @@ -58,12 +58,12 @@ struct dma_mcux_lpc_dma_data { static void nxp_lpc_dma_callback(dma_handle_t *handle, void *param, bool transferDone, uint32_t intmode) { - int ret = 1; + int ret = -EIO; struct call_back *data = (struct call_back *)param; uint32_t channel = handle->channel; if (transferDone) { - ret = 0; + ret = DMA_STATUS_COMPLETE; } if (intmode == kDMA_IntError) { diff --git a/drivers/dma/dma_nios2_msgdma.c b/drivers/dma/dma_nios2_msgdma.c index f8fd29bf214..ccc7b1e58ad 100644 --- a/drivers/dma/dma_nios2_msgdma.c +++ b/drivers/dma/dma_nios2_msgdma.c @@ -45,22 +45,22 @@ static void nios2_msgdma_callback(void *context) { struct nios2_msgdma_dev_data *dev_data = (struct nios2_msgdma_dev_data *)context; - int err_code; + int dma_status; uint32_t status; status = IORD_ALTERA_MSGDMA_CSR_STATUS(dev_data->msgdma_dev->csr_base); if (status & ALTERA_MSGDMA_CSR_STOPPED_ON_ERROR_MASK) { - err_code = -EIO; + dma_status = -EIO; } else if (status & ALTERA_MSGDMA_CSR_BUSY_MASK) { - err_code = -EBUSY; + dma_status = -EBUSY; } else { - err_code = 0; + dma_status = DMA_STATUS_COMPLETE; } LOG_DBG("msgdma csr status Reg: 0x%x", status); - dev_data->dma_callback(dev_data->dev, dev_data->user_data, 0, err_code); + dev_data->dma_callback(dev_data->dev, dev_data->user_data, 0, dma_status); } static int nios2_msgdma_config(const struct device *dev, uint32_t channel, diff --git a/drivers/dma/dma_stm32.c b/drivers/dma/dma_stm32.c index fe3d3423520..b9cde124d8d 100644 --- a/drivers/dma/dma_stm32.c +++ b/drivers/dma/dma_stm32.c @@ -118,7 +118,7 @@ static void dma_stm32_irq_handler(const struct device *dev, uint32_t id) if (!stream->hal_override) { dma_stm32_clear_ht(dma, id); } - stream->dma_callback(dev, stream->user_data, callback_arg, 0); + stream->dma_callback(dev, stream->user_data, callback_arg, DMA_STATUS_BLOCK); } else if (stm32_dma_is_tc_irq_active(dma, id)) { #ifdef CONFIG_DMAMUX_STM32 stream->busy = false; @@ -127,7 +127,7 @@ static void dma_stm32_irq_handler(const struct device *dev, uint32_t id) if (!stream->hal_override) { dma_stm32_clear_tc(dma, id); } - stream->dma_callback(dev, stream->user_data, callback_arg, 0); + stream->dma_callback(dev, stream->user_data, callback_arg, DMA_STATUS_COMPLETE); } else if (stm32_dma_is_unexpected_irq_happened(dma, id)) { LOG_ERR("Unexpected irq happened."); stream->dma_callback(dev, stream->user_data, diff --git a/drivers/dma/dma_stm32u5.c b/drivers/dma/dma_stm32u5.c index 9fb75d1c286..db58dbd2170 100644 --- a/drivers/dma/dma_stm32u5.c +++ b/drivers/dma/dma_stm32u5.c @@ -251,13 +251,13 @@ static void dma_stm32_irq_handler(const struct device *dev, uint32_t id) if (!stream->hal_override) { dma_stm32_clear_ht(dma, id); } - stream->dma_callback(dev, stream->user_data, callback_arg, 0); + stream->dma_callback(dev, stream->user_data, callback_arg, DMA_STATUS_BLOCK); } else if (stm32_dma_is_tc_irq_active(dma, id)) { /* Let HAL DMA handle flags on its own */ if (!stream->hal_override) { dma_stm32_clear_tc(dma, id); } - stream->dma_callback(dev, stream->user_data, callback_arg, 0); + stream->dma_callback(dev, stream->user_data, callback_arg, DMA_STATUS_COMPLETE); } else { LOG_ERR("Transfer Error."); dma_stm32_dump_stream_irq(dev, id); diff --git a/drivers/flash/flash_stm32_ospi.c b/drivers/flash/flash_stm32_ospi.c index 0b924296610..17c3fe8f267 100644 --- a/drivers/flash/flash_stm32_ospi.c +++ b/drivers/flash/flash_stm32_ospi.c @@ -1299,7 +1299,7 @@ static void ospi_dma_callback(const struct device *dev, void *arg, ARG_UNUSED(dev); - if (status != 0) { + if (status < 0) { LOG_ERR("DMA callback error with channel %d.", channel); } diff --git a/drivers/i2s/i2s_ll_stm32.c b/drivers/i2s/i2s_ll_stm32.c index 8596dbb4ece..62db351e434 100644 --- a/drivers/i2s/i2s_ll_stm32.c +++ b/drivers/i2s/i2s_ll_stm32.c @@ -524,7 +524,7 @@ static void dma_rx_callback(const struct device *dma_dev, void *arg, void *mblk_tmp; int ret; - if (status != 0) { + if (status < 0) { ret = -EIO; stream->state = I2S_STATE_ERROR; goto rx_disable; @@ -591,7 +591,7 @@ static void dma_tx_callback(const struct device *dma_dev, void *arg, size_t mem_block_size; int ret; - if (status != 0) { + if (status < 0) { ret = -EIO; stream->state = I2S_STATE_ERROR; goto tx_disable; diff --git a/drivers/i2s/i2s_mcux_flexcomm.c b/drivers/i2s/i2s_mcux_flexcomm.c index b5677bb36f0..a23548216eb 100644 --- a/drivers/i2s/i2s_mcux_flexcomm.c +++ b/drivers/i2s/i2s_mcux_flexcomm.c @@ -457,9 +457,9 @@ static void i2s_mcux_dma_tx_callback(const struct device *dma_dev, void *arg, dma_start(stream->dev_dma, stream->channel); } - if (ret || status) { + if (ret || status < 0) { /* - * DMA encountered an error (status != 0) + * DMA encountered an error (status < 0) * or * No buffers in input queue */ @@ -490,7 +490,7 @@ static void i2s_mcux_dma_rx_callback(const struct device *dma_dev, void *arg, LOG_DBG("rx cb: %d", stream->state); - if (status != 0) { + if (status < 0) { stream->state = I2S_STATE_ERROR; i2s_mcux_rx_stream_disable(dev, false); return; diff --git a/drivers/serial/uart_mcux_lpuart.c b/drivers/serial/uart_mcux_lpuart.c index 446be27b143..8edb3da0949 100644 --- a/drivers/serial/uart_mcux_lpuart.c +++ b/drivers/serial/uart_mcux_lpuart.c @@ -593,7 +593,7 @@ static int uart_mcux_lpuart_dma_replace_rx_buffer(const struct device *dev) } static void dma_callback(const struct device *dma_dev, void *callback_arg, uint32_t channel, - int error_code) + int dma_status) { struct device *dev = (struct device *)callback_arg; const struct mcux_lpuart_config *config = dev->config; @@ -611,8 +611,8 @@ static void dma_callback(const struct device *dma_dev, void *callback_arg, uint3 status.pending_length); } - if (error_code != 0) { - LOG_ERR("Got error : %d", error_code); + if (dma_status < 0) { + LOG_ERR("Got error : %d", dma_status); } diff --git a/drivers/serial/uart_stm32.c b/drivers/serial/uart_stm32.c index 8762c61380a..55d6b221cbb 100644 --- a/drivers/serial/uart_stm32.c +++ b/drivers/serial/uart_stm32.c @@ -1227,7 +1227,7 @@ void uart_stm32_dma_rx_cb(const struct device *dma_dev, void *user_data, const struct device *uart_dev = user_data; struct uart_stm32_data *data = uart_dev->data; - if (status != 0) { + if (status < 0) { async_evt_rx_err(data, status); return; } diff --git a/drivers/spi/spi_ll_stm32.c b/drivers/spi/spi_ll_stm32.c index fa66b850d4c..9a3bebdaa4e 100644 --- a/drivers/spi/spi_ll_stm32.c +++ b/drivers/spi/spi_ll_stm32.c @@ -61,7 +61,7 @@ static void dma_callback(const struct device *dev, void *arg, /* arg directly holds the spi device */ struct spi_stm32_data *data = arg; - if (status != 0) { + if (status < 0) { LOG_ERR("DMA callback error with channel %d.", channel); data->status_flags |= SPI_STM32_DMA_ERROR_FLAG; } else { diff --git a/drivers/spi/spi_mcux_dspi.c b/drivers/spi/spi_mcux_dspi.c index eb1d29c39f5..63bccd70499 100644 --- a/drivers/spi/spi_mcux_dspi.c +++ b/drivers/spi/spi_mcux_dspi.c @@ -482,7 +482,7 @@ static void dma_callback(const struct device *dma_dev, void *callback_arg, LOG_DBG("=dma call back @channel %d=", channel); - if (error_code) { + if (error_code < 0) { LOG_ERR("error happened no callback process %d", error_code); return; } diff --git a/drivers/spi/spi_mcux_flexcomm.c b/drivers/spi/spi_mcux_flexcomm.c index 25d24701561..427704892ce 100644 --- a/drivers/spi/spi_mcux_flexcomm.c +++ b/drivers/spi/spi_mcux_flexcomm.c @@ -305,7 +305,7 @@ static void spi_mcux_dma_callback(const struct device *dev, void *arg, const struct device *spi_dev = arg; struct spi_mcux_data *data = spi_dev->data; - if (status != 0) { + if (status < 0) { LOG_ERR("DMA callback error with channel %d.", channel); data->status_flags |= SPI_MCUX_FLEXCOMM_DMA_ERROR_FLAG; } else { diff --git a/drivers/spi/spi_mcux_lpspi.c b/drivers/spi/spi_mcux_lpspi.c index 9544a3dea48..7976c5d0087 100644 --- a/drivers/spi/spi_mcux_lpspi.c +++ b/drivers/spi/spi_mcux_lpspi.c @@ -254,7 +254,7 @@ static void spi_mcux_dma_callback(const struct device *dev, void *arg, const struct device *spi_dev = arg; struct spi_mcux_data *data = (struct spi_mcux_data *)spi_dev->data; - if (status != 0) { + if (status < 0) { LOG_ERR("DMA callback error with channel %d.", channel); data->status_flags |= SPI_MCUX_LPSPI_DMA_ERROR_FLAG; } else { diff --git a/include/zephyr/drivers/dma.h b/include/zephyr/drivers/dma.h index 0448543a80d..eb04334101d 100644 --- a/include/zephyr/drivers/dma.h +++ b/include/zephyr/drivers/dma.h @@ -136,17 +136,25 @@ struct dma_block_config { uint16_t reserved : 3; }; +#define DMA_STATUS_COMPLETE 0 +#define DMA_STATUS_BLOCK 1 + /** * @typedef dma_callback_t * @brief Callback function for DMA transfer completion * - * If enabled, callback function will be invoked at transfer completion - * or when error happens. + * If enabled, callback function will be invoked at transfer or block completion, + * or when an error happens. + * In circular mode, @p status indicates that the DMA device has reached either + * the end of the buffer (DMA_STATUS_COMPLETE) or a water mark (DMA_STATUS_BLOCK). * - * @param dev Pointer to the DMA device calling the callback. - * @param user_data A pointer to some user data or NULL - * @param channel The channel number - * @param status 0 on success, a negative errno otherwise + * @param dev Pointer to the DMA device calling the callback. + * @param user_data A pointer to some user data or NULL + * @param channel The channel number + * @param status - 0-DMA_STATUS_COMPLETE buffer fully consumed + * - 1-DMA_STATUS_BLOCK buffer consumption reached a configured block + * or water mark + * - a negative errno otherwise */ typedef void (*dma_callback_t)(const struct device *dev, void *user_data, uint32_t channel, int status); diff --git a/tests/boards/altera_max10/msgdma/src/dma.c b/tests/boards/altera_max10/msgdma/src/dma.c index f0fbe9c82c7..f02cab1330c 100644 --- a/tests/boards/altera_max10/msgdma/src/dma.c +++ b/tests/boards/altera_max10/msgdma/src/dma.c @@ -27,13 +27,13 @@ static struct dma_config dma_cfg = {0}; static struct dma_block_config dma_block_cfg = {0}; static void dma_user_callback(const struct device *dma_dev, void *arg, - uint32_t id, int error_code) + uint32_t id, int status) { - if (error_code == 0) { + if (status >= 0) { TC_PRINT("DMA completed successfully\n"); dma_stat = DMA_OP_STAT_SUCCESS; } else { - TC_PRINT("DMA error occurred!! (%d)\n", error_code); + TC_PRINT("DMA error occurred!! (%d)\n", status); dma_stat = DMA_OP_STAT_ERR; } } diff --git a/tests/boards/intel_adsp/ssp/src/main.c b/tests/boards/intel_adsp/ssp/src/main.c index b51d6dcb2d7..67d9e29f79b 100644 --- a/tests/boards/intel_adsp/ssp/src/main.c +++ b/tests/boards/intel_adsp/ssp/src/main.c @@ -83,7 +83,7 @@ static __aligned(32) int32_t rx_data[XFERS][BUF_SIZE] = { { 0 } }; static void dma_callback(const struct device *dma_dev, void *user_data, uint32_t channel, int status) { - if (status) { + if (status < 0) { TC_PRINT("tx callback status %d\n", status); } else { TC_PRINT("tx giving up\n"); @@ -93,7 +93,7 @@ static void dma_callback(const struct device *dma_dev, void *user_data, static void dma_callback_rx(const struct device *dma_dev, void *user_data, uint32_t channel, int status) { - if (status) { + if (status < 0) { TC_PRINT("rx callback status %d\n", status); } else { TC_PRINT("rx giving xfer_sem\n"); diff --git a/tests/drivers/dma/chan_blen_transfer/src/test_dma.c b/tests/drivers/dma/chan_blen_transfer/src/test_dma.c index 30785bdad17..d0fa561f37b 100644 --- a/tests/drivers/dma/chan_blen_transfer/src/test_dma.c +++ b/tests/drivers/dma/chan_blen_transfer/src/test_dma.c @@ -34,9 +34,9 @@ static char rx_data[RX_BUFF_SIZE] = { 0 }; #endif static void test_done(const struct device *dma_dev, void *arg, - uint32_t id, int error_code) + uint32_t id, int status) { - if (error_code == 0) { + if (status >= 0) { TC_PRINT("DMA transfer done\n"); } else { TC_PRINT("DMA transfer met an error\n"); diff --git a/tests/drivers/dma/chan_link_transfer/src/test_dma.c b/tests/drivers/dma/chan_link_transfer/src/test_dma.c index be7dfa455ea..9e55a36f7d4 100644 --- a/tests/drivers/dma/chan_link_transfer/src/test_dma.c +++ b/tests/drivers/dma/chan_link_transfer/src/test_dma.c @@ -40,9 +40,9 @@ static char rx_data2[RX_BUFF_SIZE] = { 0 }; #endif static void test_done(const struct device *dma_dev, void *arg, uint32_t id, - int error_code) + int status) { - if (error_code == 0) { + if (status >= 0) { TC_PRINT("DMA transfer done ch %d\n", id); } else { TC_PRINT("DMA transfer met an error\n"); diff --git a/tests/drivers/dma/loop_transfer/src/test_dma_loop.c b/tests/drivers/dma/loop_transfer/src/test_dma_loop.c index 2610d72ced3..59dad035308 100644 --- a/tests/drivers/dma/loop_transfer/src/test_dma_loop.c +++ b/tests/drivers/dma/loop_transfer/src/test_dma_loop.c @@ -98,14 +98,14 @@ static void test_transfer(const struct device *dev, uint32_t id) } static void dma_user_callback(const struct device *dma_dev, void *arg, - uint32_t id, int error_code) + uint32_t id, int status) { /* test case is done so ignore the interrupt */ if (done) { return; } - zassert_false(error_code, "DMA could not proceed, an error occurred\n"); + zassert_false(status < 0, "DMA could not proceed, an error occurred\n"); #ifdef CONFIG_DMAMUX_STM32 /* the channel is the DMAMUX's one diff --git a/tests/drivers/dma/scatter_gather/src/test_dma_sg.c b/tests/drivers/dma/scatter_gather/src/test_dma_sg.c index ca2a2a47997..9e56ac33107 100644 --- a/tests/drivers/dma/scatter_gather/src/test_dma_sg.c +++ b/tests/drivers/dma/scatter_gather/src/test_dma_sg.c @@ -44,7 +44,7 @@ static struct dma_block_config dma_block_cfgs[XFERS]; static void dma_sg_callback(const struct device *dma_dev, void *user_data, uint32_t channel, int status) { - if (status) { + if (status < 0) { TC_PRINT("callback status %d\n", status); } else { TC_PRINT("giving xfer_sem\n");