]> git.ipfire.org Git - people/ms/linux.git/blobdiff - drivers/infiniband/hw/qib/qib_keys.c
IB/qib: Support the new memory registration API
[people/ms/linux.git] / drivers / infiniband / hw / qib / qib_keys.c
index eaf139a33b2e7e12a00dc39c8ae3497b12e105e4..95b8b9110fc6092c86365bdb2910380d0883372b 100644 (file)
@@ -390,3 +390,59 @@ bail:
        spin_unlock_irqrestore(&rkt->lock, flags);
        return ret;
 }
+
+/*
+ * Initialize the memory region specified by the work request.
+ */
+int qib_reg_mr(struct qib_qp *qp, struct ib_reg_wr *wr)
+{
+       struct qib_lkey_table *rkt = &to_idev(qp->ibqp.device)->lk_table;
+       struct qib_pd *pd = to_ipd(qp->ibqp.pd);
+       struct qib_mr *mr = to_imr(wr->mr);
+       struct qib_mregion *mrg;
+       u32 key = wr->key;
+       unsigned i, n, m;
+       int ret = -EINVAL;
+       unsigned long flags;
+       u64 *page_list;
+       size_t ps;
+
+       spin_lock_irqsave(&rkt->lock, flags);
+       if (pd->user || key == 0)
+               goto bail;
+
+       mrg = rcu_dereference_protected(
+               rkt->table[(key >> (32 - ib_qib_lkey_table_size))],
+               lockdep_is_held(&rkt->lock));
+       if (unlikely(mrg == NULL || qp->ibqp.pd != mrg->pd))
+               goto bail;
+
+       if (mr->npages > mrg->max_segs)
+               goto bail;
+
+       ps = mr->ibmr.page_size;
+       if (mr->ibmr.length > ps * mr->npages)
+               goto bail;
+
+       mrg->user_base = mr->ibmr.iova;
+       mrg->iova = mr->ibmr.iova;
+       mrg->lkey = key;
+       mrg->length = mr->ibmr.length;
+       mrg->access_flags = wr->access;
+       page_list = mr->pages;
+       m = 0;
+       n = 0;
+       for (i = 0; i < mr->npages; i++) {
+               mrg->map[m]->segs[n].vaddr = (void *) page_list[i];
+               mrg->map[m]->segs[n].length = ps;
+               if (++n == QIB_SEGSZ) {
+                       m++;
+                       n = 0;
+               }
+       }
+
+       ret = 0;
+bail:
+       spin_unlock_irqrestore(&rkt->lock, flags);
+       return ret;
+}