[alsa-devel] [PATCH 4/4] ALSA: pcm: Split PCM transfer codes

Takashi Iwai tiwai at suse.de
Tue May 23 08:11:55 CEST 2017


The read and write transfer codes have the branch for the cases with
and without copy_silence ops.  Split the transfer functions to each of
them and pass the appropriate one before the loop.

Signed-off-by: Takashi Iwai <tiwai at suse.de>
---
 sound/core/pcm_lib.c | 222 ++++++++++++++++++++++++++++-----------------------
 1 file changed, 123 insertions(+), 99 deletions(-)

diff --git a/sound/core/pcm_lib.c b/sound/core/pcm_lib.c
index dfa6d13ba8bd..a08059f74794 100644
--- a/sound/core/pcm_lib.c
+++ b/sound/core/pcm_lib.c
@@ -2007,80 +2007,85 @@ static int pcm_sanity_check(struct snd_pcm_substream *substream)
 	return 0;
 }
 
+static int snd_pcm_lib_write_via_ops(struct snd_pcm_substream *substream,
+				     unsigned int hwoff,
+				     unsigned long data, unsigned int off,
+				     snd_pcm_uframes_t frames, bool in_kernel)
+{
+	char __user *buf = (char __user *) data +
+		frames_to_bytes(substream->runtime, off);
+
+	return substream->ops->copy_silence(substream, -1, hwoff, buf,
+					    frames, in_kernel);
+}
+
 static int snd_pcm_lib_write_transfer(struct snd_pcm_substream *substream,
 				      unsigned int hwoff,
 				      unsigned long data, unsigned int off,
 				      snd_pcm_uframes_t frames, bool in_kernel)
 {
 	struct snd_pcm_runtime *runtime = substream->runtime;
-	int err;
 	char __user *buf = (char __user *) data + frames_to_bytes(runtime, off);
+	char *hwbuf = runtime->dma_area + frames_to_bytes(runtime, hwoff);
+
+	if (in_kernel)
+		memcpy(hwbuf, (void *)buf, frames_to_bytes(runtime, frames));
+	else if (copy_from_user(hwbuf, buf, frames_to_bytes(runtime, frames)))
+		return -EFAULT;
+	return 0;
+}
 
-	if (substream->ops->copy_silence) {
-		err = substream->ops->copy_silence(substream, -1, hwoff, buf,
-						   frames, in_kernel);
+static int snd_pcm_lib_writev_via_ops(struct snd_pcm_substream *substream,
+				      unsigned int hwoff,
+				      unsigned long data, unsigned int off,
+				      snd_pcm_uframes_t frames, bool in_kernel)
+{
+	struct snd_pcm_runtime *runtime = substream->runtime;
+	int channels = runtime->channels;
+	void __user **bufs = (void __user **)data;
+	char __user *buf;
+	int c, err;
+
+	for (c = 0; c < channels; ++c, ++bufs) {
+		if (!*bufs)
+			buf = NULL;
+		else
+			buf = *bufs + samples_to_bytes(runtime, off);
+		err = substream->ops->copy_silence(substream, c, hwoff,
+						   buf, frames, in_kernel);
 		if (err < 0)
 			return err;
-	} else {
-		char *hwbuf = runtime->dma_area +
-			frames_to_bytes(runtime, hwoff);
-
-		if (in_kernel)
-			memcpy(hwbuf, (void *)buf,
-			       frames_to_bytes(runtime, frames));
-		else if (copy_from_user(hwbuf, buf,
-					frames_to_bytes(runtime, frames)))
-			return -EFAULT;
 	}
 	return 0;
 }
- 
+
 static int snd_pcm_lib_writev_transfer(struct snd_pcm_substream *substream,
 				       unsigned int hwoff,
 				       unsigned long data, unsigned int off,
 				       snd_pcm_uframes_t frames, bool in_kernel)
 {
 	struct snd_pcm_runtime *runtime = substream->runtime;
-	int err;
-	void __user **bufs = (void __user **)data;
 	int channels = runtime->channels;
+	size_t dma_csize = runtime->dma_bytes / channels;
+	void __user **bufs = (void __user **)data;
 	char __user *buf;
+	char *hwbuf;
 	int c;
 
-	if (substream->ops->copy_silence) {
-		for (c = 0; c < channels; ++c, ++bufs) {
-			if (!*bufs)
-				buf = NULL;
-			else
-				buf = *bufs + samples_to_bytes(runtime, off);
-			err = substream->ops->copy_silence(substream, c, hwoff,
-							   buf, frames,
-							   in_kernel);
-			if (err < 0)
-				return err;
-		}
-	} else {
-		/* default transfer behaviour */
-		size_t dma_csize = runtime->dma_bytes / channels;
-		for (c = 0; c < channels; ++c, ++bufs) {
-			char *hwbuf = runtime->dma_area + (c * dma_csize) +
-				samples_to_bytes(runtime, hwoff);
-
-			if (!*bufs) {
-				snd_pcm_format_set_silence(runtime->format,
-							   hwbuf, frames);
-			} else {
-				char __user *buf = *bufs +
-					samples_to_bytes(runtime, off);
-
-				if (in_kernel)
-					memcpy(hwbuf, (void *)buf,
-					       samples_to_bytes(runtime, frames));
-				else if (copy_from_user(hwbuf, buf,
-							samples_to_bytes(runtime, frames)))
-					return -EFAULT;
-			}
-		}
+	for (c = 0; c < channels; ++c, ++bufs) {
+		hwbuf = runtime->dma_area + (c * dma_csize) +
+			samples_to_bytes(runtime, hwoff);
+		buf = *bufs + samples_to_bytes(runtime, off);
+
+		if (!*bufs)
+			snd_pcm_format_set_silence(runtime->format,
+						   hwbuf, frames);
+		else if (in_kernel)
+			memcpy(hwbuf, (void *)buf,
+			       samples_to_bytes(runtime, frames));
+		else if (copy_from_user(hwbuf, buf,
+					samples_to_bytes(runtime, frames)))
+			return -EFAULT;
 	}
 	return 0;
 }
@@ -2105,11 +2110,17 @@ snd_pcm_sframes_t __snd_pcm_lib_write(struct snd_pcm_substream *substream,
 		if (runtime->access != SNDRV_PCM_ACCESS_RW_INTERLEAVED &&
 		    runtime->channels > 1)
 			return -EINVAL;
-		transfer = snd_pcm_lib_write_transfer;
+		if (substream->ops->copy_silence)
+			transfer = snd_pcm_lib_write_via_ops;
+		else
+			transfer = snd_pcm_lib_write_transfer;
 	} else {
 		if (runtime->access != SNDRV_PCM_ACCESS_RW_NONINTERLEAVED)
 			return -EINVAL;
-		transfer = snd_pcm_lib_writev_transfer;
+		if (substream->ops->copy_silence)
+			transfer = snd_pcm_lib_writev_via_ops;
+		else
+			transfer = snd_pcm_lib_writev_transfer;
 	}
 
 	if (size == 0)
@@ -2207,30 +2218,53 @@ snd_pcm_sframes_t __snd_pcm_lib_write(struct snd_pcm_substream *substream,
 EXPORT_SYMBOL(__snd_pcm_lib_write);
 
 
+static int snd_pcm_lib_read_via_ops(struct snd_pcm_substream *substream,
+				    unsigned int hwoff,
+				    unsigned long data, unsigned int off,
+				    snd_pcm_uframes_t frames, bool in_kernel)
+{
+	char __user *buf = (char __user *) data +
+		frames_to_bytes(substream->runtime, off);
+
+	return substream->ops->copy_silence(substream, -1, hwoff, buf,
+					    frames, in_kernel);
+}
+
 static int snd_pcm_lib_read_transfer(struct snd_pcm_substream *substream, 
 				     unsigned int hwoff,
 				     unsigned long data, unsigned int off,
 				     snd_pcm_uframes_t frames, bool in_kernel)
 {
 	struct snd_pcm_runtime *runtime = substream->runtime;
-	int err;
 	char __user *buf = (char __user *) data + frames_to_bytes(runtime, off);
+	char *hwbuf = runtime->dma_area + frames_to_bytes(runtime, hwoff);
 
-	if (substream->ops->copy_silence) {
-		err = substream->ops->copy_silence(substream, -1, hwoff, buf,
-						   frames, in_kernel);
+	if (in_kernel)
+		memcpy((void *)buf, hwbuf, frames_to_bytes(runtime, frames));
+	else if (copy_to_user(buf, hwbuf, frames_to_bytes(runtime, frames)))
+		return -EFAULT;
+	return 0;
+}
+
+static int snd_pcm_lib_readv_via_ops(struct snd_pcm_substream *substream,
+				     unsigned int hwoff,
+				     unsigned long data, unsigned int off,
+				     snd_pcm_uframes_t frames, bool in_kernel)
+{
+	struct snd_pcm_runtime *runtime = substream->runtime;
+	int channels = runtime->channels;
+	void __user **bufs = (void __user **)data;
+	char __user *buf;
+	int c, err;
+
+	for (c = 0; c < channels; ++c, ++bufs) {
+		if (!*bufs)
+			continue;
+		buf = *bufs + samples_to_bytes(runtime, off);
+		err = substream->ops->copy_silence(substream, c, hwoff,
+						   buf, frames, in_kernel);
 		if (err < 0)
 			return err;
-	} else {
-		char *hwbuf = runtime->dma_area +
-			frames_to_bytes(runtime, hwoff);
-
-		if (in_kernel)
-			memcpy((void *)buf, hwbuf,
-			       frames_to_bytes(runtime, frames));
-		else if (copy_to_user(buf, hwbuf,
-				      frames_to_bytes(runtime, frames)))
-			return -EFAULT;
 	}
 	return 0;
 }
@@ -2241,41 +2275,25 @@ static int snd_pcm_lib_readv_transfer(struct snd_pcm_substream *substream,
 				      snd_pcm_uframes_t frames, bool in_kernel)
 {
 	struct snd_pcm_runtime *runtime = substream->runtime;
-	int err;
-	void __user **bufs = (void __user **)data;
 	int channels = runtime->channels;
+	snd_pcm_uframes_t dma_csize = runtime->dma_bytes / channels;
+	void __user **bufs = (void __user **)data;
 	char __user *buf;
 	char *hwbuf;
 	int c;
 
-	if (substream->ops->copy_silence) {
-		for (c = 0; c < channels; ++c, ++bufs) {
-			if (!*bufs)
-				continue;
-			buf = *bufs + samples_to_bytes(runtime, off);
-			err = substream->ops->copy_silence(substream, c, hwoff,
-							   buf, frames,
-							   in_kernel);
-			if (err < 0)
-				return err;
-		}
-	} else {
-		snd_pcm_uframes_t dma_csize = runtime->dma_bytes / channels;
-
-		for (c = 0; c < channels; ++c, ++bufs) {
-			if (!*bufs)
-				continue;
-
-			hwbuf = runtime->dma_area + (c * dma_csize) +
-				samples_to_bytes(runtime, hwoff);
-			buf = *bufs + samples_to_bytes(runtime, off);
-			if (in_kernel)
-				memcpy((void *)buf, hwbuf,
-				       samples_to_bytes(runtime, frames));
-			else if (copy_to_user(buf, hwbuf,
-					      samples_to_bytes(runtime, frames)))
-				return -EFAULT;
-		}
+	for (c = 0; c < channels; ++c, ++bufs) {
+		if (!*bufs)
+			continue;
+		hwbuf = runtime->dma_area + (c * dma_csize) +
+			samples_to_bytes(runtime, hwoff);
+		buf = *bufs + samples_to_bytes(runtime, off);
+		if (in_kernel)
+			memcpy((void *)buf, hwbuf,
+			       samples_to_bytes(runtime, frames));
+		else if (copy_to_user(buf, hwbuf,
+				      samples_to_bytes(runtime, frames)))
+			return -EFAULT;
 	}
 	return 0;
 }
@@ -2300,11 +2318,17 @@ snd_pcm_sframes_t __snd_pcm_lib_read(struct snd_pcm_substream *substream,
 		if (runtime->access != SNDRV_PCM_ACCESS_RW_INTERLEAVED &&
 		    runtime->channels > 1)
 			return -EINVAL;
-		transfer = snd_pcm_lib_read_transfer;
+		if (substream->ops->copy_silence)
+			transfer = snd_pcm_lib_read_via_ops;
+		else
+			transfer = snd_pcm_lib_read_transfer;
 	} else {
 		if (runtime->access != SNDRV_PCM_ACCESS_RW_NONINTERLEAVED)
 			return -EINVAL;
-		transfer = snd_pcm_lib_readv_transfer;
+		if (substream->ops->copy_silence)
+			transfer = snd_pcm_lib_readv_via_ops;
+		else
+			transfer = snd_pcm_lib_readv_transfer;
 	}
 
 	if (size == 0)
-- 
2.13.0



More information about the Alsa-devel mailing list