Define simple copy helpers that work on I/O memory. This will allow reuse of existing framework functions in new use cases. Signed-off-by: Michal Wajdeczko <michal.wajdeczko@xxxxxxxxx> --- Cc: Alexander Viro <viro@xxxxxxxxxxxxxxxxxx> Cc: Andrew Morton <akpm@xxxxxxxxxxxxxxxxxxxx> Cc: Matthew Wilcox <willy@xxxxxxxxxxxxx> Cc: Rodrigo Vivi <rodrigo.vivi@xxxxxxxxx> Cc: Matthew Brost <matthew.brost@xxxxxxxxx> Cc: linux-kernel@xxxxxxxxxxxxxxx Cc: linux-fsdevel@xxxxxxxxxxxxxxx --- include/linux/uio.h | 4 ++++ lib/iov_iter.c | 42 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 46 insertions(+) diff --git a/include/linux/uio.h b/include/linux/uio.h index 853f9de5aa05..6d2a24293bd1 100644 --- a/include/linux/uio.h +++ b/include/linux/uio.h @@ -178,6 +178,10 @@ size_t copy_page_to_iter(struct page *page, size_t offset, size_t bytes, struct iov_iter *i); size_t copy_page_from_iter(struct page *page, size_t offset, size_t bytes, struct iov_iter *i); +size_t copy_iomem_to_iter(const void __iomem *from, size_t offset, + size_t bytes, struct iov_iter *i); +size_t copy_iomem_from_iter(void __iomem *to, size_t offset, + size_t bytes, struct iov_iter *i); size_t _copy_to_iter(const void *addr, size_t bytes, struct iov_iter *i); size_t _copy_from_iter(void *addr, size_t bytes, struct iov_iter *i); diff --git a/lib/iov_iter.c b/lib/iov_iter.c index 908e75a28d90..e8c1f1c68716 100644 --- a/lib/iov_iter.c +++ b/lib/iov_iter.c @@ -435,6 +435,48 @@ size_t copy_page_from_iter(struct page *page, size_t offset, size_t bytes, } EXPORT_SYMBOL(copy_page_from_iter); +size_t copy_iomem_to_iter(const void __iomem *from, size_t offset, + size_t bytes, struct iov_iter *i) +{ + unsigned char buf[SMP_CACHE_BYTES]; + size_t progress = 0, copied, len; + + from += offset; + while (bytes) { + len = min(bytes, sizeof(buf)); + memcpy_fromio(buf, from + progress, len); + copied = _copy_to_iter(buf, len, i); + if (!copied) + break; + bytes -= copied; + progress += copied; + } + + return progress; +} +EXPORT_SYMBOL(copy_iomem_to_iter); + +size_t copy_iomem_from_iter(void __iomem *to, size_t offset, + size_t bytes, struct iov_iter *i) +{ + unsigned char buf[SMP_CACHE_BYTES]; + size_t progress = 0, copied, len; + + to += offset; + while (bytes) { + len = min(bytes, sizeof(buf)); + copied = _copy_from_iter(buf, len, i); + if (!copied) + break; + memcpy_toio(to + progress, buf, copied); + bytes -= copied; + progress += copied; + } + + return progress; +} +EXPORT_SYMBOL(copy_iomem_from_iter); + static __always_inline size_t zero_to_user_iter(void __user *iter_to, size_t progress, size_t len, void *priv, void *priv2) -- 2.43.0