162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * Copyright (c) by Jaroslav Kysela <perex@perex.cz> 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * Misc memory accessors 662306a36Sopenharmony_ci */ 762306a36Sopenharmony_ci 862306a36Sopenharmony_ci#include <linux/export.h> 962306a36Sopenharmony_ci#include <linux/io.h> 1062306a36Sopenharmony_ci#include <linux/uaccess.h> 1162306a36Sopenharmony_ci#include <sound/core.h> 1262306a36Sopenharmony_ci#include <sound/pcm.h> 1362306a36Sopenharmony_ci 1462306a36Sopenharmony_ci/** 1562306a36Sopenharmony_ci * copy_to_user_fromio - copy data from mmio-space to user-space 1662306a36Sopenharmony_ci * @dst: the destination pointer on user-space 1762306a36Sopenharmony_ci * @src: the source pointer on mmio 1862306a36Sopenharmony_ci * @count: the data size to copy in bytes 1962306a36Sopenharmony_ci * 2062306a36Sopenharmony_ci * Copies the data from mmio-space to user-space. 2162306a36Sopenharmony_ci * 2262306a36Sopenharmony_ci * Return: Zero if successful, or non-zero on failure. 2362306a36Sopenharmony_ci */ 2462306a36Sopenharmony_ciint copy_to_user_fromio(void __user *dst, const volatile void __iomem *src, size_t count) 2562306a36Sopenharmony_ci{ 2662306a36Sopenharmony_ci struct iov_iter iter; 2762306a36Sopenharmony_ci 2862306a36Sopenharmony_ci if (import_ubuf(ITER_DEST, dst, count, &iter)) 2962306a36Sopenharmony_ci return -EFAULT; 3062306a36Sopenharmony_ci return copy_to_iter_fromio(&iter, (const void __iomem *)src, count); 3162306a36Sopenharmony_ci} 3262306a36Sopenharmony_ciEXPORT_SYMBOL(copy_to_user_fromio); 3362306a36Sopenharmony_ci 3462306a36Sopenharmony_ci/** 3562306a36Sopenharmony_ci * copy_to_iter_fromio - copy data from mmio-space to iov_iter 3662306a36Sopenharmony_ci * @dst: the destination iov_iter 3762306a36Sopenharmony_ci * @src: the source pointer on mmio 3862306a36Sopenharmony_ci * @count: the data size to copy in bytes 3962306a36Sopenharmony_ci * 4062306a36Sopenharmony_ci * Copies the data from mmio-space to iov_iter. 4162306a36Sopenharmony_ci * 4262306a36Sopenharmony_ci * Return: Zero if successful, or non-zero on failure. 4362306a36Sopenharmony_ci */ 4462306a36Sopenharmony_ciint copy_to_iter_fromio(struct iov_iter *dst, const void __iomem *src, 4562306a36Sopenharmony_ci size_t count) 4662306a36Sopenharmony_ci{ 4762306a36Sopenharmony_ci#if defined(__i386__) || defined(CONFIG_SPARC32) 4862306a36Sopenharmony_ci return copy_to_iter((const void __force *)src, count, dst) == count ? 0 : -EFAULT; 4962306a36Sopenharmony_ci#else 5062306a36Sopenharmony_ci char buf[256]; 5162306a36Sopenharmony_ci while (count) { 5262306a36Sopenharmony_ci size_t c = count; 5362306a36Sopenharmony_ci if (c > sizeof(buf)) 5462306a36Sopenharmony_ci c = sizeof(buf); 5562306a36Sopenharmony_ci memcpy_fromio(buf, (void __iomem *)src, c); 5662306a36Sopenharmony_ci if (copy_to_iter(buf, c, dst) != c) 5762306a36Sopenharmony_ci return -EFAULT; 5862306a36Sopenharmony_ci count -= c; 5962306a36Sopenharmony_ci src += c; 6062306a36Sopenharmony_ci } 6162306a36Sopenharmony_ci return 0; 6262306a36Sopenharmony_ci#endif 6362306a36Sopenharmony_ci} 6462306a36Sopenharmony_ciEXPORT_SYMBOL(copy_to_iter_fromio); 6562306a36Sopenharmony_ci 6662306a36Sopenharmony_ci/** 6762306a36Sopenharmony_ci * copy_from_user_toio - copy data from user-space to mmio-space 6862306a36Sopenharmony_ci * @dst: the destination pointer on mmio-space 6962306a36Sopenharmony_ci * @src: the source pointer on user-space 7062306a36Sopenharmony_ci * @count: the data size to copy in bytes 7162306a36Sopenharmony_ci * 7262306a36Sopenharmony_ci * Copies the data from user-space to mmio-space. 7362306a36Sopenharmony_ci * 7462306a36Sopenharmony_ci * Return: Zero if successful, or non-zero on failure. 7562306a36Sopenharmony_ci */ 7662306a36Sopenharmony_ciint copy_from_user_toio(volatile void __iomem *dst, const void __user *src, size_t count) 7762306a36Sopenharmony_ci{ 7862306a36Sopenharmony_ci struct iov_iter iter; 7962306a36Sopenharmony_ci 8062306a36Sopenharmony_ci if (import_ubuf(ITER_SOURCE, (void __user *)src, count, &iter)) 8162306a36Sopenharmony_ci return -EFAULT; 8262306a36Sopenharmony_ci return copy_from_iter_toio((void __iomem *)dst, &iter, count); 8362306a36Sopenharmony_ci} 8462306a36Sopenharmony_ciEXPORT_SYMBOL(copy_from_user_toio); 8562306a36Sopenharmony_ci 8662306a36Sopenharmony_ci/** 8762306a36Sopenharmony_ci * copy_from_iter_toio - copy data from iov_iter to mmio-space 8862306a36Sopenharmony_ci * @dst: the destination pointer on mmio-space 8962306a36Sopenharmony_ci * @src: the source iov_iter 9062306a36Sopenharmony_ci * @count: the data size to copy in bytes 9162306a36Sopenharmony_ci * 9262306a36Sopenharmony_ci * Copies the data from iov_iter to mmio-space. 9362306a36Sopenharmony_ci * 9462306a36Sopenharmony_ci * Return: Zero if successful, or non-zero on failure. 9562306a36Sopenharmony_ci */ 9662306a36Sopenharmony_ciint copy_from_iter_toio(void __iomem *dst, struct iov_iter *src, size_t count) 9762306a36Sopenharmony_ci{ 9862306a36Sopenharmony_ci#if defined(__i386__) || defined(CONFIG_SPARC32) 9962306a36Sopenharmony_ci return copy_from_iter((void __force *)dst, count, src) == count ? 0 : -EFAULT; 10062306a36Sopenharmony_ci#else 10162306a36Sopenharmony_ci char buf[256]; 10262306a36Sopenharmony_ci while (count) { 10362306a36Sopenharmony_ci size_t c = count; 10462306a36Sopenharmony_ci if (c > sizeof(buf)) 10562306a36Sopenharmony_ci c = sizeof(buf); 10662306a36Sopenharmony_ci if (copy_from_iter(buf, c, src) != c) 10762306a36Sopenharmony_ci return -EFAULT; 10862306a36Sopenharmony_ci memcpy_toio(dst, buf, c); 10962306a36Sopenharmony_ci count -= c; 11062306a36Sopenharmony_ci dst += c; 11162306a36Sopenharmony_ci } 11262306a36Sopenharmony_ci return 0; 11362306a36Sopenharmony_ci#endif 11462306a36Sopenharmony_ci} 11562306a36Sopenharmony_ciEXPORT_SYMBOL(copy_from_iter_toio); 116