Skip to content

Commit e687bdd

Browse files
wjablon1kv2019i
authored andcommitted
audio: chain_dma: fix notification pool overflow
Task for DMA chain uses the same function wrapper for checking DMA statuses and sending notifications for both Host and Link DMAs. Moreover, only one xrun_notification_sent flag is defined for that purpose. For Host DMA notifications are not needed since the task immediately returns an error on any Host DMA failure. However, the side effect of using the common function wrapper is that we might clear the flag while checking the Host DMA status and thus cause a Link DMA notification flood. This change fixes this issue by removing the common function wrapper and limiting notification API usage to Link DMA. Signed-off-by: Wojciech Jablonski <wojciech.jablonski@intel.com>
1 parent fd410ef commit e687bdd

1 file changed

Lines changed: 16 additions & 15 deletions

File tree

src/audio/chain_dma.c

Lines changed: 16 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -142,21 +142,16 @@ static size_t chain_get_transferred_data_size(const uint32_t out_read_pos, const
142142
return buff_size - in_read_pos + out_read_pos;
143143
}
144144

145-
/* get status from dma and check for xrun */
146-
static int chain_get_dma_status(struct chain_dma_data *cd, struct dma_chan_data *chan,
147-
struct dma_status *stat)
148-
{
149-
int ret = dma_get_status(chan->dma->z_dev, chan->index, stat);
150145
#if CONFIG_XRUN_NOTIFICATIONS_ENABLE
151-
if (ret == -EPIPE && !cd->xrun_notification_sent) {
152-
cd->xrun_notification_sent = send_gateway_xrun_notif_msg
153-
(cd->link_connector_node_id.dw, cd->stream_direction);
154-
} else if (!ret) {
155-
cd->xrun_notification_sent = false;
156-
}
157-
#endif
158-
return ret;
146+
static void chain_dma_send_xrun_notif(struct chain_dma_data *cd)
147+
{
148+
uint32_t resource_id = cd->link_connector_node_id.dw;
149+
enum sof_ipc_stream_direction dir = cd->stream_direction;
150+
151+
if (!cd->xrun_notification_sent)
152+
cd->xrun_notification_sent = send_gateway_xrun_notif_msg(resource_id, dir);
159153
}
154+
#endif
160155

161156
static enum task_state chain_task_run(void *data)
162157
{
@@ -170,11 +165,17 @@ static enum task_state chain_task_run(void *data)
170165
/* Link DMA can return -EPIPE and current status if xrun occurs, then it is not critical
171166
* and flow shall continue. Other error values will be treated as critical.
172167
*/
173-
ret = chain_get_dma_status(cd, cd->chan_link, &stat);
168+
ret = dma_get_status(cd->chan_link->dma->z_dev, cd->chan_link->index, &stat);
174169
switch (ret) {
175170
case 0:
171+
#if CONFIG_XRUN_NOTIFICATIONS_ENABLE
172+
cd->xrun_notification_sent = false;
173+
#endif
176174
break;
177175
case -EPIPE:
176+
#if CONFIG_XRUN_NOTIFICATIONS_ENABLE
177+
chain_dma_send_xrun_notif(cd);
178+
#endif
178179
tr_warn(&chain_dma_tr, "dma_get_status() link xrun occurred,"
179180
" ret = %d", ret);
180181
break;
@@ -188,7 +189,7 @@ static enum task_state chain_task_run(void *data)
188189
link_read_pos = stat.read_position;
189190

190191
/* Host DMA does not report xruns. All error values will be treated as critical. */
191-
ret = chain_get_dma_status(cd, cd->chan_host, &stat);
192+
ret = dma_get_status(cd->chan_host->dma->z_dev, cd->chan_host->index, &stat);
192193
if (ret < 0) {
193194
tr_err(&chain_dma_tr, "dma_get_status() error, ret = %d", ret);
194195
return SOF_TASK_STATE_COMPLETED;

0 commit comments

Comments
 (0)