The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/dev/mlx5/mlx5_core/mlx5_rl.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*-
    2  * Copyright (c) 2013-2017, Mellanox Technologies, Ltd.  All rights reserved.
    3  *
    4  * Redistribution and use in source and binary forms, with or without
    5  * modification, are permitted provided that the following conditions
    6  * are met:
    7  * 1. Redistributions of source code must retain the above copyright
    8  *    notice, this list of conditions and the following disclaimer.
    9  * 2. Redistributions in binary form must reproduce the above copyright
   10  *    notice, this list of conditions and the following disclaimer in the
   11  *    documentation and/or other materials provided with the distribution.
   12  *
   13  * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS `AS IS' AND
   14  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   16  * ARE DISCLAIMED.  IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
   17  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   18  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   19  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   20  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   21  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   22  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   23  * SUCH DAMAGE.
   24  *
   25  * $FreeBSD$
   26  */
   27 
   28 #include "opt_rss.h"
   29 #include "opt_ratelimit.h"
   30 
   31 #include <linux/kernel.h>
   32 #include <linux/module.h>
   33 #include <dev/mlx5/driver.h>
   34 #include <dev/mlx5/mlx5_core/mlx5_core.h>
   35 
   36 #ifdef RATELIMIT
   37 
   38 /* Finds an entry where we can register the given rate
   39  * If the rate already exists, return the entry where it is registered,
   40  * otherwise return the first available entry.
   41  * If the table is full, return NULL
   42  */
   43 static struct mlx5_rl_entry *find_rl_entry(struct mlx5_rl_table *table,
   44                                            u32 rate, u16 burst)
   45 {
   46         struct mlx5_rl_entry *ret_entry = NULL;
   47         struct mlx5_rl_entry *entry;
   48         u16 i;
   49 
   50         for (i = 0; i < table->max_size; i++) {
   51                 entry = table->rl_entry + i;
   52                 if (entry->rate == rate && entry->burst == burst)
   53                         return entry;
   54                 if (ret_entry == NULL && entry->rate == 0)
   55                         ret_entry = entry;
   56         }
   57 
   58         return ret_entry;
   59 }
   60 
   61 static int mlx5_set_rate_limit_cmd(struct mlx5_core_dev *dev,
   62                                    u32 rate, u32 burst, u16 index)
   63 {
   64         u32 in[MLX5_ST_SZ_DW(set_rate_limit_in)] = {};
   65         u32 out[MLX5_ST_SZ_DW(set_rate_limit_out)] = {};
   66 
   67         MLX5_SET(set_rate_limit_in, in, opcode, MLX5_CMD_OP_SET_RATE_LIMIT);
   68         MLX5_SET(set_rate_limit_in, in, rate_limit_index, index);
   69         MLX5_SET(set_rate_limit_in, in, rate_limit, rate);
   70         MLX5_SET(set_rate_limit_in, in, burst_upper_bound, burst);
   71         MLX5_SET(set_rate_limit_in, in, typical_packet_size, 0 /* use MTU */);
   72 
   73         return mlx5_cmd_exec(dev, in, sizeof(in), out, sizeof(out));
   74 }
   75 
   76 int mlx5e_query_rate_limit_cmd(struct mlx5_core_dev *dev,
   77                                    u16 index, u32 *scq_handle)
   78 {
   79         int err;
   80         u32 in[MLX5_ST_SZ_DW(query_pp_rate_limit_in)] = {};
   81         u32 out[MLX5_ST_SZ_DW(query_pp_rate_limit_out)] = {};
   82 
   83         MLX5_SET(query_pp_rate_limit_in, in, opcode, MLX5_CMD_OP_QUERY_RATE_LIMIT);
   84         MLX5_SET(query_pp_rate_limit_in, in, rate_limit_index, index);
   85 
   86         err = mlx5_cmd_exec(dev, in, sizeof(in), out, sizeof(out));
   87         if (err)
   88                 return err;
   89 
   90         *scq_handle = MLX5_GET(query_pp_rate_limit_out, out, pp_context.qos_handle);
   91 
   92         return 0;
   93 }
   94 
   95 bool mlx5_rl_is_in_range(const struct mlx5_core_dev *dev, u32 rate, u32 burst)
   96 {
   97         const struct mlx5_rl_table *table = &dev->priv.rl_table;
   98 
   99         return (rate <= table->max_rate && rate >= table->min_rate &&
  100                 burst <= 65535);
  101 }
  102 EXPORT_SYMBOL(mlx5_rl_is_in_range);
  103 
  104 int mlx5_rl_add_rate(struct mlx5_core_dev *dev, u32 rate, u32 burst, u16 *index)
  105 {
  106         struct mlx5_rl_table *table = &dev->priv.rl_table;
  107         struct mlx5_rl_entry *entry;
  108         int err = 0;
  109 
  110         mutex_lock(&table->rl_lock);
  111 
  112         if (!rate || !mlx5_rl_is_in_range(dev, rate, burst)) {
  113                 mlx5_core_err(dev, "Invalid rate: %u, should be %u to %u\n",
  114                               rate, table->min_rate, table->max_rate);
  115                 err = -ERANGE;
  116                 goto out;
  117         }
  118 
  119         entry = find_rl_entry(table, rate, burst);
  120         if (!entry) {
  121                 mlx5_core_err(dev, "Max number of %u rates reached\n",
  122                               table->max_size);
  123                 err = -ENOSPC;
  124                 goto out;
  125         }
  126         if (entry->refcount == 0xFFFFFFFFU) {
  127                 /* out of refcounts */
  128                 err = -ENOMEM;
  129                 goto out;
  130         } else if (entry->refcount != 0) {
  131                 /* rate already configured */
  132                 entry->refcount++;
  133         } else {
  134                 /* new rate limit */
  135                 err = mlx5_set_rate_limit_cmd(dev, rate, burst, entry->index);
  136                 if (err) {
  137                         mlx5_core_err(dev, "Failed configuring rate: %u (%d)\n",
  138                                       rate, err);
  139                         goto out;
  140                 }
  141                 entry->rate = rate;
  142                 entry->burst = burst;
  143                 entry->refcount = 1;
  144 
  145                 if (MLX5_CAP_QOS(dev, qos_remap_pp)) {
  146                         err = mlx5e_query_rate_limit_cmd(dev, entry->index, &entry->qos_handle);
  147                         if (err) {
  148                                 mlx5_core_err(dev, "Failed retrieving schedule queue handle for"
  149                                     "SQ remap: rate: %u error:(%d)\n", rate, err);
  150                                 entry->qos_handle = MLX5_INVALID_QUEUE_HANDLE;
  151                         }
  152                 } else
  153                         entry->qos_handle = MLX5_INVALID_QUEUE_HANDLE;
  154         }
  155         *index = entry->index;
  156 
  157 out:
  158         mutex_unlock(&table->rl_lock);
  159         return err;
  160 }
  161 EXPORT_SYMBOL(mlx5_rl_add_rate);
  162 
  163 void mlx5_rl_remove_rate(struct mlx5_core_dev *dev, u32 rate, u32 burst)
  164 {
  165         struct mlx5_rl_table *table = &dev->priv.rl_table;
  166         struct mlx5_rl_entry *entry = NULL;
  167 
  168         /* 0 is a reserved value for unlimited rate */
  169         if (rate == 0)
  170                 return;
  171 
  172         mutex_lock(&table->rl_lock);
  173         entry = find_rl_entry(table, rate, burst);
  174         if (!entry || !entry->refcount) {
  175                 mlx5_core_warn(dev, "Rate %u is not configured\n", rate);
  176                 goto out;
  177         }
  178 
  179         entry->refcount--;
  180         if (!entry->refcount) {
  181                 /* need to remove rate */
  182                 mlx5_set_rate_limit_cmd(dev, 0, 0, entry->index);
  183                 entry->rate = 0;
  184                 entry->burst = 0;
  185         }
  186 
  187 out:
  188         mutex_unlock(&table->rl_lock);
  189 }
  190 EXPORT_SYMBOL(mlx5_rl_remove_rate);
  191 
  192 int mlx5_init_rl_table(struct mlx5_core_dev *dev)
  193 {
  194         struct mlx5_rl_table *table = &dev->priv.rl_table;
  195         int i;
  196 
  197         mutex_init(&table->rl_lock);
  198         if (!MLX5_CAP_GEN(dev, qos) || !MLX5_CAP_QOS(dev, packet_pacing)) {
  199                 table->max_size = 0;
  200                 return 0;
  201         }
  202 
  203         /* First entry is reserved for unlimited rate */
  204         table->max_size = MLX5_CAP_QOS(dev, packet_pacing_rate_table_size) - 1;
  205         table->max_rate = MLX5_CAP_QOS(dev, packet_pacing_max_rate);
  206         table->min_rate = MLX5_CAP_QOS(dev, packet_pacing_min_rate);
  207 
  208         table->rl_entry = kcalloc(table->max_size, sizeof(struct mlx5_rl_entry),
  209                                   GFP_KERNEL);
  210         if (!table->rl_entry)
  211                 return -ENOMEM;
  212 
  213         /* The index represents the index in HW rate limit table
  214          * Index 0 is reserved for unlimited rate
  215          */
  216         for (i = 0; i < table->max_size; i++)
  217                 table->rl_entry[i].index = i + 1;
  218 
  219         return 0;
  220 }
  221 
  222 void mlx5_cleanup_rl_table(struct mlx5_core_dev *dev)
  223 {
  224         struct mlx5_rl_table *table = &dev->priv.rl_table;
  225         int i;
  226 
  227         /* Clear all configured rates */
  228         for (i = 0; i < table->max_size; i++)
  229                 if (table->rl_entry[i].rate)
  230                         mlx5_set_rate_limit_cmd(dev, 0, 0,
  231                                                 table->rl_entry[i].index);
  232 
  233         kfree(dev->priv.rl_table.rl_entry);
  234 }
  235 
  236 #endif

Cache object: 217e73692f2045c4d05b6e4e4d2338ad


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.