From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 From: Pawel Furtak Date: Wed, 16 Jan 2019 08:18:00 +0100 Subject: [PATCH] ASoC: Skl: Virt: Handle timed out message replies Ignoring timed out messages may result in inconsistent state of UOS and SOS (e.g. stream is open on SOS, but closed on GOS). This patch adds mechanism to recover after message time out (e.g. close stream after timed out open message) Change-Id: I716f793d3668ceabe3d10557c21b973806a29710 Tracked-On: OAM-74848 Signed-off-by: Pawel Furtak Reviewed-by: Janca, Grzegorz Reviewed-by: Rojewski, Cezary Tested-by: Rojewski, Cezary --- .../soc/intel/skylake/virtio/skl-virtio-fe.c | 61 ++++++++++++++++++- .../soc/intel/skylake/virtio/skl-virtio-fe.h | 3 + 2 files changed, 63 insertions(+), 1 deletion(-) diff --git a/sound/soc/intel/skylake/virtio/skl-virtio-fe.c b/sound/soc/intel/skylake/virtio/skl-virtio-fe.c index 66a57d548ab0..2985c87fd387 100644 --- a/sound/soc/intel/skylake/virtio/skl-virtio-fe.c +++ b/sound/soc/intel/skylake/virtio/skl-virtio-fe.c @@ -96,6 +96,22 @@ struct vfe_kcontrol *vfe_find_kcontrol(struct snd_skl_vfe *vfe, return NULL; } +const struct snd_pcm *vfe_skl_find_pcm_by_name(struct skl *skl, char *pcm_name) +{ + const struct snd_soc_pcm_runtime *rtd; + int ret = vfe_is_valid_pcm_id(pcm_name); + + if (ret < 0) + return NULL; + + list_for_each_entry(rtd, &skl->component->card->rtd_list, list) { + if (strncmp(rtd->pcm->id, pcm_name, + ARRAY_SIZE(rtd->pcm->id)) == 0) + return rtd->pcm; + } + return NULL; +} + static int vfe_send_virtio_msg(struct snd_skl_vfe *vfe, struct virtqueue *vq, struct scatterlist *sgs, int sg_count, void *data, bool out) @@ -318,8 +334,10 @@ static void vfe_not_tx_done(struct virtqueue *vq) break; msg_status = atomic_read(&msg->status); - if (msg_status != VFE_MSG_PENDING) + if (msg_status == VFE_MSG_TIMED_OUT) { + vfe_handle_timedout_not_tx_msg(vfe, msg); goto free_msg; + } if (msg->rx_buf) { memcpy(msg->rx_data, msg->rx_buf, msg->rx_size); @@ -593,6 +611,47 @@ snd_pcm_uframes_t vfe_pcm_pointer(struct snd_pcm_substream *substream) return substr_info ? substr_info->hw_ptr : 0; } +static void vfe_handle_timedout_pcm_msg(struct snd_skl_vfe *vfe, + struct vfe_ipc_msg *msg) +{ + struct snd_pcm_substream *substream; + const struct vfe_pcm_info *pcm_desc = &msg->header.desc.pcm; + const struct snd_pcm *pcm = + vfe_skl_find_pcm_by_name(&vfe->sdev, pcm_desc->pcm_id); + int direction = pcm_desc->direction; + + if (!pcm) + return; + + substream = pcm->streams[direction].substream; + + switch (msg->header.cmd) { + case VFE_MSG_PCM_OPEN: + vfe_pcm_close(substream); + break; + default: + dev_info(&vfe->vdev->dev, + "Timed out PCM message %d not handled", + msg->header.cmd); + break; + } +} + +void vfe_handle_timedout_not_tx_msg(struct snd_skl_vfe *vfe, + struct vfe_ipc_msg *msg) +{ + switch (msg->header.cmd & VFE_MSG_TYPE_MASK) { + case VFE_MSG_PCM: + vfe_handle_timedout_pcm_msg(vfe, msg); + break; + default: + dev_info(&vfe->vdev->dev, + "Timed out message %d not handled", + msg->header.cmd); + break; + } +} + static const char *const vfe_skl_vq_names[SKL_VIRTIO_NUM_OF_VQS] = { SKL_VIRTIO_IPC_CMD_TX_VQ_NAME, SKL_VIRTIO_IPC_CMD_RX_VQ_NAME, diff --git a/sound/soc/intel/skylake/virtio/skl-virtio-fe.h b/sound/soc/intel/skylake/virtio/skl-virtio-fe.h index 5656d0b6a6ab..1fec99031659 100644 --- a/sound/soc/intel/skylake/virtio/skl-virtio-fe.h +++ b/sound/soc/intel/skylake/virtio/skl-virtio-fe.h @@ -61,4 +61,7 @@ struct snd_skl_vfe { struct platform_device *pdev, struct snd_soc_card *card); }; +void vfe_handle_timedout_not_tx_msg(struct snd_skl_vfe *vfe, + struct vfe_ipc_msg *msg); + #endif -- https://clearlinux.org