Author | Tokens | Token Proportion | Commits | Commit Proportion |
---|---|---|---|---|
Paul Blakey | 694 | 100.00% | 1 | 100.00% |
Total | 694 | 1 |
// SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB // Copyright (c) 2020 Mellanox Technologies #include <linux/jhash.h> #include "mod_hdr.h" #define MLX5_MH_ACT_SZ MLX5_UN_SZ_BYTES(set_add_copy_action_in_auto) struct mod_hdr_key { int num_actions; void *actions; }; struct mlx5e_mod_hdr_handle { /* a node of a hash table which keeps all the mod_hdr entries */ struct hlist_node mod_hdr_hlist; struct mod_hdr_key key; struct mlx5_modify_hdr *modify_hdr; refcount_t refcnt; struct completion res_ready; int compl_result; }; static u32 hash_mod_hdr_info(struct mod_hdr_key *key) { return jhash(key->actions, key->num_actions * MLX5_MH_ACT_SZ, 0); } static int cmp_mod_hdr_info(struct mod_hdr_key *a, struct mod_hdr_key *b) { if (a->num_actions != b->num_actions) return 1; return memcmp(a->actions, b->actions, a->num_actions * MLX5_MH_ACT_SZ); } void mlx5e_mod_hdr_tbl_init(struct mod_hdr_tbl *tbl) { mutex_init(&tbl->lock); hash_init(tbl->hlist); } void mlx5e_mod_hdr_tbl_destroy(struct mod_hdr_tbl *tbl) { mutex_destroy(&tbl->lock); } static struct mlx5e_mod_hdr_handle *mod_hdr_get(struct mod_hdr_tbl *tbl, struct mod_hdr_key *key, u32 hash_key) { struct mlx5e_mod_hdr_handle *mh, *found = NULL; hash_for_each_possible(tbl->hlist, mh, mod_hdr_hlist, hash_key) { if (!cmp_mod_hdr_info(&mh->key, key)) { refcount_inc(&mh->refcnt); found = mh; break; } } return found; } struct mlx5e_mod_hdr_handle * mlx5e_mod_hdr_attach(struct mlx5_core_dev *mdev, struct mod_hdr_tbl *tbl, enum mlx5_flow_namespace_type namespace, struct mlx5e_tc_mod_hdr_acts *mod_hdr_acts) { int num_actions, actions_size, err; struct mlx5e_mod_hdr_handle *mh; struct mod_hdr_key key; u32 hash_key; num_actions = mod_hdr_acts->num_actions; actions_size = MLX5_MH_ACT_SZ * num_actions; key.actions = mod_hdr_acts->actions; key.num_actions = num_actions; hash_key = hash_mod_hdr_info(&key); mutex_lock(&tbl->lock); mh = mod_hdr_get(tbl, &key, hash_key); if (mh) { mutex_unlock(&tbl->lock); wait_for_completion(&mh->res_ready); if (mh->compl_result < 0) { err = -EREMOTEIO; goto attach_header_err; } goto attach_header; } mh = kzalloc(sizeof(*mh) + actions_size, GFP_KERNEL); if (!mh) { mutex_unlock(&tbl->lock); return ERR_PTR(-ENOMEM); } mh->key.actions = (void *)mh + sizeof(*mh); memcpy(mh->key.actions, key.actions, actions_size); mh->key.num_actions = num_actions; refcount_set(&mh->refcnt, 1); init_completion(&mh->res_ready); hash_add(tbl->hlist, &mh->mod_hdr_hlist, hash_key); mutex_unlock(&tbl->lock); mh->modify_hdr = mlx5_modify_header_alloc(mdev, namespace, mh->key.num_actions, mh->key.actions); if (IS_ERR(mh->modify_hdr)) { err = PTR_ERR(mh->modify_hdr); mh->compl_result = err; goto alloc_header_err; } mh->compl_result = 1; complete_all(&mh->res_ready); attach_header: return mh; alloc_header_err: complete_all(&mh->res_ready); attach_header_err: mlx5e_mod_hdr_detach(mdev, tbl, mh); return ERR_PTR(err); } void mlx5e_mod_hdr_detach(struct mlx5_core_dev *mdev, struct mod_hdr_tbl *tbl, struct mlx5e_mod_hdr_handle *mh) { if (!refcount_dec_and_mutex_lock(&mh->refcnt, &tbl->lock)) return; hash_del(&mh->mod_hdr_hlist); mutex_unlock(&tbl->lock); if (mh->compl_result > 0) mlx5_modify_header_dealloc(mdev, mh->modify_hdr); kfree(mh); } struct mlx5_modify_hdr *mlx5e_mod_hdr_get(struct mlx5e_mod_hdr_handle *mh) { return mh->modify_hdr; }
Information contained on this website is for historical information purposes only and does not indicate or represent copyright ownership.
Created with Cregit http://github.com/cregit/cregit
Version 2.0-RC1