/* * Copyright (c) 2013-2015, 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.
*/
/* calling with verbose false will not print error to log */ int mlx5_access_reg(struct mlx5_core_dev *dev, void *data_in, int size_in, void *data_out, int size_out, u16 reg_id, int arg, int write, bool verbose)
{ int outlen = MLX5_ST_SZ_BYTES(access_register_out) + size_out; int inlen = MLX5_ST_SZ_BYTES(access_register_in) + size_in; int err = -ENOMEM;
u32 *out = NULL;
u32 *in = NULL; void *data;
in = kvzalloc(inlen, GFP_KERNEL);
out = kvzalloc(outlen, GFP_KERNEL); if (!in || !out) goto out;
data = MLX5_ADDR_OF(access_register_in, in, register_data);
memcpy(data, data_in, size_in);
MLX5_SET(access_register_in, in, opcode, MLX5_CMD_OP_ACCESS_REG);
MLX5_SET(access_register_in, in, op_mod, !write);
MLX5_SET(access_register_in, in, argument, arg);
MLX5_SET(access_register_in, in, register_id, reg_id);
err = mlx5_cmd_do(dev, in, inlen, out, outlen); if (verbose)
err = mlx5_cmd_check(dev, err, in, out); if (err) goto out;
data = MLX5_ADDR_OF(access_register_out, out, register_data);
memcpy(data_out, data, size_out);
/* This function should be used after setting a port register only */ void mlx5_toggle_port_link(struct mlx5_core_dev *dev)
{ enum mlx5_port_status ps;
int mlx5_query_module_num(struct mlx5_core_dev *dev, int *module_num)
{
u32 in[MLX5_ST_SZ_DW(pmlp_reg)] = {0};
u32 out[MLX5_ST_SZ_DW(pmlp_reg)]; int err;
MLX5_SET(pmlp_reg, in, local_port, 1);
err = mlx5_core_access_reg(dev, in, sizeof(in), out, sizeof(out),
MLX5_REG_PMLP, 0, 0); if (err) return err;
staticint mlx5_query_module_id(struct mlx5_core_dev *dev, int module_num,
u8 *module_id)
{
u32 in[MLX5_ST_SZ_DW(mcia_reg)] = {};
u32 out[MLX5_ST_SZ_DW(mcia_reg)]; int err, status;
u8 *ptr;
MLX5_SET(mcia_reg, in, i2c_device_address, MLX5_I2C_ADDR_LOW);
MLX5_SET(mcia_reg, in, module, module_num);
MLX5_SET(mcia_reg, in, device_address, 0);
MLX5_SET(mcia_reg, in, page_number, 0);
MLX5_SET(mcia_reg, in, size, 1);
MLX5_SET(mcia_reg, in, l, 0);
err = mlx5_core_access_reg(dev, in, sizeof(in), out, sizeof(out), MLX5_REG_MCIA, 0, 0); if (err) return err;
MLX5_SET(mcia_reg, in, l, 0);
MLX5_SET(mcia_reg, in, size, size);
MLX5_SET(mcia_reg, in, module, params->module_number);
MLX5_SET(mcia_reg, in, device_address, params->offset);
MLX5_SET(mcia_reg, in, page_number, params->page);
MLX5_SET(mcia_reg, in, i2c_device_address, params->i2c_address);
err = mlx5_core_access_reg(dev, in, sizeof(in), out, sizeof(out), MLX5_REG_MCIA, 0, 0); if (err) return err;
status = MLX5_GET(mcia_reg, out, status); if (status) {
mlx5_core_err(dev, "query_mcia_reg failed: status: 0x%x\n",
status); return -EIO;
}
int mlx5_query_module_eeprom(struct mlx5_core_dev *dev,
u16 offset, u16 size, u8 *data)
{ struct mlx5_module_eeprom_query_params query = {0};
u8 module_id; int err;
err = mlx5_query_module_num(dev, &query.module_number); if (err) return err;
err = mlx5_query_module_id(dev, query.module_number, &module_id); if (err) return err;
switch (module_id) { case MLX5_MODULE_ID_SFP:
mlx5_sfp_eeprom_params_set(&query.i2c_address, &query.page, &offset); break; case MLX5_MODULE_ID_QSFP: case MLX5_MODULE_ID_QSFP_PLUS: case MLX5_MODULE_ID_QSFP28:
mlx5_qsfp_eeprom_params_set(&query.i2c_address, &query.page, &offset); break; default:
mlx5_core_err(dev, "Module ID not recognized: 0x%x\n", module_id); return -EINVAL;
}
if (offset + size > MLX5_EEPROM_PAGE_LENGTH) /* Cross pages read, read until offset 256 in low page */
size = MLX5_EEPROM_PAGE_LENGTH - offset;
query.size = size;
query.offset = offset;
return mlx5_query_mcia(dev, &query, data);
}
int mlx5_query_module_eeprom_by_page(struct mlx5_core_dev *dev, struct mlx5_module_eeprom_query_params *params,
u8 *data)
{ int err;
err = mlx5_query_module_num(dev, ¶ms->module_number); if (err) return err;
if (params->i2c_address != MLX5_I2C_ADDR_HIGH &&
params->i2c_address != MLX5_I2C_ADDR_LOW) {
mlx5_core_err(dev, "I2C address not recognized: 0x%x\n", params->i2c_address); return -EINVAL;
}
MLX5_SET(pfcc_reg, in, local_port, 1);
MLX5_SET(pfcc_reg, in, pptx_mask_n, 1);
MLX5_SET(pfcc_reg, in, pprx_mask_n, 1);
MLX5_SET(pfcc_reg, in, ppan_mask_n, 1);
MLX5_SET(pfcc_reg, in, critical_stall_mask, 1);
MLX5_SET(pfcc_reg, in, minor_stall_mask, 1);
MLX5_SET(pfcc_reg, in, device_stall_critical_watermark,
stall_critical_watermark);
MLX5_SET(pfcc_reg, in, device_stall_minor_watermark, stall_minor_watermark);
return mlx5_core_access_reg(dev, in, sizeof(in), out, sizeof(out), MLX5_REG_PFCC, 0, 1);
}
int mlx5_query_port_stall_watermark(struct mlx5_core_dev *dev,
u16 *stall_critical_watermark,
u16 *stall_minor_watermark)
{
u32 out[MLX5_ST_SZ_DW(pfcc_reg)]; int err;
err = mlx5_query_pfcc_reg(dev, out, sizeof(out)); if (err) return err;
if (stall_critical_watermark)
*stall_critical_watermark = MLX5_GET(pfcc_reg, out,
device_stall_critical_watermark);
if (stall_minor_watermark)
*stall_minor_watermark = MLX5_GET(pfcc_reg, out,
device_stall_minor_watermark);
MLX5_SET(pfcc_reg, in, local_port, 1);
MLX5_SET(pfcc_reg, in, pfctx, pfc_en_tx);
MLX5_SET(pfcc_reg, in, pfcrx, pfc_en_rx);
MLX5_SET_TO_ONES(pfcc_reg, in, prio_mask_tx);
MLX5_SET_TO_ONES(pfcc_reg, in, prio_mask_rx);
return mlx5_core_access_reg(dev, in, sizeof(in), out, sizeof(out), MLX5_REG_PFCC, 0, 1);
}
int mlx5_query_port_pfc(struct mlx5_core_dev *dev, u8 *pfc_en_tx, u8 *pfc_en_rx)
{
u32 out[MLX5_ST_SZ_DW(pfcc_reg)]; int err;
err = mlx5_query_pfcc_reg(dev, out, sizeof(out)); if (err) return err;
if (pfc_en_tx)
*pfc_en_tx = MLX5_GET(pfcc_reg, out, pfctx);
if (pfc_en_rx)
*pfc_en_rx = MLX5_GET(pfcc_reg, out, pfcrx);
int mlx5_set_port_tc_group(struct mlx5_core_dev *mdev, u8 *tc_group)
{
u32 in[MLX5_ST_SZ_DW(qetc_reg)] = {0}; int i;
for (i = 0; i <= mlx5_max_tc(mdev); i++) {
MLX5_SET(qetc_reg, in, tc_configuration[i].g, 1);
MLX5_SET(qetc_reg, in, tc_configuration[i].group, tc_group[i]);
}
return mlx5_set_port_qetcr_reg(mdev, in, sizeof(in));
}
int mlx5_query_port_tc_group(struct mlx5_core_dev *mdev,
u8 tc, u8 *tc_group)
{
u32 out[MLX5_ST_SZ_DW(qetc_reg)]; void *ets_tcn_conf; int err;
err = mlx5_query_port_qetcr_reg(mdev, out, sizeof(out)); if (err) return err;
int mlx5_set_port_tc_bw_alloc(struct mlx5_core_dev *mdev, u8 *tc_bw)
{
u32 in[MLX5_ST_SZ_DW(qetc_reg)] = {0}; int i;
for (i = 0; i <= mlx5_max_tc(mdev); i++) {
MLX5_SET(qetc_reg, in, tc_configuration[i].b, 1);
MLX5_SET(qetc_reg, in, tc_configuration[i].bw_allocation, tc_bw[i]);
}
return mlx5_set_port_qetcr_reg(mdev, in, sizeof(in));
}
int mlx5_query_port_tc_bw_alloc(struct mlx5_core_dev *mdev,
u8 tc, u8 *bw_pct)
{
u32 out[MLX5_ST_SZ_DW(qetc_reg)]; void *ets_tcn_conf; int err;
err = mlx5_query_port_qetcr_reg(mdev, out, sizeof(out)); if (err) return err;
MLX5_SET(set_wol_rol_in, in, opcode, MLX5_CMD_OP_SET_WOL_ROL);
MLX5_SET(set_wol_rol_in, in, wol_mode_valid, 1);
MLX5_SET(set_wol_rol_in, in, wol_mode, wol_mode); return mlx5_cmd_exec_in(mdev, set_wol_rol, in);
}
int mlx5_query_port_wol(struct mlx5_core_dev *mdev, u8 *wol_mode)
{
u32 out[MLX5_ST_SZ_DW(query_wol_rol_out)] = {};
u32 in[MLX5_ST_SZ_DW(query_wol_rol_in)] = {}; int err;
MLX5_SET(query_wol_rol_in, in, opcode, MLX5_CMD_OP_QUERY_WOL_ROL);
err = mlx5_cmd_exec_inout(mdev, query_wol_rol, in, out); if (!err)
*wol_mode = MLX5_GET(query_wol_rol_out, out, wol_mode);
return err;
}
int mlx5_query_ports_check(struct mlx5_core_dev *mdev, u32 *out, int outlen)
{
u32 in[MLX5_ST_SZ_DW(pcmr_reg)] = {0};
MLX5_SET(pcmr_reg, in, local_port, 1); return mlx5_core_access_reg(mdev, in, sizeof(in), out,
outlen, MLX5_REG_PCMR, 0, 0);
}
int mlx5_set_ports_check(struct mlx5_core_dev *mdev, u32 *in, int inlen)
{
u32 out[MLX5_ST_SZ_DW(pcmr_reg)];
return mlx5_core_access_reg(mdev, in, inlen, out, sizeof(out), MLX5_REG_PCMR, 0, 1);
}
int mlx5_set_port_fcs(struct mlx5_core_dev *mdev, u8 enable)
{
u32 in[MLX5_ST_SZ_DW(pcmr_reg)] = {0}; int err;
err = mlx5_query_ports_check(mdev, in, sizeof(in)); if (err) return err;
MLX5_SET(pcmr_reg, in, local_port, 1);
MLX5_SET(pcmr_reg, in, fcs_chk, enable); return mlx5_set_ports_check(mdev, in, sizeof(in));
}
void mlx5_query_port_fcs(struct mlx5_core_dev *mdev, bool *supported, bool *enabled)
{
u32 out[MLX5_ST_SZ_DW(pcmr_reg)]; /* Default values for FW which do not support MLX5_REG_PCMR */
*supported = false;
*enabled = true;
if (!MLX5_CAP_GEN(mdev, ports_check)) return;
if (mlx5_query_ports_check(mdev, out, sizeof(out))) return;
int mlx5_set_dscp2prio(struct mlx5_core_dev *mdev, u8 dscp, u8 prio)
{ int sz = MLX5_ST_SZ_BYTES(qpdpm_reg); void *qpdpm_dscp; void *out; void *in; int err;
in = kzalloc(sz, GFP_KERNEL);
out = kzalloc(sz, GFP_KERNEL); if (!in || !out) {
err = -ENOMEM; goto out;
}
MLX5_SET(qpdpm_reg, in, local_port, 1);
err = mlx5_core_access_reg(mdev, in, sz, out, sz, MLX5_REG_QPDPM, 0, 0); if (err) goto out;
memcpy(in, out, sz);
MLX5_SET(qpdpm_reg, in, local_port, 1);
/* Update the corresponding dscp entry */
qpdpm_dscp = MLX5_ADDR_OF(qpdpm_reg, in, dscp[dscp]);
MLX5_SET16(qpdpm_dscp_reg, qpdpm_dscp, prio, prio);
MLX5_SET16(qpdpm_dscp_reg, qpdpm_dscp, e, 1);
err = mlx5_core_access_reg(mdev, in, sz, out, sz, MLX5_REG_QPDPM, 0, 1);
out:
kfree(in);
kfree(out); return err;
}
/* dscp2prio[i]: priority that dscp i mapped to */ #define MLX5E_SUPPORTED_DSCP 64 int mlx5_query_dscp2prio(struct mlx5_core_dev *mdev, u8 *dscp2prio)
{ int sz = MLX5_ST_SZ_BYTES(qpdpm_reg); void *qpdpm_dscp; void *out; void *in; int err; int i;
in = kzalloc(sz, GFP_KERNEL);
out = kzalloc(sz, GFP_KERNEL); if (!in || !out) {
err = -ENOMEM; goto out;
}
MLX5_SET(qpdpm_reg, in, local_port, 1);
err = mlx5_core_access_reg(mdev, in, sz, out, sz, MLX5_REG_QPDPM, 0, 0); if (err) goto out;
for (i = 0; i < (MLX5E_SUPPORTED_DSCP); i++) {
qpdpm_dscp = MLX5_ADDR_OF(qpdpm_reg, out, dscp[i]);
dscp2prio[i] = MLX5_GET16(qpdpm_dscp_reg, qpdpm_dscp, prio);
}
mlx5e_port_get_link_mode_info_arr(mdev, &table, &max_size, false); for (i = 0; i < max_size; ++i) if (eproto.cap & MLX5E_PROT_MASK(i))
max_speed = max(max_speed, table[i].speed);
*speed = max_speed; return 0;
}
int mlx5_query_mpir_reg(struct mlx5_core_dev *dev, u32 *mpir)
{
u32 in[MLX5_ST_SZ_DW(mpir_reg)] = {}; int sz = MLX5_ST_SZ_BYTES(mpir_reg);
MLX5_SET(mpir_reg, in, local_port, 1);
return mlx5_core_access_reg(dev, in, sz, mpir, sz, MLX5_REG_MPIR, 0, 0);
}
Messung V0.5
¤ Dauer der Verarbeitung: 0.5 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.