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 38 static 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 ret = ib_destroy_usecnt(&counters->usecnt, why, uobject); 46 if (ret) 47 return ret; 48 49 ret = counters->device->ops.destroy_counters(counters); 50 if (ret) 51 return ret; 52 kfree(counters); 53 return 0; 54 } 55 56 static int UVERBS_HANDLER(UVERBS_METHOD_COUNTERS_CREATE)( 57 struct uverbs_attr_bundle *attrs) 58 { 59 struct ib_uobject *uobj = uverbs_attr_get_uobject( 60 attrs, UVERBS_ATTR_CREATE_COUNTERS_HANDLE); 61 struct ib_device *ib_dev = attrs->context->device; 62 struct ib_counters *counters; 63 int ret; 64 65 /* 66 * This check should be removed once the infrastructure 67 * have the ability to remove methods from parse tree once 68 * such condition is met. 69 */ 70 if (!ib_dev->ops.create_counters) 71 return -EOPNOTSUPP; 72 73 counters = rdma_zalloc_drv_obj(ib_dev, ib_counters); 74 if (!counters) 75 return -ENOMEM; 76 77 counters->device = ib_dev; 78 counters->uobject = uobj; 79 uobj->object = counters; 80 atomic_set(&counters->usecnt, 0); 81 82 ret = ib_dev->ops.create_counters(counters, attrs); 83 if (ret) 84 kfree(counters); 85 86 return ret; 87 } 88 89 static int UVERBS_HANDLER(UVERBS_METHOD_COUNTERS_READ)( 90 struct uverbs_attr_bundle *attrs) 91 { 92 struct ib_counters_read_attr read_attr = {}; 93 const struct uverbs_attr *uattr; 94 struct ib_counters *counters = 95 uverbs_attr_get_obj(attrs, UVERBS_ATTR_READ_COUNTERS_HANDLE); 96 int ret; 97 98 if (!counters->device->ops.read_counters) 99 return -EOPNOTSUPP; 100 101 if (!atomic_read(&counters->usecnt)) 102 return -EINVAL; 103 104 ret = uverbs_get_flags32(&read_attr.flags, attrs, 105 UVERBS_ATTR_READ_COUNTERS_FLAGS, 106 IB_UVERBS_READ_COUNTERS_PREFER_CACHED); 107 if (ret) 108 return ret; 109 110 uattr = uverbs_attr_get(attrs, UVERBS_ATTR_READ_COUNTERS_BUFF); 111 read_attr.ncounters = uattr->ptr_attr.len / sizeof(u64); 112 read_attr.counters_buff = uverbs_zalloc( 113 attrs, array_size(read_attr.ncounters, sizeof(u64))); 114 if (IS_ERR(read_attr.counters_buff)) 115 return PTR_ERR(read_attr.counters_buff); 116 117 ret = counters->device->ops.read_counters(counters, &read_attr, attrs); 118 if (ret) 119 return ret; 120 121 return uverbs_copy_to(attrs, UVERBS_ATTR_READ_COUNTERS_BUFF, 122 read_attr.counters_buff, 123 read_attr.ncounters * sizeof(u64)); 124 } 125 126 DECLARE_UVERBS_NAMED_METHOD( 127 UVERBS_METHOD_COUNTERS_CREATE, 128 UVERBS_ATTR_IDR(UVERBS_ATTR_CREATE_COUNTERS_HANDLE, 129 UVERBS_OBJECT_COUNTERS, 130 UVERBS_ACCESS_NEW, 131 UA_MANDATORY)); 132 133 DECLARE_UVERBS_NAMED_METHOD_DESTROY( 134 UVERBS_METHOD_COUNTERS_DESTROY, 135 UVERBS_ATTR_IDR(UVERBS_ATTR_DESTROY_COUNTERS_HANDLE, 136 UVERBS_OBJECT_COUNTERS, 137 UVERBS_ACCESS_DESTROY, 138 UA_MANDATORY)); 139 140 DECLARE_UVERBS_NAMED_METHOD( 141 UVERBS_METHOD_COUNTERS_READ, 142 UVERBS_ATTR_IDR(UVERBS_ATTR_READ_COUNTERS_HANDLE, 143 UVERBS_OBJECT_COUNTERS, 144 UVERBS_ACCESS_READ, 145 UA_MANDATORY), 146 UVERBS_ATTR_PTR_OUT(UVERBS_ATTR_READ_COUNTERS_BUFF, 147 UVERBS_ATTR_MIN_SIZE(0), 148 UA_MANDATORY), 149 UVERBS_ATTR_FLAGS_IN(UVERBS_ATTR_READ_COUNTERS_FLAGS, 150 enum ib_uverbs_read_counters_flags)); 151 152 DECLARE_UVERBS_NAMED_OBJECT(UVERBS_OBJECT_COUNTERS, 153 UVERBS_TYPE_ALLOC_IDR(uverbs_free_counters), 154 &UVERBS_METHOD(UVERBS_METHOD_COUNTERS_CREATE), 155 &UVERBS_METHOD(UVERBS_METHOD_COUNTERS_DESTROY), 156 &UVERBS_METHOD(UVERBS_METHOD_COUNTERS_READ)); 157 158 const struct uapi_definition uverbs_def_obj_counters[] = { 159 UAPI_DEF_CHAIN_OBJ_TREE_NAMED(UVERBS_OBJECT_COUNTERS, 160 UAPI_DEF_OBJ_NEEDS_FN(destroy_counters)), 161 {} 162 }; 163