]> pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - drivers/infiniband/hw/ipath/ipath_mr.c
IB/ipath: Fix IB_EVENT_PORT_ERR event
[linux-2.6-omap-h63xx.git] / drivers / infiniband / hw / ipath / ipath_mr.c
index 31e70732e36950bc4d765a74779c6a86ded4cf3a..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,46 +172,56 @@ 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) {
+       list_for_each_entry(chunk, &umem->chunk_list, list) {
                for (i = 0; i < chunk->nents; i++) {
                        void *vaddr;
 
@@ -219,7 +231,7 @@ struct ib_mr *ipath_reg_user_mr(struct ib_pd *pd, struct ib_umem *region,
                                goto bail;
                        }
                        mr->mr.map[m]->segs[n].vaddr = vaddr;
-                       mr->mr.map[m]->segs[n].length = region->page_size;
+                       mr->mr.map[m]->segs[n].length = umem->page_size;
                        n++;
                        if (n == IPATH_SEGSZ) {
                                m++;
@@ -253,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;
 }