]> pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - drivers/infiniband/hw/ehca/ehca_mrmw.c
Merge master.kernel.org:/pub/scm/linux/kernel/git/jejb/scsi-misc-2.6
[linux-2.6-omap-h63xx.git] / drivers / infiniband / hw / ehca / ehca_mrmw.c
index d22ab563633f0ed10c7cb476e5ebe5deec452ed0..add79bd44e398b0ef82fa7f193f27470ccf92714 100644 (file)
@@ -39,6 +39,8 @@
  * POSSIBILITY OF SUCH DAMAGE.
  */
 
+#include <rdma/ib_umem.h>
+
 #include <asm/current.h>
 
 #include "ehca_iverbs.h"
@@ -238,10 +240,8 @@ reg_phys_mr_exit0:
 
 /*----------------------------------------------------------------------*/
 
-struct ib_mr *ehca_reg_user_mr(struct ib_pd *pd,
-                              struct ib_umem *region,
-                              int mr_access_flags,
-                              struct ib_udata *udata)
+struct ib_mr *ehca_reg_user_mr(struct ib_pd *pd, u64 start, u64 length, u64 virt,
+                              int mr_access_flags, struct ib_udata *udata)
 {
        struct ib_mr *ib_mr;
        struct ehca_mr *e_mr;
@@ -257,11 +257,7 @@ struct ib_mr *ehca_reg_user_mr(struct ib_pd *pd,
                ehca_gen_err("bad pd=%p", pd);
                return ERR_PTR(-EFAULT);
        }
-       if (!region) {
-               ehca_err(pd->device, "bad input values: region=%p", region);
-               ib_mr = ERR_PTR(-EINVAL);
-               goto reg_user_mr_exit0;
-       }
+
        if (((mr_access_flags & IB_ACCESS_REMOTE_WRITE) &&
             !(mr_access_flags & IB_ACCESS_LOCAL_WRITE)) ||
            ((mr_access_flags & IB_ACCESS_REMOTE_ATOMIC) &&
@@ -275,17 +271,10 @@ struct ib_mr *ehca_reg_user_mr(struct ib_pd *pd,
                ib_mr = ERR_PTR(-EINVAL);
                goto reg_user_mr_exit0;
        }
-       if (region->page_size != PAGE_SIZE) {
-               ehca_err(pd->device, "page size not supported, "
-                        "region->page_size=%x", region->page_size);
-               ib_mr = ERR_PTR(-EINVAL);
-               goto reg_user_mr_exit0;
-       }
 
-       if ((region->length == 0) ||
-           ((region->virt_base + region->length) < region->virt_base)) {
+       if (length == 0 || virt + length < virt) {
                ehca_err(pd->device, "bad input values: length=%lx "
-                        "virt_base=%lx", region->length, region->virt_base);
+                        "virt_base=%lx", length, virt);
                ib_mr = ERR_PTR(-EINVAL);
                goto reg_user_mr_exit0;
        }
@@ -297,40 +286,55 @@ struct ib_mr *ehca_reg_user_mr(struct ib_pd *pd,
                goto reg_user_mr_exit0;
        }
 
+       e_mr->umem = ib_umem_get(pd->uobject->context, start, length,
+                                mr_access_flags);
+       if (IS_ERR(e_mr->umem)) {
+               ib_mr = (void *) e_mr->umem;
+               goto reg_user_mr_exit1;
+       }
+
+       if (e_mr->umem->page_size != PAGE_SIZE) {
+               ehca_err(pd->device, "page size not supported, "
+                        "e_mr->umem->page_size=%x", e_mr->umem->page_size);
+               ib_mr = ERR_PTR(-EINVAL);
+               goto reg_user_mr_exit2;
+       }
+
        /* determine number of MR pages */
-       num_pages_mr = (((region->virt_base % PAGE_SIZE) + region->length +
-                        PAGE_SIZE - 1) / PAGE_SIZE);
-       num_pages_4k = (((region->virt_base % EHCA_PAGESIZE) + region->length +
-                        EHCA_PAGESIZE - 1) / EHCA_PAGESIZE);
+       num_pages_mr = (((virt % PAGE_SIZE) + length + PAGE_SIZE - 1) /
+                       PAGE_SIZE);
+       num_pages_4k = (((virt % EHCA_PAGESIZE) + length + EHCA_PAGESIZE - 1) /
+                       EHCA_PAGESIZE);
 
        /* register MR on HCA */
        pginfo.type       = EHCA_MR_PGI_USER;
        pginfo.num_pages  = num_pages_mr;
        pginfo.num_4k     = num_pages_4k;
-       pginfo.region     = region;
-       pginfo.next_4k    = region->offset / EHCA_PAGESIZE;
+       pginfo.region     = e_mr->umem;
+       pginfo.next_4k    = e_mr->umem->offset / EHCA_PAGESIZE;
        pginfo.next_chunk = list_prepare_entry(pginfo.next_chunk,
-                                              (&region->chunk_list),
+                                              (&e_mr->umem->chunk_list),
                                               list);
 
-       ret = ehca_reg_mr(shca, e_mr, (u64*)region->virt_base,
-                         region->length, mr_access_flags, e_pd, &pginfo,
-                         &e_mr->ib.ib_mr.lkey, &e_mr->ib.ib_mr.rkey);
+       ret = ehca_reg_mr(shca, e_mr, (u64*) virt, length, mr_access_flags, e_pd,
+                         &pginfo, &e_mr->ib.ib_mr.lkey, &e_mr->ib.ib_mr.rkey);
        if (ret) {
                ib_mr = ERR_PTR(ret);
-               goto reg_user_mr_exit1;
+               goto reg_user_mr_exit2;
        }
 
        /* successful registration of all pages */
        return &e_mr->ib.ib_mr;
 
+reg_user_mr_exit2:
+       ib_umem_release(e_mr->umem);
 reg_user_mr_exit1:
        ehca_mr_delete(e_mr);
 reg_user_mr_exit0:
        if (IS_ERR(ib_mr))
-               ehca_err(pd->device, "rc=%lx pd=%p region=%p mr_access_flags=%x"
+               ehca_err(pd->device, "rc=%lx pd=%p mr_access_flags=%x"
                         " udata=%p",
-                        PTR_ERR(ib_mr), pd, region, mr_access_flags, udata);
+                        PTR_ERR(ib_mr), pd, mr_access_flags, udata);
        return ib_mr;
 } /* end ehca_reg_user_mr() */
 
@@ -596,6 +600,9 @@ int ehca_dereg_mr(struct ib_mr *mr)
                goto dereg_mr_exit0;
        }
 
+       if (e_mr->umem)
+               ib_umem_release(e_mr->umem);
+
        /* successful deregistration */
        ehca_mr_delete(e_mr);
 
@@ -2043,13 +2050,10 @@ int ehca_mrmw_map_hrc_alloc(const u64 hipz_rc)
        switch (hipz_rc) {
        case H_SUCCESS:              /* successful completion */
                return 0;
-       case H_ADAPTER_PARM:         /* invalid adapter handle */
-       case H_RT_PARM:              /* invalid resource type */
        case H_NOT_ENOUGH_RESOURCES: /* insufficient resources */
-       case H_MLENGTH_PARM:         /* invalid memory length */
-       case H_MEM_ACCESS_PARM:      /* invalid access controls */
        case H_CONSTRAINED:          /* resource constraint */
-               return -EINVAL;
+       case H_NO_MEM:
+               return -ENOMEM;
        case H_BUSY:                 /* long busy */
                return -EBUSY;
        default: