Skip to content

Commit 7815e31

Browse files
softwareckikv2019i
authored andcommitted
chain_dma: xrun notification update
Change xrun notifications to use the notification pool. Improve the logic for clearing the flag that informs the notification was sent. Previously, it was cleared when xrun occurred and the notification was sent, which meant that a notification was sent every second time xrun was detected, which could cause a flood of notifications. Signed-off-by: Adrian Warecki <adrian.warecki@intel.com>
1 parent e95a313 commit 7815e31

2 files changed

Lines changed: 27 additions & 60 deletions

File tree

src/audio/chain_dma.c

Lines changed: 27 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -26,9 +26,8 @@
2626
#include <zephyr/pm/policy.h>
2727
#include <rtos/init.h>
2828
#if CONFIG_XRUN_NOTIFICATIONS_ENABLE
29+
#include <sof/ipc/notification_pool.h>
2930
#include <ipc4/notification.h>
30-
#include <sof/ipc/msg.h>
31-
#include <ipc/header.h>
3231
#endif
3332

3433
#define DT_NUM_HDA_HOST_IN DT_PROP(DT_INST(0, intel_adsp_hda_host_in), dma_channels)
@@ -59,7 +58,6 @@ struct chain_dma_data {
5958
uint8_t cs;
6059
#if CONFIG_XRUN_NOTIFICATIONS_ENABLE
6160
bool xrun_notification_sent;
62-
struct ipc_msg *msg_xrun;
6361
#endif
6462

6563
/* local host DMA config */
@@ -145,33 +143,32 @@ static size_t chain_get_transferred_data_size(const uint32_t out_read_pos, const
145143
return buff_size - in_read_pos + out_read_pos;
146144
}
147145

148-
#if CONFIG_XRUN_NOTIFICATIONS_ENABLE
149-
static void handle_xrun(struct chain_dma_data *cd)
146+
/* get status from dma and check for xrun */
147+
static int chain_get_dma_status(struct chain_dma_data *cd, struct dma_chan_data *chan,
148+
struct dma_status *stat)
150149
{
151-
int ret;
152-
153-
if (cd->link_connector_node_id.f.dma_type == ipc4_hda_link_output_class &&
154-
!cd->xrun_notification_sent) {
155-
tr_warn(&chain_dma_tr, "handle_xrun(): underrun detected");
156-
xrun_notif_msg_init(cd->msg_xrun, cd->link_connector_node_id.dw,
157-
SOF_IPC4_GATEWAY_UNDERRUN_DETECTED);
158-
ipc_msg_send(cd->msg_xrun, NULL, true);
159-
cd->xrun_notification_sent = true;
160-
} else if (cd->link_connector_node_id.f.dma_type == ipc4_hda_link_input_class &&
161-
!cd->xrun_notification_sent) {
162-
tr_warn(&chain_dma_tr, "handle_xrun(): overrun detected");
163-
xrun_notif_msg_init(cd->msg_xrun, cd->link_connector_node_id.dw,
164-
SOF_IPC4_GATEWAY_OVERRUN_DETECTED);
165-
ipc_msg_send(cd->msg_xrun, NULL, true);
166-
cd->xrun_notification_sent = true;
167-
} else {
168-
/* if xrun_notification_sent is already set, then it means that link was
169-
* able to reach stability therefore next underrun/overrun should be reported.
170-
*/
150+
int ret = dma_get_status(chan->dma->z_dev, chan->index, stat);
151+
#if CONFIG_XRUN_NOTIFICATIONS_ENABLE
152+
if (ret == -EPIPE && !cd->xrun_notification_sent) {
153+
struct ipc_msg *notify = ipc_notification_pool_get(IPC4_RESOURCE_EVENT_SIZE);
154+
155+
if (notify) {
156+
if (cd->stream_direction == SOF_IPC_STREAM_PLAYBACK)
157+
gateway_underrun_notif_msg_init(notify,
158+
cd->link_connector_node_id.dw);
159+
else
160+
gateway_overrun_notif_msg_init(notify,
161+
cd->link_connector_node_id.dw);
162+
163+
ipc_msg_send(notify, notify->tx_data, false);
164+
cd->xrun_notification_sent = true;
165+
}
166+
} else if (!ret) {
171167
cd->xrun_notification_sent = false;
172168
}
173-
}
174169
#endif
170+
return ret;
171+
}
175172

176173
static enum task_state chain_task_run(void *data)
177174
{
@@ -185,16 +182,13 @@ static enum task_state chain_task_run(void *data)
185182
/* Link DMA can return -EPIPE and current status if xrun occurs, then it is not critical
186183
* and flow shall continue. Other error values will be treated as critical.
187184
*/
188-
ret = dma_get_status(cd->chan_link->dma->z_dev, cd->chan_link->index, &stat);
185+
ret = chain_get_dma_status(cd, cd->chan_link, &stat);
189186
switch (ret) {
190187
case 0:
191188
break;
192189
case -EPIPE:
193190
tr_warn(&chain_dma_tr, "chain_task_run(): dma_get_status() link xrun occurred,"
194191
" ret = %d", ret);
195-
#if CONFIG_XRUN_NOTIFICATIONS_ENABLE
196-
handle_xrun(cd);
197-
#endif
198192
break;
199193
default:
200194
tr_err(&chain_dma_tr, "chain_task_run(): dma_get_status() error, ret = %d", ret);
@@ -206,7 +200,7 @@ static enum task_state chain_task_run(void *data)
206200
link_read_pos = stat.read_position;
207201

208202
/* Host DMA does not report xruns. All error values will be treated as critical. */
209-
ret = dma_get_status(cd->chan_host->dma->z_dev, cd->chan_host->index, &stat);
203+
ret = chain_get_dma_status(cd, cd->chan_host, &stat);
210204
if (ret < 0) {
211205
tr_err(&chain_dma_tr, "chain_task_run(): dma_get_status() error, ret = %d", ret);
212206
return SOF_TASK_STATE_COMPLETED;
@@ -685,20 +679,9 @@ __cold static struct comp_dev *chain_task_create(const struct comp_driver *drv,
685679
comp_set_drvdata(dev, cd);
686680

687681
ret = chain_task_init(dev, host_dma_id, link_dma_id, fifo_size);
688-
if (ret)
689-
goto error_cd;
690-
691-
#if CONFIG_XRUN_NOTIFICATIONS_ENABLE
692-
cd->msg_xrun = ipc_msg_init(header.dat,
693-
sizeof(struct ipc4_resource_event_data_notification));
694-
if (!cd->msg_xrun)
695-
goto error_cd;
696-
cd->xrun_notification_sent = false;
697-
#endif
698-
699-
return dev;
682+
if (!ret)
683+
return dev;
700684

701-
error_cd:
702685
rfree(cd);
703686
error:
704687
rfree(dev);
@@ -711,10 +694,6 @@ __cold static void chain_task_free(struct comp_dev *dev)
711694

712695
assert_can_be_cold();
713696

714-
#if CONFIG_XRUN_NOTIFICATIONS_ENABLE
715-
ipc_msg_free(cd->msg_xrun);
716-
#endif
717-
718697
chain_release(dev);
719698
rfree(cd);
720699
rfree(dev);

src/ipc/ipc4/notification.c

Lines changed: 0 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -24,18 +24,6 @@ static void resource_notif_header_init(struct ipc_msg *msg)
2424
memset(&notif_data->event_data, 0, sizeof(notif_data->event_data));
2525
}
2626

27-
#if CONFIG_XRUN_NOTIFICATIONS_ENABLE
28-
void xrun_notif_msg_init(struct ipc_msg *msg_xrun, uint32_t resource_id, uint32_t event_type)
29-
{
30-
struct ipc4_resource_event_data_notification *notif_data = msg_xrun->tx_data;
31-
32-
resource_notif_header_init(msg_xrun);
33-
notif_data->resource_id = resource_id;
34-
notif_data->event_type = event_type;
35-
notif_data->resource_type = SOF_IPC4_GATEWAY;
36-
}
37-
#endif
38-
3927
void copier_gateway_underrun_notif_msg_init(struct ipc_msg *msg, uint32_t pipeline_id)
4028
{
4129
struct ipc4_resource_event_data_notification *notif_data = msg->tx_data;

0 commit comments

Comments
 (0)