All of lore.kernel.org
 help / color / mirror / Atom feed
From: Oleksandr Andrushchenko <andr2000@gmail.com>
To: alsa-devel@alsa-project.org, xen-devel@lists.xen.org,
	linux-kernel@vger.kernel.org
Cc: perex@perex.cz, tiwai@suse.com, andr2000@gmail.com,
	Oleksandr Andrushchenko <oleksandr_andrushchenko@epam.com>
Subject: [PATCH RESEND1 11/12] ALSA: vsnd: Implement communication with backend
Date: Mon,  7 Aug 2017 15:22:56 +0300	[thread overview]
Message-ID: <1502108577-8099-12-git-send-email-andr2000@gmail.com> (raw)
In-Reply-To: <1502108577-8099-1-git-send-email-andr2000@gmail.com>

From: Oleksandr Andrushchenko <oleksandr_andrushchenko@epam.com>

Implement frontend to backend communication according to
the para-virtualized sound protocol: xen/interface/io/sndif.h.

Signed-off-by: Oleksandr Andrushchenko <oleksandr_andrushchenko@epam.com>
---
 sound/drivers/xen-front.c | 302 +++++++++++++++++++++++++++++++++++++++++++---
 1 file changed, 288 insertions(+), 14 deletions(-)

diff --git a/sound/drivers/xen-front.c b/sound/drivers/xen-front.c
index 7275e9cb38c0..8bfec43ef03a 100644
--- a/sound/drivers/xen-front.c
+++ b/sound/drivers/xen-front.c
@@ -38,6 +38,8 @@
  * because of the fact it is already in use/reserved by the PV console.
  */
 #define GRANT_INVALID_REF	0
+/* timeout in ms to wait for backend to respond */
+#define VSND_WAIT_BACK_MS	3000
 /* maximum number of supported streams */
 #define VSND_MAX_STREAM		8
 
@@ -151,10 +153,12 @@ struct xdrv_info {
 	struct sdev_card_plat_data cfg_plat_data;
 };
 
+static inline void xdrv_evtchnl_flush(struct xdrv_evtchnl_info *channel);
 static inline void sh_buf_clear(struct sh_buf_info *buf);
 static void sh_buf_free(struct sh_buf_info *buf);
 static int sh_buf_alloc(struct xenbus_device *xb_dev, struct sh_buf_info *buf,
 	unsigned int buffer_size);
+static grant_ref_t sh_buf_get_dir_start(struct sh_buf_info *buf);
 
 static struct sdev_pcm_stream_info *sdrv_stream_get(
 	struct snd_pcm_substream *substream)
@@ -314,6 +318,234 @@ static void sdrv_copy_pcm_hw(struct snd_pcm_hardware *dst,
 	}
 }
 
+struct ALSA_SNDIF_SAMPLE_FORMAT {
+	uint8_t sndif;
+	snd_pcm_format_t alsa;
+};
+
+static struct ALSA_SNDIF_SAMPLE_FORMAT alsa_sndif_formats[] = {
+	{
+		.sndif = XENSND_PCM_FORMAT_U8,
+		.alsa = SNDRV_PCM_FORMAT_U8
+	},
+	{
+		.sndif = XENSND_PCM_FORMAT_S8,
+		.alsa = SNDRV_PCM_FORMAT_S8
+	},
+	{
+		.sndif = XENSND_PCM_FORMAT_U16_LE,
+		.alsa = SNDRV_PCM_FORMAT_U16_LE
+	},
+	{
+		.sndif = XENSND_PCM_FORMAT_U16_BE,
+		.alsa = SNDRV_PCM_FORMAT_U16_BE
+	},
+	{
+		.sndif = XENSND_PCM_FORMAT_S16_LE,
+		.alsa = SNDRV_PCM_FORMAT_S16_LE
+	},
+	{
+		.sndif = XENSND_PCM_FORMAT_S16_BE,
+		.alsa = SNDRV_PCM_FORMAT_S16_BE
+	},
+	{
+		.sndif = XENSND_PCM_FORMAT_U24_LE,
+		.alsa = SNDRV_PCM_FORMAT_U24_LE
+	},
+	{
+		.sndif = XENSND_PCM_FORMAT_U24_BE,
+		.alsa = SNDRV_PCM_FORMAT_U24_BE
+	},
+	{
+		.sndif = XENSND_PCM_FORMAT_S24_LE,
+		.alsa = SNDRV_PCM_FORMAT_S24_LE
+	},
+	{
+		.sndif = XENSND_PCM_FORMAT_S24_BE,
+		.alsa = SNDRV_PCM_FORMAT_S24_BE
+	},
+	{
+		.sndif = XENSND_PCM_FORMAT_U32_LE,
+		.alsa = SNDRV_PCM_FORMAT_U32_LE
+	},
+	{
+		.sndif = XENSND_PCM_FORMAT_U32_BE,
+		.alsa = SNDRV_PCM_FORMAT_U32_BE
+	},
+	{
+		.sndif = XENSND_PCM_FORMAT_S32_LE,
+		.alsa = SNDRV_PCM_FORMAT_S32_LE
+	},
+	{
+		.sndif = XENSND_PCM_FORMAT_S32_BE,
+		.alsa = SNDRV_PCM_FORMAT_S32_BE
+	},
+	{
+		.sndif = XENSND_PCM_FORMAT_A_LAW,
+		.alsa = SNDRV_PCM_FORMAT_A_LAW
+	},
+	{
+		.sndif = XENSND_PCM_FORMAT_MU_LAW,
+		.alsa = SNDRV_PCM_FORMAT_MU_LAW
+	},
+	{
+		.sndif = XENSND_PCM_FORMAT_F32_LE,
+		.alsa = SNDRV_PCM_FORMAT_FLOAT_LE
+	},
+	{
+		.sndif = XENSND_PCM_FORMAT_F32_BE,
+		.alsa = SNDRV_PCM_FORMAT_FLOAT_BE
+	},
+	{
+		.sndif = XENSND_PCM_FORMAT_F64_LE,
+		.alsa = SNDRV_PCM_FORMAT_FLOAT64_LE
+	},
+	{
+		.sndif = XENSND_PCM_FORMAT_F64_BE,
+		.alsa = SNDRV_PCM_FORMAT_FLOAT64_BE
+	},
+	{
+		.sndif = XENSND_PCM_FORMAT_IEC958_SUBFRAME_LE,
+		.alsa = SNDRV_PCM_FORMAT_IEC958_SUBFRAME_LE
+	},
+	{
+		.sndif = XENSND_PCM_FORMAT_IEC958_SUBFRAME_BE,
+		.alsa = SNDRV_PCM_FORMAT_IEC958_SUBFRAME_BE
+	},
+	{
+		.sndif = XENSND_PCM_FORMAT_IMA_ADPCM,
+		.alsa = SNDRV_PCM_FORMAT_IMA_ADPCM
+	},
+	{
+		.sndif = XENSND_PCM_FORMAT_MPEG,
+		.alsa = SNDRV_PCM_FORMAT_MPEG
+	},
+	{
+		.sndif = XENSND_PCM_FORMAT_GSM,
+		.alsa = SNDRV_PCM_FORMAT_GSM
+	},
+};
+
+static int alsa_to_sndif_format(snd_pcm_format_t format)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(alsa_sndif_formats); i++)
+		if (alsa_sndif_formats[i].alsa == format)
+			return alsa_sndif_formats[i].sndif;
+	return -EINVAL;
+}
+
+static void sdrv_stream_clear(struct sdev_pcm_stream_info *stream)
+{
+	stream->is_open = false;
+	stream->req_next_id = 0;
+	sh_buf_clear(&stream->sh_buf);
+}
+
+static struct xensnd_req *sdrv_be_stream_prepare_req(
+	struct sdev_pcm_stream_info *stream, uint8_t operation)
+{
+	struct xensnd_req *req;
+
+	req = RING_GET_REQUEST(&stream->evt_chnl->ring,
+		stream->evt_chnl->ring.req_prod_pvt);
+	req->operation = operation;
+	req->id = stream->req_next_id++;
+	stream->evt_chnl->resp_id = req->id;
+	return req;
+}
+
+static void sdrv_be_stream_free(struct sdev_pcm_stream_info *stream)
+{
+	sh_buf_free(&stream->sh_buf);
+	sdrv_stream_clear(stream);
+}
+
+static int sdrv_be_stream_do_io(struct xdrv_evtchnl_info *evtchnl)
+{
+	if (unlikely(evtchnl->state != EVTCHNL_STATE_CONNECTED))
+		return -EIO;
+
+	reinit_completion(&evtchnl->completion);
+	xdrv_evtchnl_flush(evtchnl);
+	return 0;
+}
+
+static inline int sdrv_be_stream_wait_io(struct xdrv_evtchnl_info *evtchnl)
+{
+	if (wait_for_completion_timeout(
+			&evtchnl->completion,
+			msecs_to_jiffies(VSND_WAIT_BACK_MS)) <= 0)
+		return -ETIMEDOUT;
+	return 0;
+}
+
+static int sdrv_be_stream_open(struct snd_pcm_substream *substream,
+	struct sdev_pcm_stream_info *stream)
+{
+	struct sdev_pcm_instance_info *pcm_instance =
+		snd_pcm_substream_chip(substream);
+	struct snd_pcm_runtime *runtime = substream->runtime;
+	struct xdrv_info *xdrv_info;
+	struct xensnd_req *req;
+	unsigned long flags;
+	int ret;
+
+	xdrv_info = pcm_instance->card_info->xdrv_info;
+
+	ret = alsa_to_sndif_format(runtime->format);
+	if (ret < 0) {
+		dev_err(&xdrv_info->xb_dev->dev,
+			"Unsupported sample format: %d\n", runtime->format);
+		return ret;
+	}
+
+	spin_lock_irqsave(&xdrv_info->io_lock, flags);
+	stream->is_open = false;
+	req = sdrv_be_stream_prepare_req(stream, XENSND_OP_OPEN);
+	req->op.open.pcm_format = (uint8_t)ret;
+	req->op.open.pcm_channels = runtime->channels;
+	req->op.open.pcm_rate = runtime->rate;
+	req->op.open.buffer_sz = stream->sh_buf.vbuffer_sz;
+	req->op.open.gref_directory = sh_buf_get_dir_start(&stream->sh_buf);
+
+	ret = sdrv_be_stream_do_io(stream->evt_chnl);
+	spin_unlock_irqrestore(&xdrv_info->io_lock, flags);
+
+	if (ret < 0)
+		return ret;
+
+	ret = sdrv_be_stream_wait_io(stream->evt_chnl);
+	stream->is_open = ret < 0 ? false : true;
+	return ret;
+}
+
+static int sdrv_be_stream_close(struct snd_pcm_substream *substream,
+	struct sdev_pcm_stream_info *stream)
+{
+	struct sdev_pcm_instance_info *pcm_instance =
+		snd_pcm_substream_chip(substream);
+	struct xdrv_info *xdrv_info;
+	struct xensnd_req *req;
+	unsigned long flags;
+	int ret;
+
+	xdrv_info = pcm_instance->card_info->xdrv_info;
+
+	spin_lock_irqsave(&xdrv_info->io_lock, flags);
+	stream->is_open = false;
+	req = sdrv_be_stream_prepare_req(stream, XENSND_OP_CLOSE);
+
+	ret = sdrv_be_stream_do_io(stream->evt_chnl);
+	spin_unlock_irqrestore(&xdrv_info->io_lock, flags);
+
+	if (ret < 0)
+		return ret;
+
+	return sdrv_be_stream_wait_io(stream->evt_chnl);
+}
+
 static int sdrv_alsa_open(struct snd_pcm_substream *substream)
 {
 	struct sdev_pcm_instance_info *pcm_instance =
@@ -339,7 +571,7 @@ static int sdrv_alsa_open(struct snd_pcm_substream *substream)
 	ret = sdrv_alsa_timer_create(substream);
 
 	spin_lock_irqsave(&xdrv_info->io_lock, flags);
-	sh_buf_clear(&stream->sh_buf);
+	sdrv_stream_clear(stream);
 	stream->evt_chnl = &xdrv_info->evt_chnls[stream->unique_id];
 	if (ret < 0)
 		stream->evt_chnl->state = EVTCHNL_STATE_DISCONNECTED;
@@ -378,7 +610,7 @@ static int sdrv_alsa_hw_params(struct snd_pcm_substream *substream,
 	int ret;
 
 	buffer_size = params_buffer_bytes(params);
-	sh_buf_clear(&stream->sh_buf);
+	sdrv_stream_clear(stream);
 	xdrv_info = pcm_instance->card_info->xdrv_info;
 	ret = sh_buf_alloc(xdrv_info->xb_dev,
 		&stream->sh_buf, buffer_size);
@@ -390,22 +622,18 @@ static int sdrv_alsa_hw_params(struct snd_pcm_substream *substream,
 	dev_err(&xdrv_info->xb_dev->dev,
 		"Failed to allocate buffers for stream idx %d\n",
 		stream->unique_id);
+	sdrv_be_stream_free(stream);
 	return ret;
 }
 
 static int sdrv_alsa_hw_free(struct snd_pcm_substream *substream)
 {
-	struct sdev_pcm_instance_info *pcm_instance =
-		snd_pcm_substream_chip(substream);
 	struct sdev_pcm_stream_info *stream = sdrv_stream_get(substream);
-	struct xdrv_info *xdrv_info;
-	unsigned long flags;
+	int ret;
 
-	xdrv_info = pcm_instance->card_info->xdrv_info;
-	spin_lock_irqsave(&xdrv_info->io_lock, flags);
-	sh_buf_free(&stream->sh_buf);
-	spin_unlock_irqrestore(&xdrv_info->io_lock, flags);
-	return 0;
+	ret = sdrv_be_stream_close(substream, stream);
+	sdrv_be_stream_free(stream);
+	return ret;
 }
 
 static int sdrv_alsa_prepare(struct snd_pcm_substream *substream)
@@ -413,8 +641,12 @@ static int sdrv_alsa_prepare(struct snd_pcm_substream *substream)
 	struct sdev_pcm_stream_info *stream = sdrv_stream_get(substream);
 	int ret = 0;
 
-	if (!stream->is_open)
+	if (!stream->is_open) {
+		ret = sdrv_be_stream_open(substream, stream);
+		if (ret < 0)
+			return ret;
 		ret = sdrv_alsa_timer_prepare(substream);
+	}
 	return ret;
 }
 
@@ -446,7 +678,28 @@ static inline snd_pcm_uframes_t sdrv_alsa_pointer(
 static int sdrv_alsa_playback_do_write(struct snd_pcm_substream *substream,
 	unsigned long pos, unsigned long count)
 {
-	return 0;
+	struct sdev_pcm_stream_info *stream = sdrv_stream_get(substream);
+	struct sdev_pcm_instance_info *pcm_instance =
+		snd_pcm_substream_chip(substream);
+	struct xdrv_info *xdrv_info;
+	struct xensnd_req *req;
+	unsigned long flags;
+	int ret;
+
+	xdrv_info = pcm_instance->card_info->xdrv_info;
+
+	spin_lock_irqsave(&xdrv_info->io_lock, flags);
+	req = sdrv_be_stream_prepare_req(stream, XENSND_OP_WRITE);
+	req->op.rw.length = count;
+	req->op.rw.offset = pos;
+
+	ret = sdrv_be_stream_do_io(stream->evt_chnl);
+	spin_unlock_irqrestore(&xdrv_info->io_lock, flags);
+
+	if (ret < 0)
+		return ret;
+
+	return sdrv_be_stream_wait_io(stream->evt_chnl);
 }
 
 static int sdrv_alsa_playback_copy_user(struct snd_pcm_substream *substream,
@@ -479,7 +732,28 @@ static int sdrv_alsa_playback_copy_kernel(struct snd_pcm_substream *substream,
 static int sdrv_alsa_playback_do_read(struct snd_pcm_substream *substream,
 	unsigned long pos, unsigned long count)
 {
-	return 0;
+	struct sdev_pcm_stream_info *stream = sdrv_stream_get(substream);
+	struct sdev_pcm_instance_info *pcm_instance =
+		snd_pcm_substream_chip(substream);
+	struct xdrv_info *xdrv_info;
+	struct xensnd_req *req;
+	unsigned long flags;
+	int ret;
+
+	xdrv_info = pcm_instance->card_info->xdrv_info;
+
+	spin_lock_irqsave(&xdrv_info->io_lock, flags);
+	req = sdrv_be_stream_prepare_req(stream, XENSND_OP_READ);
+	req->op.rw.length = count;
+	req->op.rw.offset = pos;
+
+	ret = sdrv_be_stream_do_io(stream->evt_chnl);
+	spin_unlock_irqrestore(&xdrv_info->io_lock, flags);
+
+	if (ret < 0)
+		return ret;
+
+	return sdrv_be_stream_wait_io(stream->evt_chnl);
 }
 
 static int sdrv_alsa_capture_copy_user(struct snd_pcm_substream *substream,
-- 
2.7.4

  parent reply	other threads:[~2017-08-07 12:23 UTC|newest]

Thread overview: 74+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2017-08-07 12:22 [PATCH RESEND1 00/12] ALSA: vsnd: Add Xen para-virtualized frontend driver Oleksandr Andrushchenko
2017-08-07 12:22 ` [PATCH RESEND1 01/12] ALSA: vsnd: Introduce Xen para-virtualized sound " Oleksandr Andrushchenko
2017-08-07 12:22   ` Oleksandr Andrushchenko
2017-08-07 12:22 ` [PATCH RESEND1 02/12] ALSA: vsnd: Implement driver's probe/remove Oleksandr Andrushchenko
2017-08-07 12:22   ` Oleksandr Andrushchenko
2017-08-07 12:22 ` Oleksandr Andrushchenko
2017-08-07 12:22 ` [PATCH RESEND1 03/12] ALSA: vsnd: Implement Xen bus state handling Oleksandr Andrushchenko
2017-08-07 12:22   ` Oleksandr Andrushchenko
2017-08-07 12:22 ` Oleksandr Andrushchenko
2017-08-07 12:22 ` [PATCH RESEND1 04/12] ALSA: vsnd: Read sound driver configuration from Xen store Oleksandr Andrushchenko
2017-08-07 12:22   ` Oleksandr Andrushchenko
2017-08-07 12:22 ` [PATCH RESEND1 05/12] ALSA: vsnd: Implement Xen event channel handling Oleksandr Andrushchenko
2017-08-07 12:22 ` Oleksandr Andrushchenko
2017-08-07 12:22 ` [PATCH RESEND1 06/12] ALSA: vsnd: Implement handling of shared buffers Oleksandr Andrushchenko
2017-08-07 12:22 ` Oleksandr Andrushchenko
2017-08-07 12:22 ` [PATCH RESEND1 07/12] ALSA: vsnd: Introduce ALSA virtual sound driver Oleksandr Andrushchenko
2017-08-07 12:22   ` Oleksandr Andrushchenko
2017-08-07 12:22 ` [PATCH RESEND1 08/12] ALSA: vsnd: Initialize virtul sound card Oleksandr Andrushchenko
2017-08-07 12:22   ` Oleksandr Andrushchenko
2017-08-07 12:22 ` [PATCH RESEND1 09/12] ALSA: vsnd: Add timer for period interrupt emulation Oleksandr Andrushchenko
2017-08-07 12:22   ` Oleksandr Andrushchenko
2017-08-07 12:22 ` [PATCH RESEND1 10/12] ALSA: vsnd: Implement ALSA PCM operations Oleksandr Andrushchenko
2017-08-07 12:22 ` Oleksandr Andrushchenko
2017-08-07 12:22 ` Oleksandr Andrushchenko [this message]
2017-08-07 12:22 ` [PATCH RESEND1 11/12] ALSA: vsnd: Implement communication with backend Oleksandr Andrushchenko
2017-08-07 12:22 ` [PATCH RESEND1 12/12] ALSA: vsnd: Introduce Kconfig option to enable Xen PV sound Oleksandr Andrushchenko
2017-08-07 12:22 ` Oleksandr Andrushchenko
2017-08-10  3:14 ` [PATCH RESEND1 00/12] ALSA: vsnd: Add Xen para-virtualized frontend driver Takashi Sakamoto
2017-08-10  3:14 ` Takashi Sakamoto
2017-08-10  3:14   ` Takashi Sakamoto
2017-08-10  8:10   ` Oleksandr Andrushchenko
2017-08-10  8:10   ` Oleksandr Andrushchenko
2017-08-10  8:10     ` Oleksandr Andrushchenko
2017-08-17 10:05     ` [Xen-devel] " Oleksandr Grytsov
2017-08-17 10:05       ` Oleksandr Grytsov
2017-08-18  5:43       ` Takashi Sakamoto
2017-08-18  5:43         ` Takashi Sakamoto
2017-08-18  5:56         ` Oleksandr Andrushchenko
2017-08-18  7:17           ` Takashi Sakamoto
2017-08-18  7:23             ` Oleksandr Andrushchenko
2017-08-18  7:23               ` Oleksandr Andrushchenko
2017-08-22  2:43               ` Takashi Sakamoto
2017-08-23 14:51                 ` Oleksandr Grytsov
2017-08-23 14:51                 ` Oleksandr Grytsov
2017-08-23 14:51                   ` Oleksandr Grytsov
2017-08-24  4:38                   ` Takashi Sakamoto
2017-08-24  7:04                     ` Oleksandr Andrushchenko
2017-09-04  7:21                       ` Oleksandr Andrushchenko
2017-09-04  7:21                       ` Oleksandr Andrushchenko
2017-09-05  7:24                       ` [alsa-devel] " Clemens Ladisch
2017-09-12  7:52                         ` Oleksandr Grytsov
2017-09-12  7:52                         ` Oleksandr Grytsov
2017-09-19  8:57                           ` Oleksandr Andrushchenko
2017-09-19  8:57                           ` Oleksandr Andrushchenko
2017-09-26 11:35                             ` Oleksandr Andrushchenko
2017-10-04  6:50                               ` Oleksandr Andrushchenko
2017-10-04  6:50                               ` Oleksandr Andrushchenko
2017-10-13  6:15                                 ` Oleksandr Andrushchenko
2017-10-13  6:15                                 ` Oleksandr Andrushchenko
2017-10-30  6:33                                   ` [RFC] " Oleksandr Andrushchenko
2017-10-30  6:33                                   ` Oleksandr Andrushchenko
2017-11-02  9:44                                     ` Takashi Sakamoto
2017-11-02  9:55                                       ` Oleksandr Andrushchenko
2017-11-02  9:55                                       ` Oleksandr Andrushchenko
2017-11-02  9:44                                     ` Takashi Sakamoto
2017-09-26 11:35                             ` [alsa-devel] [PATCH RESEND1 00/12] " Oleksandr Andrushchenko
2017-09-05  7:24                       ` Clemens Ladisch
2017-08-24  7:04                     ` Oleksandr Andrushchenko
2017-08-24  4:38                   ` Takashi Sakamoto
2017-08-22  2:43               ` Takashi Sakamoto
2017-08-18  7:23             ` Oleksandr Andrushchenko
2017-08-18  7:17           ` Takashi Sakamoto
2017-08-18  5:56         ` Oleksandr Andrushchenko
2017-08-18  5:43       ` Takashi Sakamoto

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1502108577-8099-12-git-send-email-andr2000@gmail.com \
    --to=andr2000@gmail.com \
    --cc=alsa-devel@alsa-project.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=oleksandr_andrushchenko@epam.com \
    --cc=perex@perex.cz \
    --cc=tiwai@suse.com \
    --cc=xen-devel@lists.xen.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.