diff options
author | Haggai Eran <haggaie@mellanox.com> | 2014-12-11 10:04:13 -0500 |
---|---|---|
committer | Roland Dreier <roland@purestorage.com> | 2014-12-15 21:13:35 -0500 |
commit | c5d76f130b286682b64c659eaf6af701e3d79a7b (patch) | |
tree | 0431513226d065f1c46e106a78e3f51ddf723a2d | |
parent | 406f9e5fa9a7a60b42e676841e39f2d752266814 (diff) |
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 <haggaie@mellanox.com>
Signed-off-by: Roland Dreier <roland@purestorage.com>
-rw-r--r-- | drivers/infiniband/core/umem.c | 34 | ||||
-rw-r--r-- | include/rdma/ib_umem.h | 2 |
2 files changed, 36 insertions, 0 deletions
diff --git a/drivers/infiniband/core/umem.c b/drivers/infiniband/core/umem.c index e0f883292374..6f152628e0d2 100644 --- a/drivers/infiniband/core/umem.c +++ b/drivers/infiniband/core/umem.c | |||
@@ -292,3 +292,37 @@ int ib_umem_page_count(struct ib_umem *umem) | |||
292 | return n; | 292 | return n; |
293 | } | 293 | } |
294 | EXPORT_SYMBOL(ib_umem_page_count); | 294 | 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); | ||
diff --git a/include/rdma/ib_umem.h b/include/rdma/ib_umem.h index 7ed6d4ff58dc..45bb04bc88cd 100644 --- a/include/rdma/ib_umem.h +++ b/include/rdma/ib_umem.h | |||
@@ -84,6 +84,8 @@ struct ib_umem *ib_umem_get(struct ib_ucontext *context, unsigned long addr, | |||
84 | size_t size, int access, int dmasync); | 84 | size_t size, int access, int dmasync); |
85 | void ib_umem_release(struct ib_umem *umem); | 85 | void ib_umem_release(struct ib_umem *umem); |
86 | int ib_umem_page_count(struct ib_umem *umem); | 86 | 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); | ||
87 | 89 | ||
88 | #else /* CONFIG_INFINIBAND_USER_MEM */ | 90 | #else /* CONFIG_INFINIBAND_USER_MEM */ |
89 | 91 | ||