cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

geneve.c (4249B)


      1// SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB
      2/* Copyright (c) 2019 Mellanox Technologies. */
      3
      4#include <linux/kernel.h>
      5#include "mlx5_core.h"
      6#include "geneve.h"
      7
      8struct mlx5_geneve {
      9	struct mlx5_core_dev *mdev;
     10	__be16 opt_class;
     11	u8 opt_type;
     12	u32 obj_id;
     13	struct mutex sync_lock; /* protect GENEVE obj operations */
     14	u32 refcount;
     15};
     16
     17static int mlx5_geneve_tlv_option_create(struct mlx5_core_dev *mdev,
     18					 __be16 class,
     19					 u8 type,
     20					 u8 len)
     21{
     22	u32 in[MLX5_ST_SZ_DW(create_geneve_tlv_option_in)] = {};
     23	u32 out[MLX5_ST_SZ_DW(general_obj_out_cmd_hdr)] = {};
     24	u64 general_obj_types;
     25	void *hdr, *opt;
     26	u16 obj_id;
     27	int err;
     28
     29	general_obj_types = MLX5_CAP_GEN_64(mdev, general_obj_types);
     30	if (!(general_obj_types & MLX5_GENERAL_OBJ_TYPES_CAP_GENEVE_TLV_OPT))
     31		return -EINVAL;
     32
     33	hdr = MLX5_ADDR_OF(create_geneve_tlv_option_in, in, hdr);
     34	opt = MLX5_ADDR_OF(create_geneve_tlv_option_in, in, geneve_tlv_opt);
     35
     36	MLX5_SET(general_obj_in_cmd_hdr, hdr, opcode, MLX5_CMD_OP_CREATE_GENERAL_OBJECT);
     37	MLX5_SET(general_obj_in_cmd_hdr, hdr, obj_type, MLX5_OBJ_TYPE_GENEVE_TLV_OPT);
     38
     39	MLX5_SET(geneve_tlv_option, opt, option_class, be16_to_cpu(class));
     40	MLX5_SET(geneve_tlv_option, opt, option_type, type);
     41	MLX5_SET(geneve_tlv_option, opt, option_data_length, len);
     42
     43	err = mlx5_cmd_exec(mdev, in, sizeof(in), out, sizeof(out));
     44	if (err)
     45		return err;
     46
     47	obj_id = MLX5_GET(general_obj_out_cmd_hdr, out, obj_id);
     48	return obj_id;
     49}
     50
     51static void mlx5_geneve_tlv_option_destroy(struct mlx5_core_dev *mdev, u16 obj_id)
     52{
     53	u32 out[MLX5_ST_SZ_DW(general_obj_out_cmd_hdr)] = {};
     54	u32 in[MLX5_ST_SZ_DW(general_obj_in_cmd_hdr)] = {};
     55
     56	MLX5_SET(general_obj_in_cmd_hdr, in, opcode, MLX5_CMD_OP_DESTROY_GENERAL_OBJECT);
     57	MLX5_SET(general_obj_in_cmd_hdr, in, obj_type, MLX5_OBJ_TYPE_GENEVE_TLV_OPT);
     58	MLX5_SET(general_obj_in_cmd_hdr, in, obj_id, obj_id);
     59
     60	mlx5_cmd_exec(mdev, in, sizeof(in), out, sizeof(out));
     61}
     62
     63int mlx5_geneve_tlv_option_add(struct mlx5_geneve *geneve, struct geneve_opt *opt)
     64{
     65	int res = 0;
     66
     67	if (IS_ERR_OR_NULL(geneve))
     68		return -EOPNOTSUPP;
     69
     70	mutex_lock(&geneve->sync_lock);
     71
     72	if (geneve->refcount) {
     73		if (geneve->opt_class == opt->opt_class &&
     74		    geneve->opt_type == opt->type) {
     75			/* We already have TLV options obj allocated */
     76			geneve->refcount++;
     77		} else {
     78			/* TLV options obj allocated, but its params
     79			 * do not match the new request.
     80			 * We support only one such object.
     81			 */
     82			mlx5_core_warn(geneve->mdev,
     83				       "Won't create Geneve TLV opt object with class:type:len = 0x%x:0x%x:%d (another class:type already exists)\n",
     84				       be16_to_cpu(opt->opt_class),
     85				       opt->type,
     86				       opt->length);
     87			res = -EOPNOTSUPP;
     88			goto unlock;
     89		}
     90	} else {
     91		/* We don't have any TLV options obj allocated */
     92
     93		res = mlx5_geneve_tlv_option_create(geneve->mdev,
     94						    opt->opt_class,
     95						    opt->type,
     96						    opt->length);
     97		if (res < 0) {
     98			mlx5_core_warn(geneve->mdev,
     99				       "Failed creating Geneve TLV opt object class:type:len = 0x%x:0x%x:%d (err=%d)\n",
    100				       be16_to_cpu(opt->opt_class),
    101				       opt->type, opt->length, res);
    102			goto unlock;
    103		}
    104		geneve->opt_class = opt->opt_class;
    105		geneve->opt_type = opt->type;
    106		geneve->obj_id = res;
    107		geneve->refcount++;
    108	}
    109
    110unlock:
    111	mutex_unlock(&geneve->sync_lock);
    112	return res;
    113}
    114
    115void mlx5_geneve_tlv_option_del(struct mlx5_geneve *geneve)
    116{
    117	if (IS_ERR_OR_NULL(geneve))
    118		return;
    119
    120	mutex_lock(&geneve->sync_lock);
    121	if (--geneve->refcount == 0) {
    122		/* We've just removed the last user of Geneve option.
    123		 * Now delete the object in FW.
    124		 */
    125		mlx5_geneve_tlv_option_destroy(geneve->mdev, geneve->obj_id);
    126
    127		geneve->opt_class = 0;
    128		geneve->opt_type = 0;
    129		geneve->obj_id = 0;
    130	}
    131	mutex_unlock(&geneve->sync_lock);
    132}
    133
    134struct mlx5_geneve *mlx5_geneve_create(struct mlx5_core_dev *mdev)
    135{
    136	struct mlx5_geneve *geneve =
    137		kzalloc(sizeof(*geneve), GFP_KERNEL);
    138
    139	if (!geneve)
    140		return ERR_PTR(-ENOMEM);
    141	geneve->mdev = mdev;
    142	mutex_init(&geneve->sync_lock);
    143
    144	return geneve;
    145}
    146
    147void mlx5_geneve_destroy(struct mlx5_geneve *geneve)
    148{
    149	if (IS_ERR_OR_NULL(geneve))
    150		return;
    151
    152	/* Lockless since we are unloading */
    153	if (geneve->refcount)
    154		mlx5_geneve_tlv_option_destroy(geneve->mdev, geneve->obj_id);
    155
    156	kfree(geneve);
    157}