IB/core: Guarantee that a local_dma_lkey is available
[cascardo/linux.git] / drivers / infiniband / core / verbs.c
index bac3fb4..2e5fd89 100644 (file)
@@ -213,24 +213,61 @@ EXPORT_SYMBOL(rdma_port_get_link_layer);
 
 /* Protection domains */
 
+/**
+ * ib_alloc_pd - Allocates an unused protection domain.
+ * @device: The device on which to allocate the protection domain.
+ *
+ * A protection domain object provides an association between QPs, shared
+ * receive queues, address handles, memory regions, and memory windows.
+ *
+ * Every PD has a local_dma_lkey which can be used as the lkey value for local
+ * memory operations.
+ */
 struct ib_pd *ib_alloc_pd(struct ib_device *device)
 {
        struct ib_pd *pd;
+       struct ib_device_attr devattr;
+       int rc;
+
+       rc = ib_query_device(device, &devattr);
+       if (rc)
+               return ERR_PTR(rc);
 
        pd = device->alloc_pd(device, NULL, NULL);
+       if (IS_ERR(pd))
+               return pd;
+
+       pd->device = device;
+       pd->uobject = NULL;
+       pd->local_mr = NULL;
+       atomic_set(&pd->usecnt, 0);
+
+       if (devattr.device_cap_flags & IB_DEVICE_LOCAL_DMA_LKEY)
+               pd->local_dma_lkey = device->local_dma_lkey;
+       else {
+               struct ib_mr *mr;
+
+               mr = ib_get_dma_mr(pd, IB_ACCESS_LOCAL_WRITE);
+               if (IS_ERR(mr)) {
+                       ib_dealloc_pd(pd);
+                       return (struct ib_pd *)mr;
+               }
 
-       if (!IS_ERR(pd)) {
-               pd->device  = device;
-               pd->uobject = NULL;
-               atomic_set(&pd->usecnt, 0);
+               pd->local_mr = mr;
+               pd->local_dma_lkey = pd->local_mr->lkey;
        }
-
        return pd;
 }
 EXPORT_SYMBOL(ib_alloc_pd);
 
 int ib_dealloc_pd(struct ib_pd *pd)
 {
+       if (pd->local_mr) {
+               if (ib_dereg_mr(pd->local_mr))
+                       return -EBUSY;
+               pd->local_mr = NULL;
+       }
+
        if (atomic_read(&pd->usecnt))
                return -EBUSY;
 
@@ -1235,54 +1272,28 @@ int ib_dereg_mr(struct ib_mr *mr)
 }
 EXPORT_SYMBOL(ib_dereg_mr);
 
-struct ib_mr *ib_create_mr(struct ib_pd *pd,
-                          struct ib_mr_init_attr *mr_init_attr)
-{
-       struct ib_mr *mr;
-
-       if (!pd->device->create_mr)
-               return ERR_PTR(-ENOSYS);
-
-       mr = pd->device->create_mr(pd, mr_init_attr);
-
-       if (!IS_ERR(mr)) {
-               mr->device  = pd->device;
-               mr->pd      = pd;
-               mr->uobject = NULL;
-               atomic_inc(&pd->usecnt);
-               atomic_set(&mr->usecnt, 0);
-       }
-
-       return mr;
-}
-EXPORT_SYMBOL(ib_create_mr);
-
-int ib_destroy_mr(struct ib_mr *mr)
-{
-       struct ib_pd *pd;
-       int ret;
-
-       if (atomic_read(&mr->usecnt))
-               return -EBUSY;
-
-       pd = mr->pd;
-       ret = mr->device->destroy_mr(mr);
-       if (!ret)
-               atomic_dec(&pd->usecnt);
-
-       return ret;
-}
-EXPORT_SYMBOL(ib_destroy_mr);
-
-struct ib_mr *ib_alloc_fast_reg_mr(struct ib_pd *pd, int max_page_list_len)
+/**
+ * ib_alloc_mr() - Allocates a memory region
+ * @pd:            protection domain associated with the region
+ * @mr_type:       memory region type
+ * @max_num_sg:    maximum sg entries available for registration.
+ *
+ * Notes:
+ * Memory registeration page/sg lists must not exceed max_num_sg.
+ * For mr_type IB_MR_TYPE_MEM_REG, the total length cannot exceed
+ * max_num_sg * used_page_size.
+ *
+ */
+struct ib_mr *ib_alloc_mr(struct ib_pd *pd,
+                         enum ib_mr_type mr_type,
+                         u32 max_num_sg)
 {
        struct ib_mr *mr;
 
-       if (!pd->device->alloc_fast_reg_mr)
+       if (!pd->device->alloc_mr)
                return ERR_PTR(-ENOSYS);
 
-       mr = pd->device->alloc_fast_reg_mr(pd, max_page_list_len);
-
+       mr = pd->device->alloc_mr(pd, mr_type, max_num_sg);
        if (!IS_ERR(mr)) {
                mr->device  = pd->device;
                mr->pd      = pd;
@@ -1293,7 +1304,7 @@ struct ib_mr *ib_alloc_fast_reg_mr(struct ib_pd *pd, int max_page_list_len)
 
        return mr;
 }
-EXPORT_SYMBOL(ib_alloc_fast_reg_mr);
+EXPORT_SYMBOL(ib_alloc_mr);
 
 struct ib_fast_reg_page_list *ib_alloc_fast_reg_page_list(struct ib_device *device,
                                                          int max_page_list_len)