linux/drivers/infiniband/core/uverbs_std_types_cq.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_core.h"
  35#include "uverbs.h"
  36#include "restrack.h"
  37
  38static int uverbs_free_cq(struct ib_uobject *uobject,
  39                          enum rdma_remove_reason why,
  40                          struct uverbs_attr_bundle *attrs)
  41{
  42        struct ib_cq *cq = uobject->object;
  43        struct ib_uverbs_event_queue *ev_queue = cq->cq_context;
  44        struct ib_ucq_object *ucq =
  45                container_of(uobject, struct ib_ucq_object, uevent.uobject);
  46        int ret;
  47
  48        ret = ib_destroy_cq_user(cq, &attrs->driver_udata);
  49        if (ret)
  50                return ret;
  51
  52        ib_uverbs_release_ucq(
  53                ev_queue ? container_of(ev_queue,
  54                                        struct ib_uverbs_completion_event_file,
  55                                        ev_queue) :
  56                           NULL,
  57                ucq);
  58        return 0;
  59}
  60
  61static int UVERBS_HANDLER(UVERBS_METHOD_CQ_CREATE)(
  62        struct uverbs_attr_bundle *attrs)
  63{
  64        struct ib_ucq_object *obj = container_of(
  65                uverbs_attr_get_uobject(attrs, UVERBS_ATTR_CREATE_CQ_HANDLE),
  66                typeof(*obj), uevent.uobject);
  67        struct ib_device *ib_dev = attrs->context->device;
  68        int ret;
  69        u64 user_handle;
  70        struct ib_cq_init_attr attr = {};
  71        struct ib_cq                   *cq;
  72        struct ib_uverbs_completion_event_file    *ev_file = NULL;
  73        struct ib_uobject *ev_file_uobj;
  74
  75        if (!ib_dev->ops.create_cq || !ib_dev->ops.destroy_cq)
  76                return -EOPNOTSUPP;
  77
  78        ret = uverbs_copy_from(&attr.comp_vector, attrs,
  79                               UVERBS_ATTR_CREATE_CQ_COMP_VECTOR);
  80        if (!ret)
  81                ret = uverbs_copy_from(&attr.cqe, attrs,
  82                                       UVERBS_ATTR_CREATE_CQ_CQE);
  83        if (!ret)
  84                ret = uverbs_copy_from(&user_handle, attrs,
  85                                       UVERBS_ATTR_CREATE_CQ_USER_HANDLE);
  86        if (ret)
  87                return ret;
  88
  89        ret = uverbs_get_flags32(&attr.flags, attrs,
  90                                 UVERBS_ATTR_CREATE_CQ_FLAGS,
  91                                 IB_UVERBS_CQ_FLAGS_TIMESTAMP_COMPLETION |
  92                                         IB_UVERBS_CQ_FLAGS_IGNORE_OVERRUN);
  93        if (ret)
  94                return ret;
  95
  96        ev_file_uobj = uverbs_attr_get_uobject(attrs, UVERBS_ATTR_CREATE_CQ_COMP_CHANNEL);
  97        if (!IS_ERR(ev_file_uobj)) {
  98                ev_file = container_of(ev_file_uobj,
  99                                       struct ib_uverbs_completion_event_file,
 100                                       uobj);
 101                uverbs_uobject_get(ev_file_uobj);
 102        }
 103
 104        obj->uevent.event_file = ib_uverbs_get_async_event(
 105                attrs, UVERBS_ATTR_CREATE_CQ_EVENT_FD);
 106
 107        if (attr.comp_vector >= attrs->ufile->device->num_comp_vectors) {
 108                ret = -EINVAL;
 109                goto err_event_file;
 110        }
 111
 112        INIT_LIST_HEAD(&obj->comp_list);
 113        INIT_LIST_HEAD(&obj->uevent.event_list);
 114
 115        cq = rdma_zalloc_drv_obj(ib_dev, ib_cq);
 116        if (!cq) {
 117                ret = -ENOMEM;
 118                goto err_event_file;
 119        }
 120
 121        cq->device        = ib_dev;
 122        cq->uobject       = obj;
 123        cq->comp_handler  = ib_uverbs_comp_handler;
 124        cq->event_handler = ib_uverbs_cq_event_handler;
 125        cq->cq_context    = ev_file ? &ev_file->ev_queue : NULL;
 126        atomic_set(&cq->usecnt, 0);
 127
 128        rdma_restrack_new(&cq->res, RDMA_RESTRACK_CQ);
 129        rdma_restrack_set_name(&cq->res, NULL);
 130
 131        ret = ib_dev->ops.create_cq(cq, &attr, &attrs->driver_udata);
 132        if (ret)
 133                goto err_free;
 134
 135        obj->uevent.uobject.object = cq;
 136        obj->uevent.uobject.user_handle = user_handle;
 137        rdma_restrack_add(&cq->res);
 138        uverbs_finalize_uobj_create(attrs, UVERBS_ATTR_CREATE_CQ_HANDLE);
 139
 140        ret = uverbs_copy_to(attrs, UVERBS_ATTR_CREATE_CQ_RESP_CQE, &cq->cqe,
 141                             sizeof(cq->cqe));
 142        return ret;
 143
 144err_free:
 145        rdma_restrack_put(&cq->res);
 146        kfree(cq);
 147err_event_file:
 148        if (obj->uevent.event_file)
 149                uverbs_uobject_put(&obj->uevent.event_file->uobj);
 150        if (ev_file)
 151                uverbs_uobject_put(ev_file_uobj);
 152        return ret;
 153};
 154
 155DECLARE_UVERBS_NAMED_METHOD(
 156        UVERBS_METHOD_CQ_CREATE,
 157        UVERBS_ATTR_IDR(UVERBS_ATTR_CREATE_CQ_HANDLE,
 158                        UVERBS_OBJECT_CQ,
 159                        UVERBS_ACCESS_NEW,
 160                        UA_MANDATORY),
 161        UVERBS_ATTR_PTR_IN(UVERBS_ATTR_CREATE_CQ_CQE,
 162                           UVERBS_ATTR_TYPE(u32),
 163                           UA_MANDATORY),
 164        UVERBS_ATTR_PTR_IN(UVERBS_ATTR_CREATE_CQ_USER_HANDLE,
 165                           UVERBS_ATTR_TYPE(u64),
 166                           UA_MANDATORY),
 167        UVERBS_ATTR_FD(UVERBS_ATTR_CREATE_CQ_COMP_CHANNEL,
 168                       UVERBS_OBJECT_COMP_CHANNEL,
 169                       UVERBS_ACCESS_READ,
 170                       UA_OPTIONAL),
 171        UVERBS_ATTR_PTR_IN(UVERBS_ATTR_CREATE_CQ_COMP_VECTOR,
 172                           UVERBS_ATTR_TYPE(u32),
 173                           UA_MANDATORY),
 174        UVERBS_ATTR_FLAGS_IN(UVERBS_ATTR_CREATE_CQ_FLAGS,
 175                             enum ib_uverbs_ex_create_cq_flags),
 176        UVERBS_ATTR_PTR_OUT(UVERBS_ATTR_CREATE_CQ_RESP_CQE,
 177                            UVERBS_ATTR_TYPE(u32),
 178                            UA_MANDATORY),
 179        UVERBS_ATTR_FD(UVERBS_ATTR_CREATE_CQ_EVENT_FD,
 180                       UVERBS_OBJECT_ASYNC_EVENT,
 181                       UVERBS_ACCESS_READ,
 182                       UA_OPTIONAL),
 183        UVERBS_ATTR_UHW());
 184
 185static int UVERBS_HANDLER(UVERBS_METHOD_CQ_DESTROY)(
 186        struct uverbs_attr_bundle *attrs)
 187{
 188        struct ib_uobject *uobj =
 189                uverbs_attr_get_uobject(attrs, UVERBS_ATTR_DESTROY_CQ_HANDLE);
 190        struct ib_ucq_object *obj =
 191                container_of(uobj, struct ib_ucq_object, uevent.uobject);
 192        struct ib_uverbs_destroy_cq_resp resp = {
 193                .comp_events_reported = obj->comp_events_reported,
 194                .async_events_reported = obj->uevent.events_reported
 195        };
 196
 197        return uverbs_copy_to(attrs, UVERBS_ATTR_DESTROY_CQ_RESP, &resp,
 198                              sizeof(resp));
 199}
 200
 201DECLARE_UVERBS_NAMED_METHOD(
 202        UVERBS_METHOD_CQ_DESTROY,
 203        UVERBS_ATTR_IDR(UVERBS_ATTR_DESTROY_CQ_HANDLE,
 204                        UVERBS_OBJECT_CQ,
 205                        UVERBS_ACCESS_DESTROY,
 206                        UA_MANDATORY),
 207        UVERBS_ATTR_PTR_OUT(UVERBS_ATTR_DESTROY_CQ_RESP,
 208                            UVERBS_ATTR_TYPE(struct ib_uverbs_destroy_cq_resp),
 209                            UA_MANDATORY));
 210
 211DECLARE_UVERBS_NAMED_OBJECT(
 212        UVERBS_OBJECT_CQ,
 213        UVERBS_TYPE_ALLOC_IDR_SZ(sizeof(struct ib_ucq_object), uverbs_free_cq),
 214        &UVERBS_METHOD(UVERBS_METHOD_CQ_CREATE),
 215        &UVERBS_METHOD(UVERBS_METHOD_CQ_DESTROY)
 216);
 217
 218const struct uapi_definition uverbs_def_obj_cq[] = {
 219        UAPI_DEF_CHAIN_OBJ_TREE_NAMED(UVERBS_OBJECT_CQ,
 220                                      UAPI_DEF_OBJ_NEEDS_FN(destroy_cq)),
 221        {}
 222};
 223