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

rqt.c (3937B)


      1// SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB
      2/* Copyright (c) 2021, Mellanox Technologies inc. All rights reserved. */
      3
      4#include "rqt.h"
      5#include <linux/mlx5/transobj.h>
      6
      7void mlx5e_rss_params_indir_init_uniform(struct mlx5e_rss_params_indir *indir,
      8					 unsigned int num_channels)
      9{
     10	unsigned int i;
     11
     12	for (i = 0; i < MLX5E_INDIR_RQT_SIZE; i++)
     13		indir->table[i] = i % num_channels;
     14}
     15
     16static int mlx5e_rqt_init(struct mlx5e_rqt *rqt, struct mlx5_core_dev *mdev,
     17			  u16 max_size, u32 *init_rqns, u16 init_size)
     18{
     19	void *rqtc;
     20	int inlen;
     21	int err;
     22	u32 *in;
     23	int i;
     24
     25	rqt->mdev = mdev;
     26	rqt->size = max_size;
     27
     28	inlen = MLX5_ST_SZ_BYTES(create_rqt_in) + sizeof(u32) * init_size;
     29	in = kvzalloc(inlen, GFP_KERNEL);
     30	if (!in)
     31		return -ENOMEM;
     32
     33	rqtc = MLX5_ADDR_OF(create_rqt_in, in, rqt_context);
     34
     35	MLX5_SET(rqtc, rqtc, rqt_max_size, rqt->size);
     36
     37	MLX5_SET(rqtc, rqtc, rqt_actual_size, init_size);
     38	for (i = 0; i < init_size; i++)
     39		MLX5_SET(rqtc, rqtc, rq_num[i], init_rqns[i]);
     40
     41	err = mlx5_core_create_rqt(rqt->mdev, in, inlen, &rqt->rqtn);
     42
     43	kvfree(in);
     44	return err;
     45}
     46
     47int mlx5e_rqt_init_direct(struct mlx5e_rqt *rqt, struct mlx5_core_dev *mdev,
     48			  bool indir_enabled, u32 init_rqn)
     49{
     50	u16 max_size = indir_enabled ? MLX5E_INDIR_RQT_SIZE : 1;
     51
     52	return mlx5e_rqt_init(rqt, mdev, max_size, &init_rqn, 1);
     53}
     54
     55static int mlx5e_bits_invert(unsigned long a, int size)
     56{
     57	int inv = 0;
     58	int i;
     59
     60	for (i = 0; i < size; i++)
     61		inv |= (test_bit(size - i - 1, &a) ? 1 : 0) << i;
     62
     63	return inv;
     64}
     65
     66static int mlx5e_calc_indir_rqns(u32 *rss_rqns, u32 *rqns, unsigned int num_rqns,
     67				 u8 hfunc, struct mlx5e_rss_params_indir *indir)
     68{
     69	unsigned int i;
     70
     71	for (i = 0; i < MLX5E_INDIR_RQT_SIZE; i++) {
     72		unsigned int ix = i;
     73
     74		if (hfunc == ETH_RSS_HASH_XOR)
     75			ix = mlx5e_bits_invert(ix, ilog2(MLX5E_INDIR_RQT_SIZE));
     76
     77		ix = indir->table[ix];
     78
     79		if (WARN_ON(ix >= num_rqns))
     80			/* Could be a bug in the driver or in the kernel part of
     81			 * ethtool: indir table refers to non-existent RQs.
     82			 */
     83			return -EINVAL;
     84		rss_rqns[i] = rqns[ix];
     85	}
     86
     87	return 0;
     88}
     89
     90int mlx5e_rqt_init_indir(struct mlx5e_rqt *rqt, struct mlx5_core_dev *mdev,
     91			 u32 *rqns, unsigned int num_rqns,
     92			 u8 hfunc, struct mlx5e_rss_params_indir *indir)
     93{
     94	u32 *rss_rqns;
     95	int err;
     96
     97	rss_rqns = kvmalloc_array(MLX5E_INDIR_RQT_SIZE, sizeof(*rss_rqns), GFP_KERNEL);
     98	if (!rss_rqns)
     99		return -ENOMEM;
    100
    101	err = mlx5e_calc_indir_rqns(rss_rqns, rqns, num_rqns, hfunc, indir);
    102	if (err)
    103		goto out;
    104
    105	err = mlx5e_rqt_init(rqt, mdev, MLX5E_INDIR_RQT_SIZE, rss_rqns, MLX5E_INDIR_RQT_SIZE);
    106
    107out:
    108	kvfree(rss_rqns);
    109	return err;
    110}
    111
    112void mlx5e_rqt_destroy(struct mlx5e_rqt *rqt)
    113{
    114	mlx5_core_destroy_rqt(rqt->mdev, rqt->rqtn);
    115}
    116
    117static int mlx5e_rqt_redirect(struct mlx5e_rqt *rqt, u32 *rqns, unsigned int size)
    118{
    119	unsigned int i;
    120	void *rqtc;
    121	int inlen;
    122	u32 *in;
    123	int err;
    124
    125	inlen = MLX5_ST_SZ_BYTES(modify_rqt_in) + sizeof(u32) * size;
    126	in = kvzalloc(inlen, GFP_KERNEL);
    127	if (!in)
    128		return -ENOMEM;
    129
    130	rqtc = MLX5_ADDR_OF(modify_rqt_in, in, ctx);
    131
    132	MLX5_SET(modify_rqt_in, in, bitmask.rqn_list, 1);
    133	MLX5_SET(rqtc, rqtc, rqt_actual_size, size);
    134	for (i = 0; i < size; i++)
    135		MLX5_SET(rqtc, rqtc, rq_num[i], rqns[i]);
    136
    137	err = mlx5_core_modify_rqt(rqt->mdev, rqt->rqtn, in, inlen);
    138
    139	kvfree(in);
    140	return err;
    141}
    142
    143int mlx5e_rqt_redirect_direct(struct mlx5e_rqt *rqt, u32 rqn)
    144{
    145	return mlx5e_rqt_redirect(rqt, &rqn, 1);
    146}
    147
    148int mlx5e_rqt_redirect_indir(struct mlx5e_rqt *rqt, u32 *rqns, unsigned int num_rqns,
    149			     u8 hfunc, struct mlx5e_rss_params_indir *indir)
    150{
    151	u32 *rss_rqns;
    152	int err;
    153
    154	if (WARN_ON(rqt->size != MLX5E_INDIR_RQT_SIZE))
    155		return -EINVAL;
    156
    157	rss_rqns = kvmalloc_array(MLX5E_INDIR_RQT_SIZE, sizeof(*rss_rqns), GFP_KERNEL);
    158	if (!rss_rqns)
    159		return -ENOMEM;
    160
    161	err = mlx5e_calc_indir_rqns(rss_rqns, rqns, num_rqns, hfunc, indir);
    162	if (err)
    163		goto out;
    164
    165	err = mlx5e_rqt_redirect(rqt, rss_rqns, MLX5E_INDIR_RQT_SIZE);
    166
    167out:
    168	kvfree(rss_rqns);
    169	return err;
    170}