]> err.no Git - linux-2.6/commitdiff
IB/ipath: Fix offset returned to ibv_modify_srq()
authorRalph Campbell <ralph.campbell@qlogic.com>
Fri, 9 Nov 2007 23:22:31 +0000 (15:22 -0800)
committerRoland Dreier <rolandd@cisco.com>
Tue, 20 Nov 2007 19:04:41 +0000 (11:04 -0800)
The wrong offset was being returned to libipathverbs so that when
ibv_modify_srq() calls mmap(), it always fails.

Signed-off-by: Ralph Campbell <ralph.campbell@qlogic.com>
Signed-off-by: Roland Dreier <rolandd@cisco.com>
drivers/infiniband/hw/ipath/ipath_srq.c

index 40c36ec190167080784383f457dff4c541a21f71..434da6270f658797cd89aeb425538de659116237 100644 (file)
@@ -211,11 +211,11 @@ int ipath_modify_srq(struct ib_srq *ibsrq, struct ib_srq_attr *attr,
                     struct ib_udata *udata)
 {
        struct ipath_srq *srq = to_isrq(ibsrq);
+       struct ipath_rwq *wq;
        int ret = 0;
 
        if (attr_mask & IB_SRQ_MAX_WR) {
                struct ipath_rwq *owq;
-               struct ipath_rwq *wq;
                struct ipath_rwqe *p;
                u32 sz, size, n, head, tail;
 
@@ -236,27 +236,20 @@ int ipath_modify_srq(struct ib_srq *ibsrq, struct ib_srq_attr *attr,
                        goto bail;
                }
 
-               /*
-                * Return the address of the RWQ as the offset to mmap.
-                * See ipath_mmap() for details.
-                */
+               /* Check that we can write the offset to mmap. */
                if (udata && udata->inlen >= sizeof(__u64)) {
                        __u64 offset_addr;
-                       __u64 offset = (__u64) wq;
+                       __u64 offset = 0;
 
                        ret = ib_copy_from_udata(&offset_addr, udata,
                                                 sizeof(offset_addr));
-                       if (ret) {
-                               vfree(wq);
-                               goto bail;
-                       }
+                       if (ret)
+                               goto bail_free;
                        udata->outbuf = (void __user *) offset_addr;
                        ret = ib_copy_to_udata(udata, &offset,
                                               sizeof(offset));
-                       if (ret) {
-                               vfree(wq);
-                               goto bail;
-                       }
+                       if (ret)
+                               goto bail_free;
                }
 
                spin_lock_irq(&srq->rq.lock);
@@ -277,10 +270,8 @@ int ipath_modify_srq(struct ib_srq *ibsrq, struct ib_srq_attr *attr,
                else
                        n -= tail;
                if (size <= n) {
-                       spin_unlock_irq(&srq->rq.lock);
-                       vfree(wq);
                        ret = -EINVAL;
-                       goto bail;
+                       goto bail_unlock;
                }
                n = 0;
                p = wq->wq;
@@ -314,6 +305,18 @@ int ipath_modify_srq(struct ib_srq *ibsrq, struct ib_srq_attr *attr,
                        u32 s = sizeof(struct ipath_rwq) + size * sz;
 
                        ipath_update_mmap_info(dev, ip, s, wq);
+
+                       /*
+                        * Return the offset to mmap.
+                        * See ipath_mmap() for details.
+                        */
+                       if (udata && udata->inlen >= sizeof(__u64)) {
+                               ret = ib_copy_to_udata(udata, &ip->offset,
+                                                      sizeof(ip->offset));
+                               if (ret)
+                                       goto bail;
+                       }
+
                        spin_lock_irq(&dev->pending_lock);
                        if (list_empty(&ip->pending_mmaps))
                                list_add(&ip->pending_mmaps,
@@ -328,7 +331,12 @@ int ipath_modify_srq(struct ib_srq *ibsrq, struct ib_srq_attr *attr,
                        srq->limit = attr->srq_limit;
                spin_unlock_irq(&srq->rq.lock);
        }
+       goto bail;
 
+bail_unlock:
+       spin_unlock_irq(&srq->rq.lock);
+bail_free:
+       vfree(wq);
 bail:
        return ret;
 }