// SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB #include "uverbs.h" struct ib_uflow_resources *flow_resources_alloc(size_t num_specs) { struct ib_uflow_resources *resources; resources = kzalloc_obj(*resources); if (!resources) return NULL; if (!num_specs) goto out; resources->counters = kzalloc_objs(*resources->counters, num_specs); resources->collection = kzalloc_objs(*resources->collection, num_specs); if (!resources->counters || !resources->collection) goto err; out: resources->max = num_specs; return resources; err: kfree(resources->counters); kfree(resources); return NULL; } EXPORT_SYMBOL(flow_resources_alloc); void ib_uverbs_flow_resources_free(struct ib_uflow_resources *uflow_res) { unsigned int i; if (!uflow_res) return; for (i = 0; i < uflow_res->collection_num; i++) atomic_dec(&uflow_res->collection[i]->usecnt); for (i = 0; i < uflow_res->counters_num; i++) atomic_dec(&uflow_res->counters[i]->usecnt); kfree(uflow_res->collection); kfree(uflow_res->counters); kfree(uflow_res); } EXPORT_SYMBOL(ib_uverbs_flow_resources_free); void flow_resources_add(struct ib_uflow_resources *uflow_res, enum ib_flow_spec_type type, void *ibobj) { WARN_ON(uflow_res->num >= uflow_res->max); switch (type) { case IB_FLOW_SPEC_ACTION_HANDLE: atomic_inc(&((struct ib_flow_action *)ibobj)->usecnt); uflow_res->collection[uflow_res->collection_num++] = (struct ib_flow_action *)ibobj; break; case IB_FLOW_SPEC_ACTION_COUNT: atomic_inc(&((struct ib_counters *)ibobj)->usecnt); uflow_res->counters[uflow_res->counters_num++] = (struct ib_counters *)ibobj; break; default: WARN_ON(1); } uflow_res->num++; } EXPORT_SYMBOL(flow_resources_add);