1 | // SPDX-License-Identifier: GPL-2.0-or-later |
2 | /* |
3 | * Copyright (c) by Jaroslav Kysela <perex@perex.cz> |
4 | * |
5 | * Misc memory accessors |
6 | */ |
7 | |
8 | #include <linux/export.h> |
9 | #include <linux/io.h> |
10 | #include <linux/uaccess.h> |
11 | #include <sound/core.h> |
12 | #include <sound/pcm.h> |
13 | |
14 | /** |
15 | * copy_to_user_fromio - copy data from mmio-space to user-space |
16 | * @dst: the destination pointer on user-space |
17 | * @src: the source pointer on mmio |
18 | * @count: the data size to copy in bytes |
19 | * |
20 | * Copies the data from mmio-space to user-space. |
21 | * |
22 | * Return: Zero if successful, or non-zero on failure. |
23 | */ |
24 | int copy_to_user_fromio(void __user *dst, const volatile void __iomem *src, size_t count) |
25 | { |
26 | struct iov_iter iter; |
27 | |
28 | if (import_ubuf(ITER_DEST, buf: dst, len: count, i: &iter)) |
29 | return -EFAULT; |
30 | return copy_to_iter_fromio(itert: &iter, src: (const void __iomem *)src, count); |
31 | } |
32 | EXPORT_SYMBOL(copy_to_user_fromio); |
33 | |
34 | /** |
35 | * copy_to_iter_fromio - copy data from mmio-space to iov_iter |
36 | * @dst: the destination iov_iter |
37 | * @src: the source pointer on mmio |
38 | * @count: the data size to copy in bytes |
39 | * |
40 | * Copies the data from mmio-space to iov_iter. |
41 | * |
42 | * Return: Zero if successful, or non-zero on failure. |
43 | */ |
44 | int copy_to_iter_fromio(struct iov_iter *dst, const void __iomem *src, |
45 | size_t count) |
46 | { |
47 | #if defined(__i386__) || defined(CONFIG_SPARC32) |
48 | return copy_to_iter((const void __force *)src, count, dst) == count ? 0 : -EFAULT; |
49 | #else |
50 | char buf[256]; |
51 | while (count) { |
52 | size_t c = count; |
53 | if (c > sizeof(buf)) |
54 | c = sizeof(buf); |
55 | memcpy_fromio(buf, (void __iomem *)src, c); |
56 | if (copy_to_iter(addr: buf, bytes: c, i: dst) != c) |
57 | return -EFAULT; |
58 | count -= c; |
59 | src += c; |
60 | } |
61 | return 0; |
62 | #endif |
63 | } |
64 | EXPORT_SYMBOL(copy_to_iter_fromio); |
65 | |
66 | /** |
67 | * copy_from_user_toio - copy data from user-space to mmio-space |
68 | * @dst: the destination pointer on mmio-space |
69 | * @src: the source pointer on user-space |
70 | * @count: the data size to copy in bytes |
71 | * |
72 | * Copies the data from user-space to mmio-space. |
73 | * |
74 | * Return: Zero if successful, or non-zero on failure. |
75 | */ |
76 | int copy_from_user_toio(volatile void __iomem *dst, const void __user *src, size_t count) |
77 | { |
78 | struct iov_iter iter; |
79 | |
80 | if (import_ubuf(ITER_SOURCE, buf: (void __user *)src, len: count, i: &iter)) |
81 | return -EFAULT; |
82 | return copy_from_iter_toio(dst: (void __iomem *)dst, iter: &iter, count); |
83 | } |
84 | EXPORT_SYMBOL(copy_from_user_toio); |
85 | |
86 | /** |
87 | * copy_from_iter_toio - copy data from iov_iter to mmio-space |
88 | * @dst: the destination pointer on mmio-space |
89 | * @src: the source iov_iter |
90 | * @count: the data size to copy in bytes |
91 | * |
92 | * Copies the data from iov_iter to mmio-space. |
93 | * |
94 | * Return: Zero if successful, or non-zero on failure. |
95 | */ |
96 | int copy_from_iter_toio(void __iomem *dst, struct iov_iter *src, size_t count) |
97 | { |
98 | #if defined(__i386__) || defined(CONFIG_SPARC32) |
99 | return copy_from_iter((void __force *)dst, count, src) == count ? 0 : -EFAULT; |
100 | #else |
101 | char buf[256]; |
102 | while (count) { |
103 | size_t c = count; |
104 | if (c > sizeof(buf)) |
105 | c = sizeof(buf); |
106 | if (copy_from_iter(addr: buf, bytes: c, i: src) != c) |
107 | return -EFAULT; |
108 | memcpy_toio(dst, buf, c); |
109 | count -= c; |
110 | dst += c; |
111 | } |
112 | return 0; |
113 | #endif |
114 | } |
115 | EXPORT_SYMBOL(copy_from_iter_toio); |
116 | |