Skip to content

Commit c5d76f1

Browse files
haggaierolandd
authored andcommitted
IB/core: Add umem function to read data from user-space
In some drivers there's a need to read data from a user space area that was pinned using ib_umem when running from a different process context. The ib_umem_copy_from function allows reading data from the physical pages pinned in the ib_umem struct. Signed-off-by: Haggai Eran <[email protected]> Signed-off-by: Roland Dreier <[email protected]>
1 parent 406f9e5 commit c5d76f1

File tree

2 files changed

+36
-0
lines changed

2 files changed

+36
-0
lines changed

drivers/infiniband/core/umem.c

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -292,3 +292,37 @@ int ib_umem_page_count(struct ib_umem *umem)
292292
return n;
293293
}
294294
EXPORT_SYMBOL(ib_umem_page_count);
295+
296+
/*
297+
* Copy from the given ib_umem's pages to the given buffer.
298+
*
299+
* umem - the umem to copy from
300+
* offset - offset to start copying from
301+
* dst - destination buffer
302+
* length - buffer length
303+
*
304+
* Returns 0 on success, or an error code.
305+
*/
306+
int ib_umem_copy_from(void *dst, struct ib_umem *umem, size_t offset,
307+
size_t length)
308+
{
309+
size_t end = offset + length;
310+
int ret;
311+
312+
if (offset > umem->length || length > umem->length - offset) {
313+
pr_err("ib_umem_copy_from not in range. offset: %zd umem length: %zd end: %zd\n",
314+
offset, umem->length, end);
315+
return -EINVAL;
316+
}
317+
318+
ret = sg_pcopy_to_buffer(umem->sg_head.sgl, umem->nmap, dst, length,
319+
offset + ib_umem_offset(umem));
320+
321+
if (ret < 0)
322+
return ret;
323+
else if (ret != length)
324+
return -EINVAL;
325+
else
326+
return 0;
327+
}
328+
EXPORT_SYMBOL(ib_umem_copy_from);

include/rdma/ib_umem.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,8 @@ struct ib_umem *ib_umem_get(struct ib_ucontext *context, unsigned long addr,
8484
size_t size, int access, int dmasync);
8585
void ib_umem_release(struct ib_umem *umem);
8686
int ib_umem_page_count(struct ib_umem *umem);
87+
int ib_umem_copy_from(void *dst, struct ib_umem *umem, size_t offset,
88+
size_t length);
8789

8890
#else /* CONFIG_INFINIBAND_USER_MEM */
8991

0 commit comments

Comments
 (0)