mlx5_port.c revision 347821
1/*- 2 * Copyright (c) 2013-2018, 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: stable/11/sys/dev/mlx5/mlx5_core/mlx5_port.c 347821 2019-05-16 17:30:20Z hselasky $ 26 */ 27 28#include <linux/module.h> 29#include <dev/mlx5/port.h> 30#include "mlx5_core.h" 31 32int mlx5_core_access_reg(struct mlx5_core_dev *dev, void *data_in, 33 int size_in, void *data_out, int size_out, 34 u16 reg_num, int arg, int write) 35{ 36 int outlen = MLX5_ST_SZ_BYTES(access_register_out) + size_out; 37 int inlen = MLX5_ST_SZ_BYTES(access_register_in) + size_in; 38 int err = -ENOMEM; 39 u32 *out = NULL; 40 u32 *in = NULL; 41 void *data; 42 43 in = mlx5_vzalloc(inlen); 44 out = mlx5_vzalloc(outlen); 45 if (!in || !out) 46 goto out; 47 48 data = MLX5_ADDR_OF(access_register_in, in, register_data); 49 memcpy(data, data_in, size_in); 50 51 MLX5_SET(access_register_in, in, opcode, MLX5_CMD_OP_ACCESS_REG); 52 MLX5_SET(access_register_in, in, op_mod, !write); 53 MLX5_SET(access_register_in, in, argument, arg); 54 MLX5_SET(access_register_in, in, register_id, reg_num); 55 56 err = mlx5_cmd_exec(dev, in, inlen, out, outlen); 57 if (err) 58 goto out; 59 data = MLX5_ADDR_OF(access_register_out, out, register_data); 60 memcpy(data_out, data, size_out); 61 62out: 63 kvfree(out); 64 kvfree(in); 65 return err; 66} 67EXPORT_SYMBOL_GPL(mlx5_core_access_reg); 68 69int mlx5_query_qcam_reg(struct mlx5_core_dev *mdev, u32 *qcam, 70 u8 feature_group, u8 access_reg_group) 71{ 72 u32 in[MLX5_ST_SZ_DW(qcam_reg)] = {}; 73 int sz = MLX5_ST_SZ_BYTES(qcam_reg); 74 75 MLX5_SET(qcam_reg, in, feature_group, feature_group); 76 MLX5_SET(qcam_reg, in, access_reg_group, access_reg_group); 77 78 return mlx5_core_access_reg(mdev, in, sz, qcam, sz, MLX5_REG_QCAM, 0, 0); 79} 80EXPORT_SYMBOL_GPL(mlx5_query_qcam_reg); 81 82int mlx5_query_pcam_reg(struct mlx5_core_dev *dev, u32 *pcam, u8 feature_group, 83 u8 access_reg_group) 84{ 85 u32 in[MLX5_ST_SZ_DW(pcam_reg)] = {}; 86 int sz = MLX5_ST_SZ_BYTES(pcam_reg); 87 88 MLX5_SET(pcam_reg, in, feature_group, feature_group); 89 MLX5_SET(pcam_reg, in, access_reg_group, access_reg_group); 90 91 return mlx5_core_access_reg(dev, in, sz, pcam, sz, MLX5_REG_PCAM, 0, 0); 92} 93 94int mlx5_query_mcam_reg(struct mlx5_core_dev *dev, u32 *mcam, u8 feature_group, 95 u8 access_reg_group) 96{ 97 u32 in[MLX5_ST_SZ_DW(mcam_reg)] = {}; 98 int sz = MLX5_ST_SZ_BYTES(mcam_reg); 99 100 MLX5_SET(mcam_reg, in, feature_group, feature_group); 101 MLX5_SET(mcam_reg, in, access_reg_group, access_reg_group); 102 103 return mlx5_core_access_reg(dev, in, sz, mcam, sz, MLX5_REG_MCAM, 0, 0); 104} 105 106struct mlx5_reg_pcap { 107 u8 rsvd0; 108 u8 port_num; 109 u8 rsvd1[2]; 110 __be32 caps_127_96; 111 __be32 caps_95_64; 112 __be32 caps_63_32; 113 __be32 caps_31_0; 114}; 115 116/* This function should be used after setting a port register only */ 117void mlx5_toggle_port_link(struct mlx5_core_dev *dev) 118{ 119 enum mlx5_port_status ps; 120 121 mlx5_query_port_admin_status(dev, &ps); 122 mlx5_set_port_status(dev, MLX5_PORT_DOWN); 123 if (ps == MLX5_PORT_UP) 124 mlx5_set_port_status(dev, MLX5_PORT_UP); 125} 126EXPORT_SYMBOL_GPL(mlx5_toggle_port_link); 127 128int mlx5_set_port_caps(struct mlx5_core_dev *dev, u8 port_num, u32 caps) 129{ 130 struct mlx5_reg_pcap in; 131 struct mlx5_reg_pcap out; 132 int err; 133 134 memset(&in, 0, sizeof(in)); 135 in.caps_127_96 = cpu_to_be32(caps); 136 in.port_num = port_num; 137 138 err = mlx5_core_access_reg(dev, &in, sizeof(in), &out, 139 sizeof(out), MLX5_REG_PCAP, 0, 1); 140 141 return err; 142} 143EXPORT_SYMBOL_GPL(mlx5_set_port_caps); 144 145int mlx5_query_port_ptys(struct mlx5_core_dev *dev, u32 *ptys, 146 int ptys_size, int proto_mask, u8 local_port) 147{ 148 u32 in[MLX5_ST_SZ_DW(ptys_reg)]; 149 int err; 150 151 memset(in, 0, sizeof(in)); 152 MLX5_SET(ptys_reg, in, local_port, local_port); 153 MLX5_SET(ptys_reg, in, proto_mask, proto_mask); 154 155 err = mlx5_core_access_reg(dev, in, sizeof(in), ptys, 156 ptys_size, MLX5_REG_PTYS, 0, 0); 157 158 return err; 159} 160EXPORT_SYMBOL_GPL(mlx5_query_port_ptys); 161 162int mlx5_query_port_proto_cap(struct mlx5_core_dev *dev, 163 u32 *proto_cap, int proto_mask) 164{ 165 u32 out[MLX5_ST_SZ_DW(ptys_reg)]; 166 int err; 167 168 err = mlx5_query_port_ptys(dev, out, sizeof(out), proto_mask, 1); 169 if (err) 170 return err; 171 172 if (proto_mask == MLX5_PTYS_EN) 173 *proto_cap = MLX5_GET(ptys_reg, out, eth_proto_capability); 174 else 175 *proto_cap = MLX5_GET(ptys_reg, out, ib_proto_capability); 176 177 return 0; 178} 179EXPORT_SYMBOL_GPL(mlx5_query_port_proto_cap); 180 181int mlx5_query_port_autoneg(struct mlx5_core_dev *dev, int proto_mask, 182 u8 *an_disable_cap, u8 *an_disable_status) 183{ 184 u32 out[MLX5_ST_SZ_DW(ptys_reg)]; 185 int err; 186 187 err = mlx5_query_port_ptys(dev, out, sizeof(out), proto_mask, 1); 188 if (err) 189 return err; 190 191 *an_disable_status = MLX5_GET(ptys_reg, out, an_disable_admin); 192 *an_disable_cap = MLX5_GET(ptys_reg, out, an_disable_cap); 193 194 return 0; 195} 196EXPORT_SYMBOL_GPL(mlx5_query_port_autoneg); 197 198int mlx5_set_port_autoneg(struct mlx5_core_dev *dev, bool disable, 199 u32 eth_proto_admin, int proto_mask) 200{ 201 u32 in[MLX5_ST_SZ_DW(ptys_reg)] = {0}; 202 u32 out[MLX5_ST_SZ_DW(ptys_reg)] = {0}; 203 u8 an_disable_cap; 204 u8 an_disable_status; 205 int err; 206 207 err = mlx5_query_port_autoneg(dev, proto_mask, &an_disable_cap, 208 &an_disable_status); 209 if (err) 210 return err; 211 if (!an_disable_cap) 212 return -EPERM; 213 214 MLX5_SET(ptys_reg, in, local_port, 1); 215 MLX5_SET(ptys_reg, in, an_disable_admin, disable); 216 MLX5_SET(ptys_reg, in, proto_mask, proto_mask); 217 if (proto_mask == MLX5_PTYS_EN) 218 MLX5_SET(ptys_reg, in, eth_proto_admin, eth_proto_admin); 219 220 err = mlx5_core_access_reg(dev, in, sizeof(in), out, 221 sizeof(out), MLX5_REG_PTYS, 0, 1); 222 return err; 223} 224EXPORT_SYMBOL_GPL(mlx5_set_port_autoneg); 225 226int mlx5_query_port_proto_admin(struct mlx5_core_dev *dev, 227 u32 *proto_admin, int proto_mask) 228{ 229 u32 out[MLX5_ST_SZ_DW(ptys_reg)]; 230 int err; 231 232 err = mlx5_query_port_ptys(dev, out, sizeof(out), proto_mask, 1); 233 if (err) 234 return err; 235 236 if (proto_mask == MLX5_PTYS_EN) 237 *proto_admin = MLX5_GET(ptys_reg, out, eth_proto_admin); 238 else 239 *proto_admin = MLX5_GET(ptys_reg, out, ib_proto_admin); 240 241 return 0; 242} 243EXPORT_SYMBOL_GPL(mlx5_query_port_proto_admin); 244 245int mlx5_query_port_eth_proto_oper(struct mlx5_core_dev *dev, 246 u32 *proto_oper, u8 local_port) 247{ 248 u32 out[MLX5_ST_SZ_DW(ptys_reg)]; 249 int err; 250 251 err = mlx5_query_port_ptys(dev, out, sizeof(out), MLX5_PTYS_EN, 252 local_port); 253 if (err) 254 return err; 255 256 *proto_oper = MLX5_GET(ptys_reg, out, eth_proto_oper); 257 258 return 0; 259} 260EXPORT_SYMBOL(mlx5_query_port_eth_proto_oper); 261 262int mlx5_set_port_proto(struct mlx5_core_dev *dev, u32 proto_admin, 263 int proto_mask) 264{ 265 u32 in[MLX5_ST_SZ_DW(ptys_reg)] = {0}; 266 u32 out[MLX5_ST_SZ_DW(ptys_reg)] = {0}; 267 int err; 268 269 MLX5_SET(ptys_reg, in, local_port, 1); 270 MLX5_SET(ptys_reg, in, proto_mask, proto_mask); 271 if (proto_mask == MLX5_PTYS_EN) 272 MLX5_SET(ptys_reg, in, eth_proto_admin, proto_admin); 273 else 274 MLX5_SET(ptys_reg, in, ib_proto_admin, proto_admin); 275 276 err = mlx5_core_access_reg(dev, in, sizeof(in), out, 277 sizeof(out), MLX5_REG_PTYS, 0, 1); 278 return err; 279} 280EXPORT_SYMBOL_GPL(mlx5_set_port_proto); 281 282int mlx5_set_port_status(struct mlx5_core_dev *dev, 283 enum mlx5_port_status status) 284{ 285 u32 in[MLX5_ST_SZ_DW(paos_reg)] = {0}; 286 u32 out[MLX5_ST_SZ_DW(paos_reg)] = {0}; 287 int err; 288 289 MLX5_SET(paos_reg, in, local_port, 1); 290 291 MLX5_SET(paos_reg, in, admin_status, status); 292 MLX5_SET(paos_reg, in, ase, 1); 293 294 err = mlx5_core_access_reg(dev, in, sizeof(in), out, 295 sizeof(out), MLX5_REG_PAOS, 0, 1); 296 return err; 297} 298 299int mlx5_query_port_status(struct mlx5_core_dev *dev, u8 *status) 300{ 301 u32 in[MLX5_ST_SZ_DW(paos_reg)] = {0}; 302 u32 out[MLX5_ST_SZ_DW(paos_reg)] = {0}; 303 int err; 304 305 MLX5_SET(paos_reg, in, local_port, 1); 306 307 err = mlx5_core_access_reg(dev, in, sizeof(in), out, 308 sizeof(out), MLX5_REG_PAOS, 0, 0); 309 if (err) 310 return err; 311 312 *status = MLX5_GET(paos_reg, out, oper_status); 313 return err; 314} 315 316int mlx5_query_port_admin_status(struct mlx5_core_dev *dev, 317 enum mlx5_port_status *status) 318{ 319 u32 in[MLX5_ST_SZ_DW(paos_reg)] = {0}; 320 u32 out[MLX5_ST_SZ_DW(paos_reg)]; 321 int err; 322 323 MLX5_SET(paos_reg, in, local_port, 1); 324 err = mlx5_core_access_reg(dev, in, sizeof(in), out, 325 sizeof(out), MLX5_REG_PAOS, 0, 0); 326 if (err) 327 return err; 328 *status = MLX5_GET(paos_reg, out, admin_status); 329 return 0; 330} 331EXPORT_SYMBOL_GPL(mlx5_query_port_admin_status); 332 333static int mlx5_query_port_mtu(struct mlx5_core_dev *dev, 334 int *admin_mtu, int *max_mtu, int *oper_mtu) 335{ 336 u32 in[MLX5_ST_SZ_DW(pmtu_reg)] = {0}; 337 u32 out[MLX5_ST_SZ_DW(pmtu_reg)] = {0}; 338 int err; 339 340 MLX5_SET(pmtu_reg, in, local_port, 1); 341 342 err = mlx5_core_access_reg(dev, in, sizeof(in), out, 343 sizeof(out), MLX5_REG_PMTU, 0, 0); 344 if (err) 345 return err; 346 347 if (max_mtu) 348 *max_mtu = MLX5_GET(pmtu_reg, out, max_mtu); 349 if (oper_mtu) 350 *oper_mtu = MLX5_GET(pmtu_reg, out, oper_mtu); 351 if (admin_mtu) 352 *admin_mtu = MLX5_GET(pmtu_reg, out, admin_mtu); 353 354 return err; 355} 356 357int mlx5_set_port_mtu(struct mlx5_core_dev *dev, int mtu) 358{ 359 u32 in[MLX5_ST_SZ_DW(pmtu_reg)] = {0}; 360 u32 out[MLX5_ST_SZ_DW(pmtu_reg)] = {0}; 361 362 MLX5_SET(pmtu_reg, in, admin_mtu, mtu); 363 MLX5_SET(pmtu_reg, in, local_port, 1); 364 365 return mlx5_core_access_reg(dev, in, sizeof(in), out, 366 sizeof(out), MLX5_REG_PMTU, 0, 1); 367} 368EXPORT_SYMBOL_GPL(mlx5_set_port_mtu); 369 370int mlx5_query_port_max_mtu(struct mlx5_core_dev *dev, int *max_mtu) 371{ 372 return mlx5_query_port_mtu(dev, NULL, max_mtu, NULL); 373} 374EXPORT_SYMBOL_GPL(mlx5_query_port_max_mtu); 375 376int mlx5_set_port_pause_and_pfc(struct mlx5_core_dev *dev, u32 port, 377 u8 rx_pause, u8 tx_pause, 378 u8 pfc_en_rx, u8 pfc_en_tx) 379{ 380 u32 in[MLX5_ST_SZ_DW(pfcc_reg)] = {0}; 381 u32 out[MLX5_ST_SZ_DW(pfcc_reg)] = {0}; 382 383 if (pfc_en_rx || pfc_en_tx) { 384 /* PFC and global pauseframes are incompatible features */ 385 if (tx_pause || rx_pause) 386 return -EINVAL; 387 } 388 389 MLX5_SET(pfcc_reg, in, local_port, port); 390 MLX5_SET(pfcc_reg, in, pptx, tx_pause); 391 MLX5_SET(pfcc_reg, in, pprx, rx_pause); 392 MLX5_SET(pfcc_reg, in, pfctx, pfc_en_tx); 393 MLX5_SET(pfcc_reg, in, pfcrx, pfc_en_rx); 394 MLX5_SET(pfcc_reg, in, prio_mask_tx, pfc_en_tx); 395 MLX5_SET(pfcc_reg, in, prio_mask_rx, pfc_en_rx); 396 397 return mlx5_core_access_reg(dev, in, sizeof(in), out, 398 sizeof(out), MLX5_REG_PFCC, 0, 1); 399} 400 401int mlx5_query_port_pause(struct mlx5_core_dev *dev, u32 port, 402 u32 *rx_pause, u32 *tx_pause) 403{ 404 u32 in[MLX5_ST_SZ_DW(pfcc_reg)] = {0}; 405 u32 out[MLX5_ST_SZ_DW(pfcc_reg)] = {0}; 406 int err; 407 408 MLX5_SET(pfcc_reg, in, local_port, port); 409 410 err = mlx5_core_access_reg(dev, in, sizeof(in), out, 411 sizeof(out), MLX5_REG_PFCC, 0, 0); 412 if (err) 413 return err; 414 415 *rx_pause = MLX5_GET(pfcc_reg, out, pprx); 416 *tx_pause = MLX5_GET(pfcc_reg, out, pptx); 417 418 return 0; 419} 420 421int mlx5_query_port_pfc(struct mlx5_core_dev *dev, u8 *pfc_en_tx, u8 *pfc_en_rx) 422{ 423 u32 in[MLX5_ST_SZ_DW(pfcc_reg)] = {}; 424 u32 out[MLX5_ST_SZ_DW(pfcc_reg)]; 425 int err; 426 427 MLX5_SET(pfcc_reg, in, local_port, 1); 428 err = mlx5_core_access_reg(dev, in, sizeof(in), out, 429 sizeof(out), MLX5_REG_PFCC, 0, 0); 430 if (err) 431 return err; 432 433 if (pfc_en_tx != NULL) 434 *pfc_en_tx = MLX5_GET(pfcc_reg, out, pfctx); 435 if (pfc_en_rx != NULL) 436 *pfc_en_rx = MLX5_GET(pfcc_reg, out, pfcrx); 437 return 0; 438} 439EXPORT_SYMBOL_GPL(mlx5_query_port_pfc); 440 441int mlx5_query_port_oper_mtu(struct mlx5_core_dev *dev, int *oper_mtu) 442{ 443 return mlx5_query_port_mtu(dev, NULL, NULL, oper_mtu); 444} 445EXPORT_SYMBOL_GPL(mlx5_query_port_oper_mtu); 446 447u8 mlx5_is_wol_supported(struct mlx5_core_dev *dev) 448{ 449 u8 wol_supported = 0; 450 451 if (MLX5_CAP_GEN(dev, wol_s)) 452 wol_supported |= MLX5_WOL_SECURED_MAGIC; 453 if (MLX5_CAP_GEN(dev, wol_g)) 454 wol_supported |= MLX5_WOL_MAGIC; 455 if (MLX5_CAP_GEN(dev, wol_a)) 456 wol_supported |= MLX5_WOL_ARP; 457 if (MLX5_CAP_GEN(dev, wol_b)) 458 wol_supported |= MLX5_WOL_BROADCAST; 459 if (MLX5_CAP_GEN(dev, wol_m)) 460 wol_supported |= MLX5_WOL_MULTICAST; 461 if (MLX5_CAP_GEN(dev, wol_u)) 462 wol_supported |= MLX5_WOL_UNICAST; 463 if (MLX5_CAP_GEN(dev, wol_p)) 464 wol_supported |= MLX5_WOL_PHY_ACTIVITY; 465 466 return wol_supported; 467} 468EXPORT_SYMBOL_GPL(mlx5_is_wol_supported); 469 470int mlx5_set_wol(struct mlx5_core_dev *dev, u8 wol_mode) 471{ 472 u32 in[MLX5_ST_SZ_DW(set_wol_rol_in)] = {0}; 473 u32 out[MLX5_ST_SZ_DW(set_wol_rol_out)] = {0}; 474 475 MLX5_SET(set_wol_rol_in, in, opcode, MLX5_CMD_OP_SET_WOL_ROL); 476 MLX5_SET(set_wol_rol_in, in, wol_mode_valid, 1); 477 MLX5_SET(set_wol_rol_in, in, wol_mode, wol_mode); 478 479 return mlx5_cmd_exec(dev, in, sizeof(in), out, sizeof(out)); 480} 481EXPORT_SYMBOL_GPL(mlx5_set_wol); 482 483int mlx5_query_dropless_mode(struct mlx5_core_dev *dev, u16 *timeout) 484{ 485 u32 in[MLX5_ST_SZ_DW(query_delay_drop_params_in)] = {0}; 486 u32 out[MLX5_ST_SZ_DW(query_delay_drop_params_out)] = {0}; 487 int err = 0; 488 489 MLX5_SET(query_delay_drop_params_in, in, opcode, 490 MLX5_CMD_OP_QUERY_DELAY_DROP_PARAMS); 491 492 err = mlx5_cmd_exec(dev, in, sizeof(in), out, sizeof(out)); 493 if (err) 494 return err; 495 496 *timeout = MLX5_GET(query_delay_drop_params_out, out, 497 delay_drop_timeout); 498 499 return 0; 500} 501EXPORT_SYMBOL_GPL(mlx5_query_dropless_mode); 502 503int mlx5_set_dropless_mode(struct mlx5_core_dev *dev, u16 timeout) 504{ 505 u32 in[MLX5_ST_SZ_DW(set_delay_drop_params_in)] = {0}; 506 u32 out[MLX5_ST_SZ_DW(set_delay_drop_params_out)] = {0}; 507 508 MLX5_SET(set_delay_drop_params_in, in, opcode, 509 MLX5_CMD_OP_SET_DELAY_DROP_PARAMS); 510 MLX5_SET(set_delay_drop_params_in, in, delay_drop_timeout, timeout); 511 512 return mlx5_cmd_exec(dev, in, sizeof(in), out, sizeof(out)); 513} 514EXPORT_SYMBOL_GPL(mlx5_set_dropless_mode); 515 516int mlx5_core_access_pvlc(struct mlx5_core_dev *dev, 517 struct mlx5_pvlc_reg *pvlc, int write) 518{ 519 int sz = MLX5_ST_SZ_BYTES(pvlc_reg); 520 u8 in[MLX5_ST_SZ_BYTES(pvlc_reg)] = {0}; 521 u8 out[MLX5_ST_SZ_BYTES(pvlc_reg)] = {0}; 522 int err; 523 524 MLX5_SET(pvlc_reg, in, local_port, pvlc->local_port); 525 if (write) 526 MLX5_SET(pvlc_reg, in, vl_admin, pvlc->vl_admin); 527 528 err = mlx5_core_access_reg(dev, in, sz, out, sz, MLX5_REG_PVLC, 0, 529 !!write); 530 if (err) 531 return err; 532 533 if (!write) { 534 pvlc->local_port = MLX5_GET(pvlc_reg, out, local_port); 535 pvlc->vl_hw_cap = MLX5_GET(pvlc_reg, out, vl_hw_cap); 536 pvlc->vl_admin = MLX5_GET(pvlc_reg, out, vl_admin); 537 pvlc->vl_operational = MLX5_GET(pvlc_reg, out, vl_operational); 538 } 539 540 return 0; 541} 542EXPORT_SYMBOL_GPL(mlx5_core_access_pvlc); 543 544int mlx5_core_access_ptys(struct mlx5_core_dev *dev, 545 struct mlx5_ptys_reg *ptys, int write) 546{ 547 int sz = MLX5_ST_SZ_BYTES(ptys_reg); 548 void *out = NULL; 549 void *in = NULL; 550 int err; 551 552 in = mlx5_vzalloc(sz); 553 if (!in) 554 return -ENOMEM; 555 556 out = mlx5_vzalloc(sz); 557 if (!out) { 558 kfree(in); 559 return -ENOMEM; 560 } 561 562 MLX5_SET(ptys_reg, in, local_port, ptys->local_port); 563 MLX5_SET(ptys_reg, in, proto_mask, ptys->proto_mask); 564 if (write) { 565 MLX5_SET(ptys_reg, in, eth_proto_capability, 566 ptys->eth_proto_cap); 567 MLX5_SET(ptys_reg, in, ib_link_width_capability, 568 ptys->ib_link_width_cap); 569 MLX5_SET(ptys_reg, in, ib_proto_capability, 570 ptys->ib_proto_cap); 571 MLX5_SET(ptys_reg, in, eth_proto_admin, ptys->eth_proto_admin); 572 MLX5_SET(ptys_reg, in, ib_link_width_admin, 573 ptys->ib_link_width_admin); 574 MLX5_SET(ptys_reg, in, ib_proto_admin, ptys->ib_proto_admin); 575 MLX5_SET(ptys_reg, in, eth_proto_oper, ptys->eth_proto_oper); 576 MLX5_SET(ptys_reg, in, ib_link_width_oper, 577 ptys->ib_link_width_oper); 578 MLX5_SET(ptys_reg, in, ib_proto_oper, ptys->ib_proto_oper); 579 MLX5_SET(ptys_reg, in, eth_proto_lp_advertise, 580 ptys->eth_proto_lp_advertise); 581 } 582 583 err = mlx5_core_access_reg(dev, in, sz, out, sz, MLX5_REG_PTYS, 0, 584 !!write); 585 if (err) 586 goto out; 587 588 if (!write) { 589 ptys->local_port = MLX5_GET(ptys_reg, out, local_port); 590 ptys->proto_mask = MLX5_GET(ptys_reg, out, proto_mask); 591 ptys->eth_proto_cap = MLX5_GET(ptys_reg, out, 592 eth_proto_capability); 593 ptys->ib_link_width_cap = MLX5_GET(ptys_reg, out, 594 ib_link_width_capability); 595 ptys->ib_proto_cap = MLX5_GET(ptys_reg, out, 596 ib_proto_capability); 597 ptys->eth_proto_admin = MLX5_GET(ptys_reg, out, 598 eth_proto_admin); 599 ptys->ib_link_width_admin = MLX5_GET(ptys_reg, out, 600 ib_link_width_admin); 601 ptys->ib_proto_admin = MLX5_GET(ptys_reg, out, ib_proto_admin); 602 ptys->eth_proto_oper = MLX5_GET(ptys_reg, out, eth_proto_oper); 603 ptys->ib_link_width_oper = MLX5_GET(ptys_reg, out, 604 ib_link_width_oper); 605 ptys->ib_proto_oper = MLX5_GET(ptys_reg, out, ib_proto_oper); 606 ptys->eth_proto_lp_advertise = MLX5_GET(ptys_reg, out, 607 eth_proto_lp_advertise); 608 } 609 610out: 611 kvfree(in); 612 kvfree(out); 613 return err; 614} 615EXPORT_SYMBOL_GPL(mlx5_core_access_ptys); 616 617static int mtu_to_ib_mtu(int mtu) 618{ 619 switch (mtu) { 620 case 256: return 1; 621 case 512: return 2; 622 case 1024: return 3; 623 case 2048: return 4; 624 case 4096: return 5; 625 default: 626 printf("mlx5_core: WARN: ""invalid mtu\n"); 627 return -1; 628 } 629} 630 631int mlx5_core_access_pmtu(struct mlx5_core_dev *dev, 632 struct mlx5_pmtu_reg *pmtu, int write) 633{ 634 int sz = MLX5_ST_SZ_BYTES(pmtu_reg); 635 void *out = NULL; 636 void *in = NULL; 637 int err; 638 639 in = mlx5_vzalloc(sz); 640 if (!in) 641 return -ENOMEM; 642 643 out = mlx5_vzalloc(sz); 644 if (!out) { 645 kfree(in); 646 return -ENOMEM; 647 } 648 649 MLX5_SET(pmtu_reg, in, local_port, pmtu->local_port); 650 if (write) 651 MLX5_SET(pmtu_reg, in, admin_mtu, pmtu->admin_mtu); 652 653 err = mlx5_core_access_reg(dev, in, sz, out, sz, MLX5_REG_PMTU, 0, 654 !!write); 655 if (err) 656 goto out; 657 658 if (!write) { 659 pmtu->local_port = MLX5_GET(pmtu_reg, out, local_port); 660 pmtu->max_mtu = mtu_to_ib_mtu(MLX5_GET(pmtu_reg, out, 661 max_mtu)); 662 pmtu->admin_mtu = mtu_to_ib_mtu(MLX5_GET(pmtu_reg, out, 663 admin_mtu)); 664 pmtu->oper_mtu = mtu_to_ib_mtu(MLX5_GET(pmtu_reg, out, 665 oper_mtu)); 666 } 667 668out: 669 kvfree(in); 670 kvfree(out); 671 return err; 672} 673EXPORT_SYMBOL_GPL(mlx5_core_access_pmtu); 674 675int mlx5_query_module_num(struct mlx5_core_dev *dev, int *module_num) 676{ 677 u32 in[MLX5_ST_SZ_DW(pmlp_reg)] = {0}; 678 u32 out[MLX5_ST_SZ_DW(pmlp_reg)] = {0}; 679 int lane = 0; 680 int err; 681 682 MLX5_SET(pmlp_reg, in, local_port, 1); 683 684 err = mlx5_core_access_reg(dev, in, sizeof(in), out, 685 sizeof(out), MLX5_REG_PMLP, 0, 0); 686 if (err) 687 return err; 688 689 lane = MLX5_GET(pmlp_reg, out, lane0_module_mapping); 690 *module_num = lane & MLX5_EEPROM_IDENTIFIER_BYTE_MASK; 691 692 return 0; 693} 694EXPORT_SYMBOL_GPL(mlx5_query_module_num); 695 696int mlx5_query_eeprom(struct mlx5_core_dev *dev, 697 int i2c_addr, int page_num, int device_addr, 698 int size, int module_num, u32 *data, int *size_read) 699{ 700 u32 in[MLX5_ST_SZ_DW(mcia_reg)] = {0}; 701 u32 out[MLX5_ST_SZ_DW(mcia_reg)] = {0}; 702 u32 *ptr = (u32 *)MLX5_ADDR_OF(mcia_reg, out, dword_0); 703 int status; 704 int err; 705 706 size = min_t(int, size, MLX5_EEPROM_MAX_BYTES); 707 708 MLX5_SET(mcia_reg, in, l, 0); 709 MLX5_SET(mcia_reg, in, module, module_num); 710 MLX5_SET(mcia_reg, in, i2c_device_address, i2c_addr); 711 MLX5_SET(mcia_reg, in, page_number, page_num); 712 MLX5_SET(mcia_reg, in, device_address, device_addr); 713 MLX5_SET(mcia_reg, in, size, size); 714 715 err = mlx5_core_access_reg(dev, in, sizeof(in), out, 716 sizeof(out), MLX5_REG_MCIA, 0, 0); 717 if (err) 718 return err; 719 720 status = MLX5_GET(mcia_reg, out, status); 721 if (status) 722 return status; 723 724 memcpy(data, ptr, size); 725 *size_read = size; 726 return 0; 727} 728EXPORT_SYMBOL_GPL(mlx5_query_eeprom); 729 730int mlx5_vxlan_udp_port_add(struct mlx5_core_dev *dev, u16 port) 731{ 732 u32 in[MLX5_ST_SZ_DW(add_vxlan_udp_dport_in)] = {0}; 733 u32 out[MLX5_ST_SZ_DW(add_vxlan_udp_dport_out)] = {0}; 734 int err; 735 736 MLX5_SET(add_vxlan_udp_dport_in, in, opcode, 737 MLX5_CMD_OP_ADD_VXLAN_UDP_DPORT); 738 MLX5_SET(add_vxlan_udp_dport_in, in, vxlan_udp_port, port); 739 740 err = mlx5_cmd_exec(dev, in, sizeof(in), out, sizeof(out)); 741 if (err) { 742 mlx5_core_err(dev, "Failed %s, port %u, err - %d", 743 mlx5_command_str(MLX5_CMD_OP_ADD_VXLAN_UDP_DPORT), 744 port, err); 745 } 746 747 return err; 748} 749 750int mlx5_vxlan_udp_port_delete(struct mlx5_core_dev *dev, u16 port) 751{ 752 u32 in[MLX5_ST_SZ_DW(delete_vxlan_udp_dport_in)] = {0}; 753 u32 out[MLX5_ST_SZ_DW(delete_vxlan_udp_dport_out)] = {0}; 754 int err; 755 756 MLX5_SET(delete_vxlan_udp_dport_in, in, opcode, 757 MLX5_CMD_OP_DELETE_VXLAN_UDP_DPORT); 758 MLX5_SET(delete_vxlan_udp_dport_in, in, vxlan_udp_port, port); 759 760 err = mlx5_cmd_exec(dev, in, sizeof(in), out, sizeof(out)); 761 if (err) { 762 mlx5_core_err(dev, "Failed %s, port %u, err - %d", 763 mlx5_command_str(MLX5_CMD_OP_DELETE_VXLAN_UDP_DPORT), 764 port, err); 765 } 766 767 return err; 768} 769 770int mlx5_query_wol(struct mlx5_core_dev *dev, u8 *wol_mode) 771{ 772 u32 in[MLX5_ST_SZ_DW(query_wol_rol_in)] = {0}; 773 u32 out[MLX5_ST_SZ_DW(query_wol_rol_out)] = {0}; 774 int err; 775 776 MLX5_SET(query_wol_rol_in, in, opcode, MLX5_CMD_OP_QUERY_WOL_ROL); 777 778 err = mlx5_cmd_exec(dev, in, sizeof(in), out, sizeof(out)); 779 780 if (!err) 781 *wol_mode = MLX5_GET(query_wol_rol_out, out, wol_mode); 782 783 return err; 784} 785EXPORT_SYMBOL_GPL(mlx5_query_wol); 786 787int mlx5_query_port_cong_status(struct mlx5_core_dev *mdev, int protocol, 788 int priority, int *is_enable) 789{ 790 u32 in[MLX5_ST_SZ_DW(query_cong_status_in)] = {0}; 791 u32 out[MLX5_ST_SZ_DW(query_cong_status_out)] = {0}; 792 int err; 793 794 *is_enable = 0; 795 796 MLX5_SET(query_cong_status_in, in, opcode, 797 MLX5_CMD_OP_QUERY_CONG_STATUS); 798 MLX5_SET(query_cong_status_in, in, cong_protocol, protocol); 799 MLX5_SET(query_cong_status_in, in, priority, priority); 800 801 err = mlx5_cmd_exec(mdev, in, sizeof(in), out, sizeof(out)); 802 if (!err) 803 *is_enable = MLX5_GET(query_cong_status_out, out, enable); 804 return err; 805} 806 807int mlx5_modify_port_cong_status(struct mlx5_core_dev *mdev, int protocol, 808 int priority, int enable) 809{ 810 u32 in[MLX5_ST_SZ_DW(modify_cong_status_in)] = {0}; 811 u32 out[MLX5_ST_SZ_DW(modify_cong_status_out)] = {0}; 812 813 MLX5_SET(modify_cong_status_in, in, opcode, 814 MLX5_CMD_OP_MODIFY_CONG_STATUS); 815 MLX5_SET(modify_cong_status_in, in, cong_protocol, protocol); 816 MLX5_SET(modify_cong_status_in, in, priority, priority); 817 MLX5_SET(modify_cong_status_in, in, enable, enable); 818 819 return mlx5_cmd_exec(mdev, in, sizeof(in), out, sizeof(out)); 820} 821 822int mlx5_query_port_cong_params(struct mlx5_core_dev *mdev, int protocol, 823 void *out, int out_size) 824{ 825 u32 in[MLX5_ST_SZ_DW(query_cong_params_in)] = {0}; 826 827 MLX5_SET(query_cong_params_in, in, opcode, 828 MLX5_CMD_OP_QUERY_CONG_PARAMS); 829 MLX5_SET(query_cong_params_in, in, cong_protocol, protocol); 830 831 return mlx5_cmd_exec(mdev, in, sizeof(in), out, out_size); 832} 833 834static int mlx5_query_port_qetcr_reg(struct mlx5_core_dev *mdev, u32 *out, 835 int outlen) 836{ 837 u32 in[MLX5_ST_SZ_DW(qetc_reg)]; 838 839 if (!MLX5_CAP_GEN(mdev, ets)) 840 return -ENOTSUPP; 841 842 memset(in, 0, sizeof(in)); 843 return mlx5_core_access_reg(mdev, in, sizeof(in), out, outlen, 844 MLX5_REG_QETCR, 0, 0); 845} 846 847int mlx5_max_tc(struct mlx5_core_dev *mdev) 848{ 849 u8 num_tc = MLX5_CAP_GEN(mdev, max_tc) ? : 8; 850 851 return num_tc - 1; 852} 853EXPORT_SYMBOL_GPL(mlx5_max_tc); 854 855static int mlx5_set_port_qetcr_reg(struct mlx5_core_dev *mdev, u32 *in, 856 int inlen) 857{ 858 u32 out[MLX5_ST_SZ_DW(qetc_reg)]; 859 860 if (!MLX5_CAP_GEN(mdev, ets)) 861 return -ENOTSUPP; 862 863 return mlx5_core_access_reg(mdev, in, inlen, out, sizeof(out), 864 MLX5_REG_QETCR, 0, 1); 865} 866 867int mlx5_query_port_tc_rate_limit(struct mlx5_core_dev *mdev, 868 u8 *max_bw_value, 869 u8 *max_bw_units) 870{ 871 u32 out[MLX5_ST_SZ_DW(qetc_reg)]; 872 void *ets_tcn_conf; 873 int err; 874 int i; 875 876 err = mlx5_query_port_qetcr_reg(mdev, out, sizeof(out)); 877 if (err) 878 return err; 879 880 for (i = 0; i <= mlx5_max_tc(mdev); i++) { 881 ets_tcn_conf = MLX5_ADDR_OF(qetc_reg, out, tc_configuration[i]); 882 883 max_bw_value[i] = MLX5_GET(ets_tcn_config_reg, ets_tcn_conf, 884 max_bw_value); 885 max_bw_units[i] = MLX5_GET(ets_tcn_config_reg, ets_tcn_conf, 886 max_bw_units); 887 } 888 889 return 0; 890} 891EXPORT_SYMBOL_GPL(mlx5_query_port_tc_rate_limit); 892 893int mlx5_modify_port_tc_rate_limit(struct mlx5_core_dev *mdev, 894 const u8 *max_bw_value, 895 const u8 *max_bw_units) 896{ 897 u32 in[MLX5_ST_SZ_DW(qetc_reg)] = {}; 898 void *ets_tcn_conf; 899 int i; 900 901 MLX5_SET(qetc_reg, in, port_number, 1); 902 903 for (i = 0; i <= mlx5_max_tc(mdev); i++) { 904 ets_tcn_conf = MLX5_ADDR_OF(qetc_reg, in, tc_configuration[i]); 905 906 MLX5_SET(ets_tcn_config_reg, ets_tcn_conf, r, 1); 907 MLX5_SET(ets_tcn_config_reg, ets_tcn_conf, max_bw_units, 908 max_bw_units[i]); 909 MLX5_SET(ets_tcn_config_reg, ets_tcn_conf, max_bw_value, 910 max_bw_value[i]); 911 } 912 913 return mlx5_set_port_qetcr_reg(mdev, in, sizeof(in)); 914} 915EXPORT_SYMBOL_GPL(mlx5_modify_port_tc_rate_limit); 916 917int mlx5_query_port_prio_tc(struct mlx5_core_dev *mdev, 918 u8 prio, u8 *tc) 919{ 920 u32 in[MLX5_ST_SZ_DW(qtct_reg)]; 921 u32 out[MLX5_ST_SZ_DW(qtct_reg)]; 922 int err; 923 924 memset(in, 0, sizeof(in)); 925 memset(out, 0, sizeof(out)); 926 927 MLX5_SET(qtct_reg, in, port_number, 1); 928 MLX5_SET(qtct_reg, in, prio, prio); 929 930 err = mlx5_core_access_reg(mdev, in, sizeof(in), out, 931 sizeof(out), MLX5_REG_QTCT, 0, 0); 932 if (!err) 933 *tc = MLX5_GET(qtct_reg, out, tclass); 934 935 return err; 936} 937EXPORT_SYMBOL_GPL(mlx5_query_port_prio_tc); 938 939int mlx5_set_port_prio_tc(struct mlx5_core_dev *mdev, int prio_index, 940 const u8 prio_tc) 941{ 942 u32 in[MLX5_ST_SZ_DW(qtct_reg)] = {}; 943 u32 out[MLX5_ST_SZ_DW(qtct_reg)]; 944 int err; 945 946 if (prio_tc > mlx5_max_tc(mdev)) 947 return -EINVAL; 948 949 MLX5_SET(qtct_reg, in, prio, prio_index); 950 MLX5_SET(qtct_reg, in, tclass, prio_tc); 951 952 err = mlx5_core_access_reg(mdev, in, sizeof(in), out, 953 sizeof(out), MLX5_REG_QTCT, 0, 1); 954 955 return (err); 956} 957EXPORT_SYMBOL_GPL(mlx5_set_port_prio_tc); 958 959int mlx5_set_port_tc_group(struct mlx5_core_dev *mdev, const u8 *tc_group) 960{ 961 u32 in[MLX5_ST_SZ_DW(qetc_reg)] = {}; 962 int i; 963 964 for (i = 0; i <= mlx5_max_tc(mdev); i++) { 965 MLX5_SET(qetc_reg, in, tc_configuration[i].g, 1); 966 MLX5_SET(qetc_reg, in, tc_configuration[i].group, tc_group[i]); 967 } 968 969 return mlx5_set_port_qetcr_reg(mdev, in, sizeof(in)); 970} 971EXPORT_SYMBOL_GPL(mlx5_set_port_tc_group); 972 973int mlx5_query_port_tc_group(struct mlx5_core_dev *mdev, 974 u8 tc, u8 *tc_group) 975{ 976 u32 out[MLX5_ST_SZ_DW(qetc_reg)]; 977 void *ets_tcn_conf; 978 int err; 979 980 err = mlx5_query_port_qetcr_reg(mdev, out, sizeof(out)); 981 if (err) 982 return err; 983 984 ets_tcn_conf = MLX5_ADDR_OF(qetc_reg, out, 985 tc_configuration[tc]); 986 987 *tc_group = MLX5_GET(ets_tcn_config_reg, ets_tcn_conf, 988 group); 989 990 return 0; 991} 992EXPORT_SYMBOL_GPL(mlx5_query_port_tc_group); 993 994int mlx5_set_port_tc_bw_alloc(struct mlx5_core_dev *mdev, const u8 *tc_bw) 995{ 996 u32 in[MLX5_ST_SZ_DW(qetc_reg)] = {}; 997 int i; 998 999 for (i = 0; i <= mlx5_max_tc(mdev); i++) { 1000 MLX5_SET(qetc_reg, in, tc_configuration[i].b, 1); 1001 MLX5_SET(qetc_reg, in, tc_configuration[i].bw_allocation, tc_bw[i]); 1002 } 1003 1004 return mlx5_set_port_qetcr_reg(mdev, in, sizeof(in)); 1005} 1006EXPORT_SYMBOL_GPL(mlx5_set_port_tc_bw_alloc); 1007 1008int mlx5_query_port_tc_bw_alloc(struct mlx5_core_dev *mdev, u8 *bw_pct) 1009{ 1010 u32 out[MLX5_ST_SZ_DW(qetc_reg)]; 1011 void *ets_tcn_conf; 1012 int err; 1013 int i; 1014 1015 err = mlx5_query_port_qetcr_reg(mdev, out, sizeof(out)); 1016 if (err) 1017 return err; 1018 1019 for (i = 0; i <= mlx5_max_tc(mdev); i++) { 1020 ets_tcn_conf = MLX5_ADDR_OF(qetc_reg, out, tc_configuration[i]); 1021 bw_pct[i] = MLX5_GET(ets_tcn_config_reg, ets_tcn_conf, bw_allocation); 1022 } 1023 return 0; 1024} 1025EXPORT_SYMBOL_GPL(mlx5_query_port_tc_bw_alloc); 1026 1027int mlx5_modify_port_cong_params(struct mlx5_core_dev *mdev, 1028 void *in, int in_size) 1029{ 1030 u32 out[MLX5_ST_SZ_DW(modify_cong_params_out)] = {0}; 1031 1032 MLX5_SET(modify_cong_params_in, in, opcode, 1033 MLX5_CMD_OP_MODIFY_CONG_PARAMS); 1034 1035 return mlx5_cmd_exec(mdev, in, in_size, out, sizeof(out)); 1036} 1037 1038int mlx5_query_port_cong_statistics(struct mlx5_core_dev *mdev, int clear, 1039 void *out, int out_size) 1040{ 1041 u32 in[MLX5_ST_SZ_DW(query_cong_statistics_in)] = {0}; 1042 1043 MLX5_SET(query_cong_statistics_in, in, opcode, 1044 MLX5_CMD_OP_QUERY_CONG_STATISTICS); 1045 MLX5_SET(query_cong_statistics_in, in, clear, clear); 1046 1047 return mlx5_cmd_exec(mdev, in, sizeof(in), out, out_size); 1048} 1049 1050int mlx5_set_diagnostic_params(struct mlx5_core_dev *mdev, void *in, 1051 int in_size) 1052{ 1053 u32 out[MLX5_ST_SZ_DW(set_diagnostic_params_out)] = {0}; 1054 1055 MLX5_SET(set_diagnostic_params_in, in, opcode, 1056 MLX5_CMD_OP_SET_DIAGNOSTICS); 1057 1058 return mlx5_cmd_exec(mdev, in, in_size, out, sizeof(out)); 1059} 1060 1061int mlx5_query_diagnostic_counters(struct mlx5_core_dev *mdev, 1062 u8 num_of_samples, u16 sample_index, 1063 void *out, int out_size) 1064{ 1065 u32 in[MLX5_ST_SZ_DW(query_diagnostic_counters_in)] = {0}; 1066 1067 MLX5_SET(query_diagnostic_counters_in, in, opcode, 1068 MLX5_CMD_OP_QUERY_DIAGNOSTICS); 1069 MLX5_SET(query_diagnostic_counters_in, in, num_of_samples, 1070 num_of_samples); 1071 MLX5_SET(query_diagnostic_counters_in, in, sample_index, sample_index); 1072 1073 return mlx5_cmd_exec(mdev, in, sizeof(in), out, out_size); 1074} 1075 1076int mlx5_set_trust_state(struct mlx5_core_dev *mdev, u8 trust_state) 1077{ 1078 u32 out[MLX5_ST_SZ_DW(qpts_reg)] = {}; 1079 u32 in[MLX5_ST_SZ_DW(qpts_reg)] = {}; 1080 int err; 1081 1082 MLX5_SET(qpts_reg, in, local_port, 1); 1083 MLX5_SET(qpts_reg, in, trust_state, trust_state); 1084 1085 err = mlx5_core_access_reg(mdev, in, sizeof(in), out, 1086 sizeof(out), MLX5_REG_QPTS, 0, 1); 1087 return err; 1088} 1089 1090int mlx5_query_trust_state(struct mlx5_core_dev *mdev, u8 *trust_state) 1091{ 1092 u32 out[MLX5_ST_SZ_DW(qpts_reg)] = {}; 1093 u32 in[MLX5_ST_SZ_DW(qpts_reg)] = {}; 1094 int err; 1095 1096 MLX5_SET(qpts_reg, in, local_port, 1); 1097 1098 err = mlx5_core_access_reg(mdev, in, sizeof(in), out, 1099 sizeof(out), MLX5_REG_QPTS, 0, 0); 1100 if (!err) 1101 *trust_state = MLX5_GET(qpts_reg, out, trust_state); 1102 1103 return err; 1104} 1105 1106int mlx5_set_dscp2prio(struct mlx5_core_dev *mdev, const u8 *dscp2prio) 1107{ 1108 int sz = MLX5_ST_SZ_BYTES(qpdpm_reg); 1109 void *qpdpm_dscp; 1110 void *out; 1111 void *in; 1112 int err; 1113 int i; 1114 1115 in = kzalloc(sz, GFP_KERNEL); 1116 out = kzalloc(sz, GFP_KERNEL); 1117 if (!in || !out) { 1118 err = -ENOMEM; 1119 goto out; 1120 } 1121 1122 MLX5_SET(qpdpm_reg, in, local_port, 1); 1123 err = mlx5_core_access_reg(mdev, in, sz, out, sz, MLX5_REG_QPDPM, 0, 0); 1124 if (err) 1125 goto out; 1126 1127 memcpy(in, out, sz); 1128 MLX5_SET(qpdpm_reg, in, local_port, 1); 1129 1130 /* Update the corresponding dscp entry */ 1131 for (i = 0; i < MLX5_MAX_SUPPORTED_DSCP; i++) { 1132 qpdpm_dscp = MLX5_ADDR_OF(qpdpm_reg, in, dscp[i]); 1133 MLX5_SET16(qpdpm_dscp_reg, qpdpm_dscp, prio, dscp2prio[i]); 1134 MLX5_SET16(qpdpm_dscp_reg, qpdpm_dscp, e, 1); 1135 } 1136 err = mlx5_core_access_reg(mdev, in, sz, out, sz, MLX5_REG_QPDPM, 0, 1); 1137out: 1138 kfree(in); 1139 kfree(out); 1140 return err; 1141} 1142 1143int mlx5_query_dscp2prio(struct mlx5_core_dev *mdev, u8 *dscp2prio) 1144{ 1145 int sz = MLX5_ST_SZ_BYTES(qpdpm_reg); 1146 void *qpdpm_dscp; 1147 void *out; 1148 void *in; 1149 int err; 1150 int i; 1151 1152 in = kzalloc(sz, GFP_KERNEL); 1153 out = kzalloc(sz, GFP_KERNEL); 1154 if (!in || !out) { 1155 err = -ENOMEM; 1156 goto out; 1157 } 1158 1159 MLX5_SET(qpdpm_reg, in, local_port, 1); 1160 err = mlx5_core_access_reg(mdev, in, sz, out, sz, MLX5_REG_QPDPM, 0, 0); 1161 if (err) 1162 goto out; 1163 1164 for (i = 0; i < MLX5_MAX_SUPPORTED_DSCP; i++) { 1165 qpdpm_dscp = MLX5_ADDR_OF(qpdpm_reg, out, dscp[i]); 1166 dscp2prio[i] = MLX5_GET16(qpdpm_dscp_reg, qpdpm_dscp, prio); 1167 } 1168out: 1169 kfree(in); 1170 kfree(out); 1171 return err; 1172} 1173 1174int mlx5_query_pddr_range_info(struct mlx5_core_dev *mdev, u8 local_port, u8 *is_er_type) 1175{ 1176 u32 pddr_reg[MLX5_ST_SZ_DW(pddr_reg)] = {}; 1177 int sz = MLX5_ST_SZ_BYTES(pddr_reg); 1178 int error; 1179 u8 ecc; 1180 u8 ci; 1181 1182 MLX5_SET(pddr_reg, pddr_reg, local_port, local_port); 1183 MLX5_SET(pddr_reg, pddr_reg, page_select, 3 /* module info page */); 1184 1185 error = mlx5_core_access_reg(mdev, pddr_reg, sz, pddr_reg, sz, 1186 MLX5_ACCESS_REG_SUMMARY_CTRL_ID_PDDR, 0, 0); 1187 if (error != 0) 1188 return (error); 1189 1190 ecc = MLX5_GET(pddr_reg, pddr_reg, page_data.pddr_module_info.ethernet_compliance_code); 1191 ci = MLX5_GET(pddr_reg, pddr_reg, page_data.pddr_module_info.cable_identifier); 1192 1193 switch (ci) { 1194 case 0: /* QSFP28 */ 1195 case 1: /* QSFP+ */ 1196 *is_er_type = 0; 1197 break; 1198 case 2: /* SFP28/SFP+ */ 1199 case 3: /* QSA (QSFP->SFP) */ 1200 *is_er_type = ((ecc & (1 << 7)) != 0); 1201 break; 1202 default: 1203 *is_er_type = 0; 1204 break; 1205 } 1206 return (0); 1207} 1208EXPORT_SYMBOL_GPL(mlx5_query_pddr_range_info); 1209