@@ -1532,9 +1532,10 @@ static inline u64 pcm_format_to_bits(snd_pcm_format_t pcm_format)
dev_dbg((pcm)->card->dev, fmt, ##args)
/* helpers for copying between iov_iter and iomem */
-int copy_to_iter_fromio(struct iov_iter *itert, const void __iomem *src,
- size_t count);
-int copy_from_iter_toio(void __iomem *dst, struct iov_iter *iter, size_t count);
+size_t copy_to_iter_fromio(const void __iomem *src, size_t bytes,
+ struct iov_iter *iter) __must_check;
+size_t copy_from_iter_toio(void __iomem *dst, size_t bytes,
+ struct iov_iter *iter) __must_check;
struct snd_pcm_status64 {
snd_pcm_state_t state; /* stream state */
@@ -27,38 +27,43 @@ int copy_to_user_fromio(void __user *dst, const volatile void __iomem *src, size
if (import_ubuf(ITER_DEST, dst, count, &iter))
return -EFAULT;
- return copy_to_iter_fromio(&iter, (const void __iomem *)src, count);
+ if (copy_to_iter_fromio((const void __iomem *)src, count, &iter) != count)
+ return -EFAULT;
+ return 0;
}
EXPORT_SYMBOL(copy_to_user_fromio);
/**
* copy_to_iter_fromio - copy data from mmio-space to iov_iter
- * @dst: the destination iov_iter
* @src: the source pointer on mmio
* @count: the data size to copy in bytes
+ * @dst: the destination iov_iter
*
* Copies the data from mmio-space to iov_iter.
*
- * Return: Zero if successful, or non-zero on failure.
+ * Return: number of bytes to be copied
*/
-int copy_to_iter_fromio(struct iov_iter *dst, const void __iomem *src,
- size_t count)
+size_t copy_to_iter_fromio(const void __iomem *src, size_t count,
+ struct iov_iter *dst)
{
#if defined(__i386__) || defined(CONFIG_SPARC32)
- return copy_to_iter((const void __force *)src, count, dst) == count ? 0 : -EFAULT;
+ return copy_to_iter((const void __force *)src, count, dst);
#else
char buf[256];
+ size_t res = 0;
+
while (count) {
size_t c = count;
if (c > sizeof(buf))
c = sizeof(buf);
memcpy_fromio(buf, (void __iomem *)src, c);
if (copy_to_iter(buf, c, dst) != c)
- return -EFAULT;
+ return res;
count -= c;
src += c;
+ res += c;
}
- return 0;
+ return res;
#endif
}
EXPORT_SYMBOL(copy_to_iter_fromio);
@@ -79,37 +84,43 @@ int copy_from_user_toio(volatile void __iomem *dst, const void __user *src, size
if (import_ubuf(ITER_SOURCE, (void __user *)src, count, &iter))
return -EFAULT;
- return copy_from_iter_toio((void __iomem *)dst, &iter, count);
+ if (copy_from_iter_toio((void __iomem *)dst, count, &iter) != count)
+ return -EFAULT;
+ return 0;
}
EXPORT_SYMBOL(copy_from_user_toio);
/**
* copy_from_iter_toio - copy data from iov_iter to mmio-space
* @dst: the destination pointer on mmio-space
- * @src: the source iov_iter
* @count: the data size to copy in bytes
+ * @src: the source iov_iter
*
* Copies the data from iov_iter to mmio-space.
*
- * Return: Zero if successful, or non-zero on failure.
+ * Return: number of bytes to be copied
*/
-int copy_from_iter_toio(void __iomem *dst, struct iov_iter *src, size_t count)
+size_t copy_from_iter_toio(void __iomem *dst, size_t count,
+ struct iov_iter *src)
{
#if defined(__i386__) || defined(CONFIG_SPARC32)
- return copy_from_iter((void __force *)dst, count, src) == count ? 0 : -EFAULT;
+ return copy_from_iter((void __force *)dst, count, src);
#else
char buf[256];
+ size_t res = 0;
+
while (count) {
size_t c = count;
if (c > sizeof(buf))
c = sizeof(buf);
if (copy_from_iter(buf, c, src) != c)
- return -EFAULT;
+ return res;
memcpy_toio(dst, buf, c);
count -= c;
dst += c;
+ res += c;
}
- return 0;
+ return res;
#endif
}
EXPORT_SYMBOL(copy_from_iter_toio);
@@ -696,7 +696,9 @@ snd_nm256_playback_copy(struct snd_pcm_substream *substream,
struct snd_pcm_runtime *runtime = substream->runtime;
struct nm256_stream *s = runtime->private_data;
- return copy_from_iter_toio(s->bufptr + pos, src, count);
+ if (copy_from_iter_toio(s->bufptr + pos, count, src) != count)
+ return -EFAULT;
+ return 0;
}
/*
@@ -710,7 +712,9 @@ snd_nm256_capture_copy(struct snd_pcm_substream *substream,
struct snd_pcm_runtime *runtime = substream->runtime;
struct nm256_stream *s = runtime->private_data;
- return copy_to_iter_fromio(dst, s->bufptr + pos, count);
+ if (copy_to_iter_fromio(s->bufptr + pos, count, dst) != count)
+ return -EFAULT;
+ return 0;
}
#endif /* !__i386__ */
@@ -256,8 +256,10 @@ static int snd_rme32_playback_copy(struct snd_pcm_substream *substream,
{
struct rme32 *rme32 = snd_pcm_substream_chip(substream);
- return copy_from_iter_toio(rme32->iobase + RME32_IO_DATA_BUFFER + pos,
- src, count);
+ if (copy_from_iter_toio(rme32->iobase + RME32_IO_DATA_BUFFER + pos,
+ count, src) != count)
+ return -EFAULT;
+ return 0;
}
/* copy callback for halfduplex mode */
@@ -267,9 +269,10 @@ static int snd_rme32_capture_copy(struct snd_pcm_substream *substream,
{
struct rme32 *rme32 = snd_pcm_substream_chip(substream);
- return copy_to_iter_fromio(dst,
- rme32->iobase + RME32_IO_DATA_BUFFER + pos,
- count);
+ if (copy_to_iter_fromio(rme32->iobase + RME32_IO_DATA_BUFFER + pos,
+ count, dst) != count)
+ return -EFAULT;
+ return 0;
}
/*
@@ -322,8 +322,10 @@ snd_rme96_playback_copy(struct snd_pcm_substream *substream,
{
struct rme96 *rme96 = snd_pcm_substream_chip(substream);
- return copy_from_iter_toio(rme96->iobase + RME96_IO_PLAY_BUFFER + pos,
- src, count);
+ if (copy_from_iter_toio(rme96->iobase + RME96_IO_PLAY_BUFFER + pos,
+ count, src) != count)
+ return -EFAULT;
+ return 0;
}
static int
@@ -333,9 +335,10 @@ snd_rme96_capture_copy(struct snd_pcm_substream *substream,
{
struct rme96 *rme96 = snd_pcm_substream_chip(substream);
- return copy_to_iter_fromio(dst,
- rme96->iobase + RME96_IO_REC_BUFFER + pos,
- count);
+ if (copy_to_iter_fromio(rme96->iobase + RME96_IO_REC_BUFFER + pos,
+ count, dst) != count)
+ return -EFAULT;
+ return 0;
}
/*
@@ -1232,14 +1232,16 @@ static int lpass_platform_copy(struct snd_soc_component *component,
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
if (is_cdc_dma_port(dai_id)) {
- ret = copy_from_iter_toio(dma_buf, buf, bytes);
+ if (copy_from_iter_toio(dma_buf, bytes, buf) != bytes)
+ ret = -EFAULT;
} else {
if (copy_from_iter((void __force *)dma_buf, bytes, buf) != bytes)
ret = -EFAULT;
}
} else if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) {
if (is_cdc_dma_port(dai_id)) {
- ret = copy_to_iter_fromio(buf, dma_buf, bytes);
+ if (copy_to_iter_fromio(dma_buf, bytes, buf) != bytes)
+ ret = -EFAULT;
} else {
if (copy_to_iter((void __force *)dma_buf, bytes, buf) != bytes)
ret = -EFAULT;
We introduced a couple of helpers for copying iomem over iov_iter, and the functions were formed like the former copy_from/to_user(), and the return value was adjusted to 0/-EFAULT, which made the code transition a bit easier at that time. OTOH, the standard copy_from/to_iter() functions have different argument orders and the return value, and this difference can be confusing. It's not only confusing but dangerous; actually I did write a wrong code due to that once :-< For reducing the confusion, this patch changes the syntax of those helpers to align with the standard copy_from/to_iter(). The argument order is changed and the return value is the size of copied bytes. The callers of those functions are updated accordingly, too. Signed-off-by: Takashi Iwai <tiwai@suse.de> --- include/sound/pcm.h | 7 +++--- sound/core/memory.c | 41 +++++++++++++++++++++------------ sound/pci/nm256/nm256.c | 8 +++++-- sound/pci/rme32.c | 13 +++++++---- sound/pci/rme96.c | 13 +++++++---- sound/soc/qcom/lpass-platform.c | 6 +++-- 6 files changed, 56 insertions(+), 32 deletions(-)