linux/drivers/infiniband/core/uverbs_std_types.c
<<
>>
Prefs
   1/*
   2 * Copyright (c) 2017, Mellanox Technologies inc.  All rights reserved.
   3 *
   4 * This software is available to you under a choice of one of two
   5 * licenses.  You may choose to be licensed under the terms of the GNU
   6 * General Public License (GPL) Version 2, available from the file
   7 * COPYING in the main directory of this source tree, or the
   8 * OpenIB.org BSD license below:
   9 *
  10 *     Redistribution and use in source and binary forms, with or
  11 *     without modification, are permitted provided that the following
  12 *     conditions are met:
  13 *
  14 *      - Redistributions of source code must retain the above
  15 *        copyright notice, this list of conditions and the following
  16 *        disclaimer.
  17 *
  18 *      - Redistributions in binary form must reproduce the above
  19 *        copyright notice, this list of conditions and the following
  20 *        disclaimer in the documentation and/or other materials
  21 *        provided with the distribution.
  22 *
  23 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  24 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  25 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  26 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
  27 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
  28 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
  29 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
  30 * SOFTWARE.
  31 */
  32
  33#include <rdma/uverbs_std_types.h>
  34#include <rdma/ib_user_verbs.h>
  35#include <rdma/ib_verbs.h>
  36#include <linux/bug.h>
  37#include <linux/file.h>
  38#include "rdma_core.h"
  39#include "uverbs.h"
  40
  41static int uverbs_free_ah(struct ib_uobject *uobject,
  42                          enum rdma_remove_reason why)
  43{
  44        return rdma_destroy_ah((struct ib_ah *)uobject->object);
  45}
  46
  47static int uverbs_free_flow(struct ib_uobject *uobject,
  48                            enum rdma_remove_reason why)
  49{
  50        return ib_destroy_flow((struct ib_flow *)uobject->object);
  51}
  52
  53static int uverbs_free_mw(struct ib_uobject *uobject,
  54                          enum rdma_remove_reason why)
  55{
  56        return uverbs_dealloc_mw((struct ib_mw *)uobject->object);
  57}
  58
  59static int uverbs_free_qp(struct ib_uobject *uobject,
  60                          enum rdma_remove_reason why)
  61{
  62        struct ib_qp *qp = uobject->object;
  63        struct ib_uqp_object *uqp =
  64                container_of(uobject, struct ib_uqp_object, uevent.uobject);
  65        int ret;
  66
  67        if (why == RDMA_REMOVE_DESTROY) {
  68                if (!list_empty(&uqp->mcast_list))
  69                        return -EBUSY;
  70        } else if (qp == qp->real_qp) {
  71                ib_uverbs_detach_umcast(qp, uqp);
  72        }
  73
  74        ret = ib_destroy_qp(qp);
  75        if (ret && why == RDMA_REMOVE_DESTROY)
  76                return ret;
  77
  78        if (uqp->uxrcd)
  79                atomic_dec(&uqp->uxrcd->refcnt);
  80
  81        ib_uverbs_release_uevent(uobject->context->ufile, &uqp->uevent);
  82        return ret;
  83}
  84
  85static int uverbs_free_rwq_ind_tbl(struct ib_uobject *uobject,
  86                                   enum rdma_remove_reason why)
  87{
  88        struct ib_rwq_ind_table *rwq_ind_tbl = uobject->object;
  89        struct ib_wq **ind_tbl = rwq_ind_tbl->ind_tbl;
  90        int ret;
  91
  92        ret = ib_destroy_rwq_ind_table(rwq_ind_tbl);
  93        if (!ret || why != RDMA_REMOVE_DESTROY)
  94                kfree(ind_tbl);
  95        return ret;
  96}
  97
  98static int uverbs_free_wq(struct ib_uobject *uobject,
  99                          enum rdma_remove_reason why)
 100{
 101        struct ib_wq *wq = uobject->object;
 102        struct ib_uwq_object *uwq =
 103                container_of(uobject, struct ib_uwq_object, uevent.uobject);
 104        int ret;
 105
 106        ret = ib_destroy_wq(wq);
 107        if (!ret || why != RDMA_REMOVE_DESTROY)
 108                ib_uverbs_release_uevent(uobject->context->ufile, &uwq->uevent);
 109        return ret;
 110}
 111
 112static int uverbs_free_srq(struct ib_uobject *uobject,
 113                           enum rdma_remove_reason why)
 114{
 115        struct ib_srq *srq = uobject->object;
 116        struct ib_uevent_object *uevent =
 117                container_of(uobject, struct ib_uevent_object, uobject);
 118        enum ib_srq_type  srq_type = srq->srq_type;
 119        int ret;
 120
 121        ret = ib_destroy_srq(srq);
 122
 123        if (ret && why == RDMA_REMOVE_DESTROY)
 124                return ret;
 125
 126        if (srq_type == IB_SRQT_XRC) {
 127                struct ib_usrq_object *us =
 128                        container_of(uevent, struct ib_usrq_object, uevent);
 129
 130                atomic_dec(&us->uxrcd->refcnt);
 131        }
 132
 133        ib_uverbs_release_uevent(uobject->context->ufile, uevent);
 134        return ret;
 135}
 136
 137static int uverbs_free_cq(struct ib_uobject *uobject,
 138                          enum rdma_remove_reason why)
 139{
 140        struct ib_cq *cq = uobject->object;
 141        struct ib_uverbs_event_queue *ev_queue = cq->cq_context;
 142        struct ib_ucq_object *ucq =
 143                container_of(uobject, struct ib_ucq_object, uobject);
 144        int ret;
 145
 146        ret = ib_destroy_cq(cq);
 147        if (!ret || why != RDMA_REMOVE_DESTROY)
 148                ib_uverbs_release_ucq(uobject->context->ufile, ev_queue ?
 149                                      container_of(ev_queue,
 150                                                   struct ib_uverbs_completion_event_file,
 151                                                   ev_queue) : NULL,
 152                                      ucq);
 153        return ret;
 154}
 155
 156static int uverbs_free_mr(struct ib_uobject *uobject,
 157                          enum rdma_remove_reason why)
 158{
 159        return ib_dereg_mr((struct ib_mr *)uobject->object);
 160}
 161
 162static int uverbs_free_xrcd(struct ib_uobject *uobject,
 163                            enum rdma_remove_reason why)
 164{
 165        struct ib_xrcd *xrcd = uobject->object;
 166        struct ib_uxrcd_object *uxrcd =
 167                container_of(uobject, struct ib_uxrcd_object, uobject);
 168        int ret;
 169
 170        mutex_lock(&uobject->context->ufile->device->xrcd_tree_mutex);
 171        if (why == RDMA_REMOVE_DESTROY && atomic_read(&uxrcd->refcnt))
 172                ret = -EBUSY;
 173        else
 174                ret = ib_uverbs_dealloc_xrcd(uobject->context->ufile->device,
 175                                             xrcd, why);
 176        mutex_unlock(&uobject->context->ufile->device->xrcd_tree_mutex);
 177
 178        return ret;
 179}
 180
 181static int uverbs_free_pd(struct ib_uobject *uobject,
 182                          enum rdma_remove_reason why)
 183{
 184        struct ib_pd *pd = uobject->object;
 185
 186        if (why == RDMA_REMOVE_DESTROY && atomic_read(&pd->usecnt))
 187                return -EBUSY;
 188
 189        ib_dealloc_pd((struct ib_pd *)uobject->object);
 190        return 0;
 191}
 192
 193static int uverbs_hot_unplug_completion_event_file(struct ib_uobject_file *uobj_file,
 194                                                   enum rdma_remove_reason why)
 195{
 196        struct ib_uverbs_completion_event_file *comp_event_file =
 197                container_of(uobj_file, struct ib_uverbs_completion_event_file,
 198                             uobj_file);
 199        struct ib_uverbs_event_queue *event_queue = &comp_event_file->ev_queue;
 200
 201        spin_lock_irq(&event_queue->lock);
 202        event_queue->is_closed = 1;
 203        spin_unlock_irq(&event_queue->lock);
 204
 205        if (why == RDMA_REMOVE_DRIVER_REMOVE) {
 206                wake_up_interruptible(&event_queue->poll_wait);
 207                kill_fasync(&event_queue->async_queue, SIGIO, POLL_IN);
 208        }
 209        return 0;
 210};
 211
 212const struct uverbs_obj_fd_type uverbs_type_attrs_comp_channel = {
 213        .type = UVERBS_TYPE_ALLOC_FD(sizeof(struct ib_uverbs_completion_event_file), 0),
 214        .context_closed = uverbs_hot_unplug_completion_event_file,
 215        .fops = &uverbs_event_fops,
 216        .name = "[infinibandevent]",
 217        .flags = O_RDONLY,
 218};
 219
 220const struct uverbs_obj_idr_type uverbs_type_attrs_cq = {
 221        .type = UVERBS_TYPE_ALLOC_IDR_SZ(sizeof(struct ib_ucq_object), 0),
 222        .destroy_object = uverbs_free_cq,
 223};
 224
 225const struct uverbs_obj_idr_type uverbs_type_attrs_qp = {
 226        .type = UVERBS_TYPE_ALLOC_IDR_SZ(sizeof(struct ib_uqp_object), 0),
 227        .destroy_object = uverbs_free_qp,
 228};
 229
 230const struct uverbs_obj_idr_type uverbs_type_attrs_mw = {
 231        .type = UVERBS_TYPE_ALLOC_IDR(0),
 232        .destroy_object = uverbs_free_mw,
 233};
 234
 235const struct uverbs_obj_idr_type uverbs_type_attrs_mr = {
 236        /* 1 is used in order to free the MR after all the MWs */
 237        .type = UVERBS_TYPE_ALLOC_IDR(1),
 238        .destroy_object = uverbs_free_mr,
 239};
 240
 241const struct uverbs_obj_idr_type uverbs_type_attrs_srq = {
 242        .type = UVERBS_TYPE_ALLOC_IDR_SZ(sizeof(struct ib_usrq_object), 0),
 243        .destroy_object = uverbs_free_srq,
 244};
 245
 246const struct uverbs_obj_idr_type uverbs_type_attrs_ah = {
 247        .type = UVERBS_TYPE_ALLOC_IDR(0),
 248        .destroy_object = uverbs_free_ah,
 249};
 250
 251const struct uverbs_obj_idr_type uverbs_type_attrs_flow = {
 252        .type = UVERBS_TYPE_ALLOC_IDR(0),
 253        .destroy_object = uverbs_free_flow,
 254};
 255
 256const struct uverbs_obj_idr_type uverbs_type_attrs_wq = {
 257        .type = UVERBS_TYPE_ALLOC_IDR_SZ(sizeof(struct ib_uwq_object), 0),
 258        .destroy_object = uverbs_free_wq,
 259};
 260
 261const struct uverbs_obj_idr_type uverbs_type_attrs_rwq_ind_table = {
 262        .type = UVERBS_TYPE_ALLOC_IDR(0),
 263        .destroy_object = uverbs_free_rwq_ind_tbl,
 264};
 265
 266const struct uverbs_obj_idr_type uverbs_type_attrs_xrcd = {
 267        .type = UVERBS_TYPE_ALLOC_IDR_SZ(sizeof(struct ib_uxrcd_object), 0),
 268        .destroy_object = uverbs_free_xrcd,
 269};
 270
 271const struct uverbs_obj_idr_type uverbs_type_attrs_pd = {
 272        /* 2 is used in order to free the PD after MRs */
 273        .type = UVERBS_TYPE_ALLOC_IDR(2),
 274        .destroy_object = uverbs_free_pd,
 275};
 276