linux/drivers/infiniband/core/uverbs_std_types_counters.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB
   2/*
   3 * Copyright (c) 2018, Mellanox Technologies inc.  All rights reserved.
   4 *
   5 * This software is available to you under a choice of one of two
   6 * licenses.  You may choose to be licensed under the terms of the GNU
   7 * General Public License (GPL) Version 2, available from the file
   8 * COPYING in the main directory of this source tree, or the
   9 * OpenIB.org BSD license below:
  10 *
  11 *     Redistribution and use in source and binary forms, with or
  12 *     without modification, are permitted provided that the following
  13 *     conditions are met:
  14 *
  15 *      - Redistributions of source code must retain the above
  16 *        copyright notice, this list of conditions and the following
  17 *        disclaimer.
  18 *
  19 *      - Redistributions in binary form must reproduce the above
  20 *        copyright notice, this list of conditions and the following
  21 *        disclaimer in the documentation and/or other materials
  22 *        provided with the distribution.
  23 *
  24 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  25 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  26 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  27 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
  28 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
  29 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
  30 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
  31 * SOFTWARE.
  32 */
  33
  34#include "rdma_core.h"
  35#include "uverbs.h"
  36#include <rdma/uverbs_std_types.h>
  37
  38static int uverbs_free_counters(struct ib_uobject *uobject,
  39                                enum rdma_remove_reason why,
  40                                struct uverbs_attr_bundle *attrs)
  41{
  42        struct ib_counters *counters = uobject->object;
  43        int ret;
  44
  45        if (atomic_read(&counters->usecnt))
  46                return -EBUSY;
  47
  48        ret = counters->device->ops.destroy_counters(counters);
  49        if (ret)
  50                return ret;
  51        kfree(counters);
  52        return 0;
  53}
  54
  55static int UVERBS_HANDLER(UVERBS_METHOD_COUNTERS_CREATE)(
  56        struct uverbs_attr_bundle *attrs)
  57{
  58        struct ib_uobject *uobj = uverbs_attr_get_uobject(
  59                attrs, UVERBS_ATTR_CREATE_COUNTERS_HANDLE);
  60        struct ib_device *ib_dev = attrs->context->device;
  61        struct ib_counters *counters;
  62        int ret;
  63
  64        /*
  65         * This check should be removed once the infrastructure
  66         * have the ability to remove methods from parse tree once
  67         * such condition is met.
  68         */
  69        if (!ib_dev->ops.create_counters)
  70                return -EOPNOTSUPP;
  71
  72        counters = rdma_zalloc_drv_obj(ib_dev, ib_counters);
  73        if (!counters)
  74                return -ENOMEM;
  75
  76        counters->device = ib_dev;
  77        counters->uobject = uobj;
  78        uobj->object = counters;
  79        atomic_set(&counters->usecnt, 0);
  80
  81        ret = ib_dev->ops.create_counters(counters, attrs);
  82        if (ret)
  83                kfree(counters);
  84
  85        return ret;
  86}
  87
  88static int UVERBS_HANDLER(UVERBS_METHOD_COUNTERS_READ)(
  89        struct uverbs_attr_bundle *attrs)
  90{
  91        struct ib_counters_read_attr read_attr = {};
  92        const struct uverbs_attr *uattr;
  93        struct ib_counters *counters =
  94                uverbs_attr_get_obj(attrs, UVERBS_ATTR_READ_COUNTERS_HANDLE);
  95        int ret;
  96
  97        if (!counters->device->ops.read_counters)
  98                return -EOPNOTSUPP;
  99
 100        if (!atomic_read(&counters->usecnt))
 101                return -EINVAL;
 102
 103        ret = uverbs_get_flags32(&read_attr.flags, attrs,
 104                                 UVERBS_ATTR_READ_COUNTERS_FLAGS,
 105                                 IB_UVERBS_READ_COUNTERS_PREFER_CACHED);
 106        if (ret)
 107                return ret;
 108
 109        uattr = uverbs_attr_get(attrs, UVERBS_ATTR_READ_COUNTERS_BUFF);
 110        read_attr.ncounters = uattr->ptr_attr.len / sizeof(u64);
 111        read_attr.counters_buff = uverbs_zalloc(
 112                attrs, array_size(read_attr.ncounters, sizeof(u64)));
 113        if (IS_ERR(read_attr.counters_buff))
 114                return PTR_ERR(read_attr.counters_buff);
 115
 116        ret = counters->device->ops.read_counters(counters, &read_attr, attrs);
 117        if (ret)
 118                return ret;
 119
 120        return uverbs_copy_to(attrs, UVERBS_ATTR_READ_COUNTERS_BUFF,
 121                              read_attr.counters_buff,
 122                              read_attr.ncounters * sizeof(u64));
 123}
 124
 125DECLARE_UVERBS_NAMED_METHOD(
 126        UVERBS_METHOD_COUNTERS_CREATE,
 127        UVERBS_ATTR_IDR(UVERBS_ATTR_CREATE_COUNTERS_HANDLE,
 128                        UVERBS_OBJECT_COUNTERS,
 129                        UVERBS_ACCESS_NEW,
 130                        UA_MANDATORY));
 131
 132DECLARE_UVERBS_NAMED_METHOD_DESTROY(
 133        UVERBS_METHOD_COUNTERS_DESTROY,
 134        UVERBS_ATTR_IDR(UVERBS_ATTR_DESTROY_COUNTERS_HANDLE,
 135                        UVERBS_OBJECT_COUNTERS,
 136                        UVERBS_ACCESS_DESTROY,
 137                        UA_MANDATORY));
 138
 139DECLARE_UVERBS_NAMED_METHOD(
 140        UVERBS_METHOD_COUNTERS_READ,
 141        UVERBS_ATTR_IDR(UVERBS_ATTR_READ_COUNTERS_HANDLE,
 142                        UVERBS_OBJECT_COUNTERS,
 143                        UVERBS_ACCESS_READ,
 144                        UA_MANDATORY),
 145        UVERBS_ATTR_PTR_OUT(UVERBS_ATTR_READ_COUNTERS_BUFF,
 146                            UVERBS_ATTR_MIN_SIZE(0),
 147                            UA_MANDATORY),
 148        UVERBS_ATTR_FLAGS_IN(UVERBS_ATTR_READ_COUNTERS_FLAGS,
 149                             enum ib_uverbs_read_counters_flags));
 150
 151DECLARE_UVERBS_NAMED_OBJECT(UVERBS_OBJECT_COUNTERS,
 152                            UVERBS_TYPE_ALLOC_IDR(uverbs_free_counters),
 153                            &UVERBS_METHOD(UVERBS_METHOD_COUNTERS_CREATE),
 154                            &UVERBS_METHOD(UVERBS_METHOD_COUNTERS_DESTROY),
 155                            &UVERBS_METHOD(UVERBS_METHOD_COUNTERS_READ));
 156
 157const struct uapi_definition uverbs_def_obj_counters[] = {
 158        UAPI_DEF_CHAIN_OBJ_TREE_NAMED(UVERBS_OBJECT_COUNTERS,
 159                                      UAPI_DEF_OBJ_NEEDS_FN(destroy_counters)),
 160        {}
 161};
 162