fedora core 6 1.2949 + vserver 2.2.0
[linux-2.6.git] / drivers / infiniband / hw / ipath / ipath_keys.c
index 5ae8761..851763d 100644 (file)
@@ -1,4 +1,5 @@
 /*
+ * Copyright (c) 2006 QLogic, Inc. 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
@@ -33,6 +34,7 @@
 #include <asm/io.h>
 
 #include "ipath_verbs.h"
+#include "ipath_kernel.h"
 
 /**
  * ipath_alloc_lkey - allocate an lkey
@@ -59,7 +61,7 @@ int ipath_alloc_lkey(struct ipath_lkey_table *rkt, struct ipath_mregion *mr)
                r = (r + 1) & (rkt->max - 1);
                if (r == n) {
                        spin_unlock_irqrestore(&rkt->lock, flags);
-                       _VERBS_INFO("LKEY table full\n");
+                       ipath_dbg(KERN_INFO "LKEY table full\n");
                        ret = 0;
                        goto bail;
                }
@@ -116,10 +118,12 @@ void ipath_free_lkey(struct ipath_lkey_table *rkt, u32 lkey)
  * Check the IB SGE for validity and initialize our internal version
  * of it.
  */
-int ipath_lkey_ok(struct ipath_lkey_table *rkt, struct ipath_sge *isge,
+int ipath_lkey_ok(struct ipath_qp *qp, struct ipath_sge *isge,
                  struct ib_sge *sge, int acc)
 {
+       struct ipath_lkey_table *rkt = &to_idev(qp->ibqp.device)->lk_table;
        struct ipath_mregion *mr;
+       unsigned n, m;
        size_t off;
        int ret;
 
@@ -130,14 +134,15 @@ int ipath_lkey_ok(struct ipath_lkey_table *rkt, struct ipath_sge *isge,
         */
        if (sge->lkey == 0) {
                isge->mr = NULL;
-               isge->vaddr = bus_to_virt(sge->addr);
+               isge->vaddr = (void *) sge->addr;
                isge->length = sge->length;
                isge->sge_length = sge->length;
                ret = 1;
                goto bail;
        }
        mr = rkt->table[(sge->lkey >> (32 - ib_ipath_lkey_table_size))];
-       if (unlikely(mr == NULL || mr->lkey != sge->lkey)) {
+       if (unlikely(mr == NULL || mr->lkey != sge->lkey ||
+                    qp->ibqp.pd != mr->pd)) {
                ret = 0;
                goto bail;
        }
@@ -151,20 +156,22 @@ int ipath_lkey_ok(struct ipath_lkey_table *rkt, struct ipath_sge *isge,
        }
 
        off += mr->offset;
-       isge->mr = mr;
-       isge->m = 0;
-       isge->n = 0;
-       while (off >= mr->map[isge->m]->segs[isge->n].length) {
-               off -= mr->map[isge->m]->segs[isge->n].length;
-               isge->n++;
-               if (isge->n >= IPATH_SEGSZ) {
-                       isge->m++;
-                       isge->n = 0;
+       m = 0;
+       n = 0;
+       while (off >= mr->map[m]->segs[n].length) {
+               off -= mr->map[m]->segs[n].length;
+               n++;
+               if (n >= IPATH_SEGSZ) {
+                       m++;
+                       n = 0;
                }
        }
-       isge->vaddr = mr->map[isge->m]->segs[isge->n].vaddr + off;
-       isge->length = mr->map[isge->m]->segs[isge->n].length - off;
+       isge->mr = mr;
+       isge->vaddr = mr->map[m]->segs[n].vaddr + off;
+       isge->length = mr->map[m]->segs[n].length - off;
        isge->sge_length = sge->length;
+       isge->m = m;
+       isge->n = n;
 
        ret = 1;
 
@@ -183,17 +190,35 @@ bail:
  *
  * Return 1 if successful, otherwise 0.
  */
-int ipath_rkey_ok(struct ipath_ibdev *dev, struct ipath_sge_state *ss,
+int ipath_rkey_ok(struct ipath_qp *qp, struct ipath_sge_state *ss,
                  u32 len, u64 vaddr, u32 rkey, int acc)
 {
+       struct ipath_ibdev *dev = to_idev(qp->ibqp.device);
        struct ipath_lkey_table *rkt = &dev->lk_table;
        struct ipath_sge *sge = &ss->sge;
        struct ipath_mregion *mr;
+       unsigned n, m;
        size_t off;
        int ret;
 
+       /*
+        * We use RKEY == zero for kernel virtual addresses
+        * (see ipath_get_dma_mr and ipath_dma.c).
+        */
+       if (rkey == 0) {
+               sge->mr = NULL;
+               sge->vaddr = (void *) vaddr;
+               sge->length = len;
+               sge->sge_length = len;
+               ss->sg_list = NULL;
+               ss->num_sge = 1;
+               ret = 1;
+               goto bail;
+       }
+
        mr = rkt->table[(rkey >> (32 - ib_ipath_lkey_table_size))];
-       if (unlikely(mr == NULL || mr->lkey != rkey)) {
+       if (unlikely(mr == NULL || mr->lkey != rkey ||
+                    qp->ibqp.pd != mr->pd)) {
                ret = 0;
                goto bail;
        }
@@ -206,20 +231,22 @@ int ipath_rkey_ok(struct ipath_ibdev *dev, struct ipath_sge_state *ss,
        }
 
        off += mr->offset;
-       sge->mr = mr;
-       sge->m = 0;
-       sge->n = 0;
-       while (off >= mr->map[sge->m]->segs[sge->n].length) {
-               off -= mr->map[sge->m]->segs[sge->n].length;
-               sge->n++;
-               if (sge->n >= IPATH_SEGSZ) {
-                       sge->m++;
-                       sge->n = 0;
+       m = 0;
+       n = 0;
+       while (off >= mr->map[m]->segs[n].length) {
+               off -= mr->map[m]->segs[n].length;
+               n++;
+               if (n >= IPATH_SEGSZ) {
+                       m++;
+                       n = 0;
                }
        }
-       sge->vaddr = mr->map[sge->m]->segs[sge->n].vaddr + off;
-       sge->length = mr->map[sge->m]->segs[sge->n].length - off;
+       sge->mr = mr;
+       sge->vaddr = mr->map[m]->segs[n].vaddr + off;
+       sge->length = mr->map[m]->segs[n].length - off;
        sge->sge_length = len;
+       sge->m = m;
+       sge->n = n;
        ss->sg_list = NULL;
        ss->num_sge = 1;