]> pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - drivers/infiniband/hw/ipath/ipath_mr.c
Merge git://git.kernel.org/pub/scm/linux/kernel/git/lethal/sh-2.6
[linux-2.6-omap-h63xx.git] / drivers / infiniband / hw / ipath / ipath_mr.c
index 8cc8598d6c6968cbd2a957ec4ccd2c3d41b4ea92..e442470a23755ff87947434abc21ff39a2d54158 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2006 QLogic, Inc. All rights reserved.
+ * Copyright (c) 2006, 2007 QLogic Corporation. All rights reserved.
  * Copyright (c) 2005, 2006 PathScale, Inc. All rights reserved.
  *
  * This software is available to you under a choice of one of two
@@ -31,6 +31,7 @@
  * SOFTWARE.
  */
 
+#include <rdma/ib_umem.h>
 #include <rdma/ib_pack.h>
 #include <rdma/ib_smi.h>
 
@@ -147,6 +148,7 @@ struct ib_mr *ipath_reg_phys_mr(struct ib_pd *pd,
        mr->mr.offset = 0;
        mr->mr.access_flags = acc;
        mr->mr.max_segs = num_phys_buf;
+       mr->umem = NULL;
 
        m = 0;
        n = 0;
@@ -170,50 +172,66 @@ bail:
 /**
  * ipath_reg_user_mr - register a userspace memory region
  * @pd: protection domain for this memory region
- * @region: the user memory region
+ * @start: starting userspace address
+ * @length: length of region to register
+ * @virt_addr: virtual address to use (from HCA's point of view)
  * @mr_access_flags: access flags for this memory region
  * @udata: unused by the InfiniPath driver
  *
  * Returns the memory region on success, otherwise returns an errno.
  */
-struct ib_mr *ipath_reg_user_mr(struct ib_pd *pd, struct ib_umem *region,
-                               int mr_access_flags, struct ib_udata *udata)
+struct ib_mr *ipath_reg_user_mr(struct ib_pd *pd, u64 start, u64 length,
+                               u64 virt_addr, int mr_access_flags,
+                               struct ib_udata *udata)
 {
        struct ipath_mr *mr;
+       struct ib_umem *umem;
        struct ib_umem_chunk *chunk;
        int n, m, i;
        struct ib_mr *ret;
 
-       if (region->length == 0) {
+       if (length == 0) {
                ret = ERR_PTR(-EINVAL);
                goto bail;
        }
 
+       umem = ib_umem_get(pd->uobject->context, start, length, mr_access_flags);
+       if (IS_ERR(umem))
+               return (void *) umem;
+
        n = 0;
-       list_for_each_entry(chunk, &region->chunk_list, list)
+       list_for_each_entry(chunk, &umem->chunk_list, list)
                n += chunk->nents;
 
        mr = alloc_mr(n, &to_idev(pd->device)->lk_table);
        if (!mr) {
                ret = ERR_PTR(-ENOMEM);
+               ib_umem_release(umem);
                goto bail;
        }
 
        mr->mr.pd = pd;
-       mr->mr.user_base = region->user_base;
-       mr->mr.iova = region->virt_base;
-       mr->mr.length = region->length;
-       mr->mr.offset = region->offset;
+       mr->mr.user_base = start;
+       mr->mr.iova = virt_addr;
+       mr->mr.length = length;
+       mr->mr.offset = umem->offset;
        mr->mr.access_flags = mr_access_flags;
        mr->mr.max_segs = n;
+       mr->umem = umem;
 
        m = 0;
        n = 0;
-       list_for_each_entry(chunk, &region->chunk_list, list) {
-               for (i = 0; i < chunk->nmap; i++) {
-                       mr->mr.map[m]->segs[n].vaddr =
-                               page_address(chunk->page_list[i].page);
-                       mr->mr.map[m]->segs[n].length = region->page_size;
+       list_for_each_entry(chunk, &umem->chunk_list, list) {
+               for (i = 0; i < chunk->nents; i++) {
+                       void *vaddr;
+
+                       vaddr = page_address(chunk->page_list[i].page);
+                       if (!vaddr) {
+                               ret = ERR_PTR(-EINVAL);
+                               goto bail;
+                       }
+                       mr->mr.map[m]->segs[n].vaddr = vaddr;
+                       mr->mr.map[m]->segs[n].length = umem->page_size;
                        n++;
                        if (n == IPATH_SEGSZ) {
                                m++;
@@ -247,6 +265,10 @@ int ipath_dereg_mr(struct ib_mr *ibmr)
                i--;
                kfree(mr->mr.map[i]);
        }
+
+       if (mr->umem)
+               ib_umem_release(mr->umem);
+
        kfree(mr);
        return 0;
 }