]> pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - drivers/infiniband/hw/amso1100/c2_provider.c
Merge master.kernel.org:/pub/scm/linux/kernel/git/davem/sparc-2.6
[linux-2.6-omap-h63xx.git] / drivers / infiniband / hw / amso1100 / c2_provider.c
index dd6af551108bc111a87c4bb0cbd8ebd449007a6e..997cf1530762458f80e285cd8f6297a5d8eeb94e 100644 (file)
@@ -56,6 +56,7 @@
 #include <asm/byteorder.h>
 
 #include <rdma/ib_smi.h>
+#include <rdma/ib_umem.h>
 #include <rdma/ib_user_verbs.h>
 #include "c2.h"
 #include "c2_provider.h"
@@ -290,7 +291,7 @@ static int c2_destroy_qp(struct ib_qp *ib_qp)
        return 0;
 }
 
-static struct ib_cq *c2_create_cq(struct ib_device *ibdev, int entries,
+static struct ib_cq *c2_create_cq(struct ib_device *ibdev, int entries, int vector,
                                  struct ib_ucontext *context,
                                  struct ib_udata *udata)
 {
@@ -390,14 +391,19 @@ static struct ib_mr *c2_reg_phys_mr(struct ib_pd *ib_pd,
        }
 
        mr = kmalloc(sizeof(*mr), GFP_KERNEL);
-       if (!mr)
+       if (!mr) {
+               vfree(page_list);
                return ERR_PTR(-ENOMEM);
+       }
 
        mr->pd = to_c2pd(ib_pd);
+       mr->umem = NULL;
        pr_debug("%s - page shift %d, pbl_depth %d, total_len %u, "
                "*iova_start %llx, first pa %llx, last pa %llx\n",
                __FUNCTION__, page_shift, pbl_depth, total_len,
-               *iova_start, page_list[0], page_list[pbl_depth-1]);
+               (unsigned long long) *iova_start,
+               (unsigned long long) page_list[0],
+               (unsigned long long) page_list[pbl_depth-1]);
        err = c2_nsmr_register_phys_kern(to_c2dev(ib_pd->device), page_list,
                                         (1 << page_shift), pbl_depth,
                                         total_len, 0, iova_start,
@@ -424,8 +430,8 @@ static struct ib_mr *c2_get_dma_mr(struct ib_pd *pd, int acc)
        return c2_reg_phys_mr(pd, &bl, 1, acc, &kva);
 }
 
-static struct ib_mr *c2_reg_user_mr(struct ib_pd *pd, struct ib_umem *region,
-                                   int acc, struct ib_udata *udata)
+static struct ib_mr *c2_reg_user_mr(struct ib_pd *pd, u64 start, u64 length,
+                                   u64 virt, int acc, struct ib_udata *udata)
 {
        u64 *pages;
        u64 kva = 0;
@@ -437,15 +443,23 @@ static struct ib_mr *c2_reg_user_mr(struct ib_pd *pd, struct ib_umem *region,
        struct c2_mr *c2mr;
 
        pr_debug("%s:%u\n", __FUNCTION__, __LINE__);
-       shift = ffs(region->page_size) - 1;
 
        c2mr = kmalloc(sizeof(*c2mr), GFP_KERNEL);
        if (!c2mr)
                return ERR_PTR(-ENOMEM);
        c2mr->pd = c2pd;
 
+       c2mr->umem = ib_umem_get(pd->uobject->context, start, length, acc);
+       if (IS_ERR(c2mr->umem)) {
+               err = PTR_ERR(c2mr->umem);
+               kfree(c2mr);
+               return ERR_PTR(err);
+       }
+
+       shift = ffs(c2mr->umem->page_size) - 1;
+
        n = 0;
-       list_for_each_entry(chunk, &region->chunk_list, list)
+       list_for_each_entry(chunk, &c2mr->umem->chunk_list, list)
                n += chunk->nents;
 
        pages = kmalloc(n * sizeof(u64), GFP_KERNEL);
@@ -455,35 +469,34 @@ static struct ib_mr *c2_reg_user_mr(struct ib_pd *pd, struct ib_umem *region,
        }
 
        i = 0;
-       list_for_each_entry(chunk, &region->chunk_list, list) {
+       list_for_each_entry(chunk, &c2mr->umem->chunk_list, list) {
                for (j = 0; j < chunk->nmap; ++j) {
                        len = sg_dma_len(&chunk->page_list[j]) >> shift;
                        for (k = 0; k < len; ++k) {
                                pages[i++] =
                                        sg_dma_address(&chunk->page_list[j]) +
-                                       (region->page_size * k);
+                                       (c2mr->umem->page_size * k);
                        }
                }
        }
 
-       kva = (u64)region->virt_base;
+       kva = virt;
        err = c2_nsmr_register_phys_kern(to_c2dev(pd->device),
                                         pages,
-                                        region->page_size,
+                                        c2mr->umem->page_size,
                                         i,
-                                        region->length,
-                                        region->offset,
+                                        length,
+                                        c2mr->umem->offset,
                                         &kva,
                                         c2_convert_access(acc),
                                         c2mr);
        kfree(pages);
-       if (err) {
-               kfree(c2mr);
-               return ERR_PTR(err);
-       }
+       if (err)
+               goto err;
        return &c2mr->ibmr;
 
 err:
+       ib_umem_release(c2mr->umem);
        kfree(c2mr);
        return ERR_PTR(err);
 }
@@ -498,8 +511,11 @@ static int c2_dereg_mr(struct ib_mr *ib_mr)
        err = c2_stag_dealloc(to_c2dev(ib_mr->device), ib_mr->lkey);
        if (err)
                pr_debug("c2_stag_dealloc failed: %d\n", err);
-       else
+       else {
+               if (mr->umem)
+                       ib_umem_release(mr->umem);
                kfree(mr);
+       }
 
        return err;
 }
@@ -753,20 +769,17 @@ static struct net_device *c2_pseudo_netdev_init(struct c2_dev *c2dev)
 
 int c2_register_device(struct c2_dev *dev)
 {
-       int ret;
+       int ret = -ENOMEM;
        int i;
 
        /* Register pseudo network device */
        dev->pseudo_netdev = c2_pseudo_netdev_init(dev);
-       if (dev->pseudo_netdev) {
-               ret = register_netdev(dev->pseudo_netdev);
-               if (ret) {
-                       printk(KERN_ERR PFX
-                               "Unable to register netdev, ret = %d\n", ret);
-                       free_netdev(dev->pseudo_netdev);
-                       return ret;
-               }
-       }
+       if (!dev->pseudo_netdev)
+               goto out3;
+
+       ret = register_netdev(dev->pseudo_netdev);
+       if (ret)
+               goto out2;
 
        pr_debug("%s:%u\n", __FUNCTION__, __LINE__);
        strlcpy(dev->ibdev.name, "amso%d", IB_DEVICE_NAME_MAX);
@@ -794,8 +807,8 @@ int c2_register_device(struct c2_dev *dev)
        memset(&dev->ibdev.node_guid, 0, sizeof(dev->ibdev.node_guid));
        memcpy(&dev->ibdev.node_guid, dev->pseudo_netdev->dev_addr, 6);
        dev->ibdev.phys_port_cnt = 1;
+       dev->ibdev.num_comp_vectors = 1;
        dev->ibdev.dma_device = &dev->pcidev->dev;
-       dev->ibdev.class_dev.dev = &dev->pcidev->dev;
        dev->ibdev.query_device = c2_query_device;
        dev->ibdev.query_port = c2_query_port;
        dev->ibdev.modify_port = c2_modify_port;
@@ -844,21 +857,25 @@ int c2_register_device(struct c2_dev *dev)
 
        ret = ib_register_device(&dev->ibdev);
        if (ret)
-               return ret;
+               goto out1;
 
        for (i = 0; i < ARRAY_SIZE(c2_class_attributes); ++i) {
                ret = class_device_create_file(&dev->ibdev.class_dev,
                                               c2_class_attributes[i]);
-               if (ret) {
-                       unregister_netdev(dev->pseudo_netdev);
-                       free_netdev(dev->pseudo_netdev);
-                       ib_unregister_device(&dev->ibdev);
-                       return ret;
-               }
+               if (ret)
+                       goto out0;
        }
+       goto out3;
 
-       pr_debug("%s:%u\n", __FUNCTION__, __LINE__);
-       return 0;
+out0:
+       ib_unregister_device(&dev->ibdev);
+out1:
+       unregister_netdev(dev->pseudo_netdev);
+out2:
+       free_netdev(dev->pseudo_netdev);
+out3:
+       pr_debug("%s:%u ret=%d\n", __FUNCTION__, __LINE__, ret);
+       return ret;
 }
 
 void c2_unregister_device(struct c2_dev *dev)