/* * Copyright (c) 2018, Mellanox Technologies. All rights reserved. * * This software is available to you under a choice of one of two * licenses. You may choose to be licensed under the terms of the GNU * General Public License (GPL) Version 2, available from the file * COPYING in the main directory of this source tree, or the * OpenIB.org BSD license below: * * Redistribution and use in source and binary forms, with or * without modification, are permitted provided that the following * conditions are met: * * - Redistributions of source code must retain the above * copyright notice, this list of conditions and the following * disclaimer. * * - Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following * disclaimer in the documentation and/or other materials * provided with the distribution. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE.
*/ #include"port_buffer.h"
int mlx5e_port_query_buffer(struct mlx5e_priv *priv, struct mlx5e_port_buffer *port_buffer)
{
u16 port_buff_cell_sz = priv->dcbx.port_buff_cell_sz; struct mlx5_core_dev *mdev = priv->mdev; int sz = MLX5_ST_SZ_BYTES(pbmc_reg);
u32 total_used = 0; void *buffer; void *out; int err; int i;
out = kzalloc(sz, GFP_KERNEL); if (!out) return -ENOMEM;
err = mlx5e_port_query_pbmc(mdev, out); if (err) goto out;
/* No limit on usage of shared buffer pool (max_buff=0) */ #define MLX5_SB_POOL_NO_THRESHOLD 0 /* Shared buffer pool usage threshold when calculated * dynamically in alpha units. alpha=13 is equivalent to * HW_alpha of [(1/128) * 2 ^ (alpha-1)] = 32, where HW_alpha * equates to the following portion of the shared buffer pool: * [32 / (1 + n * 32)] While *n* is the number of buffers * that are using the shared buffer pool.
*/ #define MLX5_SB_POOL_THRESHOLD 13
/** * select_sbcm_params() - selects the shared buffer pool configuration * * @buffer: <input> port buffer to retrieve params of * @lossless_buff_count: <input> number of lossless buffers in total * * The selection is based on the following rules: * 1. If buffer size is 0, no shared buffer pool is used. * 2. If buffer is lossy, use lossy shared buffer pool. * 3. If there are more than 1 lossless buffers, use lossless shared buffer pool * with threshold. * 4. If there is only 1 lossless buffer, use lossless shared buffer pool * without threshold. * * @return const struct mlx5_sbcm_params* selected values
*/ staticconststruct mlx5_sbcm_params *
select_sbcm_params(struct mlx5e_bufferx_reg *buffer, u8 lossless_buff_count)
{ if (buffer->size == 0) return &sbcm_default;
if (buffer->lossy) return &sbcm_lossy;
if (lossless_buff_count > 1) return &sbcm_lossless;
return &sbcm_lossless_no_threshold;
}
staticint port_update_pool_cfg(struct mlx5_core_dev *mdev, struct mlx5e_port_buffer *port_buffer)
{ conststruct mlx5_sbcm_params *p;
u8 lossless_buff_count = 0; int err; int i;
if (!MLX5_CAP_GEN(mdev, sbcam_reg)) return 0;
for (i = 0; i < MLX5E_MAX_NETWORK_BUFFER; i++)
lossless_buff_count += ((port_buffer->buffer[i].size) &&
(!(port_buffer->buffer[i].lossy)));
for (i = 0; i < MLX5E_MAX_NETWORK_BUFFER; i++) {
p = select_sbcm_params(&port_buffer->buffer[i], lossless_buff_count);
err = mlx5e_port_set_sbcm(mdev, 0, i,
MLX5_INGRESS_DIR,
p->infi_size,
p->max_buff,
p->pool_idx); if (err) return err;
}
if (shared_buffer_size < 4) {
pr_err("Requested port buffer is too large, not enough space left for shared buffer\n"); return -EINVAL;
}
/* Total shared buffer size is split in a ratio of 3:1 between * lossy and lossless pools respectively.
*/
lossless_ipool_size = shared_buffer_size / 4;
lossy_epool_size = shared_buffer_size - lossless_ipool_size;
in = kzalloc(sz, GFP_KERNEL); if (!in) return -ENOMEM;
err = mlx5e_port_query_pbmc(mdev, in); if (err) goto out;
for (i = 0; i < MLX5E_MAX_NETWORK_BUFFER; i++) { void *buffer = MLX5_ADDR_OF(pbmc_reg, in, buffer[i]);
current_headroom_cells += MLX5_GET(bufferx_reg, buffer, size);
for (i = 0; i < MLX5E_MAX_NETWORK_BUFFER; i++) { if (port_buffer->buffer[i].lossy) {
port_buffer->buffer[i].xoff = 0;
port_buffer->buffer[i].xon = 0; continue;
}
if (port_buffer->buffer[i].size <
(xoff + max_mtu + port_buff_cell_sz)) {
pr_err("buffer_size[%d]=%d is not enough for lossless buffer\n",
i, port_buffer->buffer[i].size); return -ENOMEM;
}
/** * update_buffer_lossy - Update buffer configuration based on pfc * @mdev: port function core device * @max_mtu: netdev's max_mtu * @pfc_en: <input> current pfc configuration * @buffer: <input> current prio to buffer mapping * @xoff: <input> xoff value * @port_buff_cell_sz: <input> port buffer cell_size * @port_buffer: <output> port receive buffer configuration * @change: <output> * * Update buffer configuration based on pfc configuration and * priority to buffer mapping. * Buffer's lossy bit is changed to: * lossless if there is at least one PFC enabled priority * mapped to this buffer lossy if all priorities mapped to * this buffer are PFC disabled * * @return: 0 if no error, * sets change to true if buffer configuration was modified.
*/ staticint update_buffer_lossy(struct mlx5_core_dev *mdev, unsignedint max_mtu,
u8 pfc_en, u8 *buffer, u32 xoff, u16 port_buff_cell_sz, struct mlx5e_port_buffer *port_buffer, bool *change)
{ bool changed = false;
u8 lossy_count;
u8 prio_count;
u8 lossy; int prio; int err; int i;
for (i = 0; i < MLX5E_MAX_NETWORK_BUFFER; i++) {
prio_count = 0;
lossy_count = 0;
for (prio = 0; prio < MLX5E_MAX_PRIORITY; prio++) { if (buffer[prio] != i) continue;
err = mlx5_query_port_pause(mdev, &g_rx_pause, &g_tx_pause); if (err) return err;
/* If global pause enabled, set all active buffers to lossless. * Otherwise, check PFC setting.
*/ if (g_rx_pause || g_tx_pause)
*pfc_en = 0xff; else
err = mlx5_query_port_pfc(mdev, pfc_en, NULL);
if (change & MLX5E_PORT_BUFFER_PRIO2BUFFER) {
update_prio2buffer = true; for (i = 0; i < MLX5E_MAX_NETWORK_BUFFER; i++)
netdev_dbg(priv->netdev, "%s: requested to map prio[%d] to buffer %d\n",
__func__, i, prio2buffer[i]);
err = fill_pfc_en(priv->mdev, &curr_pfc_en); if (err) return err;
/* Need to update buffer configuration if xoff value is changed */ if (!update_buffer && xoff != priv->dcbx.xoff) {
update_buffer = true;
err = update_xoff_threshold(&port_buffer, xoff, max_mtu, port_buff_cell_sz); if (err) return err;
}
/* Apply the settings */ if (update_buffer) {
err = port_set_buffer(priv, &port_buffer); if (err) return err;
}
priv->dcbx.xoff = xoff;
if (update_prio2buffer)
err = mlx5e_port_set_priority2buffer(priv->mdev, prio2buffer);
return err;
}
Messung V0.5
¤ Dauer der Verarbeitung: 0.11 Sekunden
(vorverarbeitet)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.