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