mlx5_port.c revision 347868
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 347868 2019-05-16 18:19:08Z 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, bool ext) 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 if (ext) 273 MLX5_SET(ptys_reg, in, ext_eth_proto_admin, proto_admin); 274 else 275 MLX5_SET(ptys_reg, in, eth_proto_admin, proto_admin); 276 } else { 277 MLX5_SET(ptys_reg, in, ib_proto_admin, proto_admin); 278 } 279 280 err = mlx5_core_access_reg(dev, in, sizeof(in), out, 281 sizeof(out), MLX5_REG_PTYS, 0, 1); 282 return err; 283} 284EXPORT_SYMBOL_GPL(mlx5_set_port_proto); 285 286int mlx5_set_port_status(struct mlx5_core_dev *dev, 287 enum mlx5_port_status status) 288{ 289 u32 in[MLX5_ST_SZ_DW(paos_reg)] = {0}; 290 u32 out[MLX5_ST_SZ_DW(paos_reg)] = {0}; 291 int err; 292 293 MLX5_SET(paos_reg, in, local_port, 1); 294 295 MLX5_SET(paos_reg, in, admin_status, status); 296 MLX5_SET(paos_reg, in, ase, 1); 297 298 err = mlx5_core_access_reg(dev, in, sizeof(in), out, 299 sizeof(out), MLX5_REG_PAOS, 0, 1); 300 return err; 301} 302 303int mlx5_query_port_status(struct mlx5_core_dev *dev, u8 *status) 304{ 305 u32 in[MLX5_ST_SZ_DW(paos_reg)] = {0}; 306 u32 out[MLX5_ST_SZ_DW(paos_reg)] = {0}; 307 int err; 308 309 MLX5_SET(paos_reg, in, local_port, 1); 310 311 err = mlx5_core_access_reg(dev, in, sizeof(in), out, 312 sizeof(out), MLX5_REG_PAOS, 0, 0); 313 if (err) 314 return err; 315 316 *status = MLX5_GET(paos_reg, out, oper_status); 317 return err; 318} 319 320int mlx5_query_port_admin_status(struct mlx5_core_dev *dev, 321 enum mlx5_port_status *status) 322{ 323 u32 in[MLX5_ST_SZ_DW(paos_reg)] = {0}; 324 u32 out[MLX5_ST_SZ_DW(paos_reg)]; 325 int err; 326 327 MLX5_SET(paos_reg, in, local_port, 1); 328 err = mlx5_core_access_reg(dev, in, sizeof(in), out, 329 sizeof(out), MLX5_REG_PAOS, 0, 0); 330 if (err) 331 return err; 332 *status = MLX5_GET(paos_reg, out, admin_status); 333 return 0; 334} 335EXPORT_SYMBOL_GPL(mlx5_query_port_admin_status); 336 337static int mlx5_query_port_mtu(struct mlx5_core_dev *dev, 338 int *admin_mtu, int *max_mtu, int *oper_mtu) 339{ 340 u32 in[MLX5_ST_SZ_DW(pmtu_reg)] = {0}; 341 u32 out[MLX5_ST_SZ_DW(pmtu_reg)] = {0}; 342 int err; 343 344 MLX5_SET(pmtu_reg, in, local_port, 1); 345 346 err = mlx5_core_access_reg(dev, in, sizeof(in), out, 347 sizeof(out), MLX5_REG_PMTU, 0, 0); 348 if (err) 349 return err; 350 351 if (max_mtu) 352 *max_mtu = MLX5_GET(pmtu_reg, out, max_mtu); 353 if (oper_mtu) 354 *oper_mtu = MLX5_GET(pmtu_reg, out, oper_mtu); 355 if (admin_mtu) 356 *admin_mtu = MLX5_GET(pmtu_reg, out, admin_mtu); 357 358 return err; 359} 360 361int mlx5_set_port_mtu(struct mlx5_core_dev *dev, int mtu) 362{ 363 u32 in[MLX5_ST_SZ_DW(pmtu_reg)] = {0}; 364 u32 out[MLX5_ST_SZ_DW(pmtu_reg)] = {0}; 365 366 MLX5_SET(pmtu_reg, in, admin_mtu, mtu); 367 MLX5_SET(pmtu_reg, in, local_port, 1); 368 369 return mlx5_core_access_reg(dev, in, sizeof(in), out, 370 sizeof(out), MLX5_REG_PMTU, 0, 1); 371} 372EXPORT_SYMBOL_GPL(mlx5_set_port_mtu); 373 374int mlx5_query_port_max_mtu(struct mlx5_core_dev *dev, int *max_mtu) 375{ 376 return mlx5_query_port_mtu(dev, NULL, max_mtu, NULL); 377} 378EXPORT_SYMBOL_GPL(mlx5_query_port_max_mtu); 379 380int mlx5_set_port_pause_and_pfc(struct mlx5_core_dev *dev, u32 port, 381 u8 rx_pause, u8 tx_pause, 382 u8 pfc_en_rx, u8 pfc_en_tx) 383{ 384 u32 in[MLX5_ST_SZ_DW(pfcc_reg)] = {0}; 385 u32 out[MLX5_ST_SZ_DW(pfcc_reg)] = {0}; 386 387 if (pfc_en_rx || pfc_en_tx) { 388 /* PFC and global pauseframes are incompatible features */ 389 if (tx_pause || rx_pause) 390 return -EINVAL; 391 } 392 393 MLX5_SET(pfcc_reg, in, local_port, port); 394 MLX5_SET(pfcc_reg, in, pptx, tx_pause); 395 MLX5_SET(pfcc_reg, in, pprx, rx_pause); 396 MLX5_SET(pfcc_reg, in, pfctx, pfc_en_tx); 397 MLX5_SET(pfcc_reg, in, pfcrx, pfc_en_rx); 398 MLX5_SET(pfcc_reg, in, prio_mask_tx, pfc_en_tx); 399 MLX5_SET(pfcc_reg, in, prio_mask_rx, pfc_en_rx); 400 401 return mlx5_core_access_reg(dev, in, sizeof(in), out, 402 sizeof(out), MLX5_REG_PFCC, 0, 1); 403} 404 405int mlx5_query_port_pause(struct mlx5_core_dev *dev, u32 port, 406 u32 *rx_pause, u32 *tx_pause) 407{ 408 u32 in[MLX5_ST_SZ_DW(pfcc_reg)] = {0}; 409 u32 out[MLX5_ST_SZ_DW(pfcc_reg)] = {0}; 410 int err; 411 412 MLX5_SET(pfcc_reg, in, local_port, port); 413 414 err = mlx5_core_access_reg(dev, in, sizeof(in), out, 415 sizeof(out), MLX5_REG_PFCC, 0, 0); 416 if (err) 417 return err; 418 419 *rx_pause = MLX5_GET(pfcc_reg, out, pprx); 420 *tx_pause = MLX5_GET(pfcc_reg, out, pptx); 421 422 return 0; 423} 424 425int mlx5_query_port_pfc(struct mlx5_core_dev *dev, u8 *pfc_en_tx, u8 *pfc_en_rx) 426{ 427 u32 in[MLX5_ST_SZ_DW(pfcc_reg)] = {}; 428 u32 out[MLX5_ST_SZ_DW(pfcc_reg)]; 429 int err; 430 431 MLX5_SET(pfcc_reg, in, local_port, 1); 432 err = mlx5_core_access_reg(dev, in, sizeof(in), out, 433 sizeof(out), MLX5_REG_PFCC, 0, 0); 434 if (err) 435 return err; 436 437 if (pfc_en_tx != NULL) 438 *pfc_en_tx = MLX5_GET(pfcc_reg, out, pfctx); 439 if (pfc_en_rx != NULL) 440 *pfc_en_rx = MLX5_GET(pfcc_reg, out, pfcrx); 441 return 0; 442} 443EXPORT_SYMBOL_GPL(mlx5_query_port_pfc); 444 445int mlx5_query_port_oper_mtu(struct mlx5_core_dev *dev, int *oper_mtu) 446{ 447 return mlx5_query_port_mtu(dev, NULL, NULL, oper_mtu); 448} 449EXPORT_SYMBOL_GPL(mlx5_query_port_oper_mtu); 450 451u8 mlx5_is_wol_supported(struct mlx5_core_dev *dev) 452{ 453 u8 wol_supported = 0; 454 455 if (MLX5_CAP_GEN(dev, wol_s)) 456 wol_supported |= MLX5_WOL_SECURED_MAGIC; 457 if (MLX5_CAP_GEN(dev, wol_g)) 458 wol_supported |= MLX5_WOL_MAGIC; 459 if (MLX5_CAP_GEN(dev, wol_a)) 460 wol_supported |= MLX5_WOL_ARP; 461 if (MLX5_CAP_GEN(dev, wol_b)) 462 wol_supported |= MLX5_WOL_BROADCAST; 463 if (MLX5_CAP_GEN(dev, wol_m)) 464 wol_supported |= MLX5_WOL_MULTICAST; 465 if (MLX5_CAP_GEN(dev, wol_u)) 466 wol_supported |= MLX5_WOL_UNICAST; 467 if (MLX5_CAP_GEN(dev, wol_p)) 468 wol_supported |= MLX5_WOL_PHY_ACTIVITY; 469 470 return wol_supported; 471} 472EXPORT_SYMBOL_GPL(mlx5_is_wol_supported); 473 474int mlx5_set_wol(struct mlx5_core_dev *dev, u8 wol_mode) 475{ 476 u32 in[MLX5_ST_SZ_DW(set_wol_rol_in)] = {0}; 477 u32 out[MLX5_ST_SZ_DW(set_wol_rol_out)] = {0}; 478 479 MLX5_SET(set_wol_rol_in, in, opcode, MLX5_CMD_OP_SET_WOL_ROL); 480 MLX5_SET(set_wol_rol_in, in, wol_mode_valid, 1); 481 MLX5_SET(set_wol_rol_in, in, wol_mode, wol_mode); 482 483 return mlx5_cmd_exec(dev, in, sizeof(in), out, sizeof(out)); 484} 485EXPORT_SYMBOL_GPL(mlx5_set_wol); 486 487int mlx5_query_dropless_mode(struct mlx5_core_dev *dev, u16 *timeout) 488{ 489 u32 in[MLX5_ST_SZ_DW(query_delay_drop_params_in)] = {0}; 490 u32 out[MLX5_ST_SZ_DW(query_delay_drop_params_out)] = {0}; 491 int err = 0; 492 493 MLX5_SET(query_delay_drop_params_in, in, opcode, 494 MLX5_CMD_OP_QUERY_DELAY_DROP_PARAMS); 495 496 err = mlx5_cmd_exec(dev, in, sizeof(in), out, sizeof(out)); 497 if (err) 498 return err; 499 500 *timeout = MLX5_GET(query_delay_drop_params_out, out, 501 delay_drop_timeout); 502 503 return 0; 504} 505EXPORT_SYMBOL_GPL(mlx5_query_dropless_mode); 506 507int mlx5_set_dropless_mode(struct mlx5_core_dev *dev, u16 timeout) 508{ 509 u32 in[MLX5_ST_SZ_DW(set_delay_drop_params_in)] = {0}; 510 u32 out[MLX5_ST_SZ_DW(set_delay_drop_params_out)] = {0}; 511 512 MLX5_SET(set_delay_drop_params_in, in, opcode, 513 MLX5_CMD_OP_SET_DELAY_DROP_PARAMS); 514 MLX5_SET(set_delay_drop_params_in, in, delay_drop_timeout, timeout); 515 516 return mlx5_cmd_exec(dev, in, sizeof(in), out, sizeof(out)); 517} 518EXPORT_SYMBOL_GPL(mlx5_set_dropless_mode); 519 520int mlx5_core_access_pvlc(struct mlx5_core_dev *dev, 521 struct mlx5_pvlc_reg *pvlc, int write) 522{ 523 int sz = MLX5_ST_SZ_BYTES(pvlc_reg); 524 u8 in[MLX5_ST_SZ_BYTES(pvlc_reg)] = {0}; 525 u8 out[MLX5_ST_SZ_BYTES(pvlc_reg)] = {0}; 526 int err; 527 528 MLX5_SET(pvlc_reg, in, local_port, pvlc->local_port); 529 if (write) 530 MLX5_SET(pvlc_reg, in, vl_admin, pvlc->vl_admin); 531 532 err = mlx5_core_access_reg(dev, in, sz, out, sz, MLX5_REG_PVLC, 0, 533 !!write); 534 if (err) 535 return err; 536 537 if (!write) { 538 pvlc->local_port = MLX5_GET(pvlc_reg, out, local_port); 539 pvlc->vl_hw_cap = MLX5_GET(pvlc_reg, out, vl_hw_cap); 540 pvlc->vl_admin = MLX5_GET(pvlc_reg, out, vl_admin); 541 pvlc->vl_operational = MLX5_GET(pvlc_reg, out, vl_operational); 542 } 543 544 return 0; 545} 546EXPORT_SYMBOL_GPL(mlx5_core_access_pvlc); 547 548int mlx5_core_access_ptys(struct mlx5_core_dev *dev, 549 struct mlx5_ptys_reg *ptys, int write) 550{ 551 int sz = MLX5_ST_SZ_BYTES(ptys_reg); 552 void *out = NULL; 553 void *in = NULL; 554 int err; 555 556 in = mlx5_vzalloc(sz); 557 if (!in) 558 return -ENOMEM; 559 560 out = mlx5_vzalloc(sz); 561 if (!out) { 562 kfree(in); 563 return -ENOMEM; 564 } 565 566 MLX5_SET(ptys_reg, in, local_port, ptys->local_port); 567 MLX5_SET(ptys_reg, in, proto_mask, ptys->proto_mask); 568 if (write) { 569 MLX5_SET(ptys_reg, in, eth_proto_capability, 570 ptys->eth_proto_cap); 571 MLX5_SET(ptys_reg, in, ib_link_width_capability, 572 ptys->ib_link_width_cap); 573 MLX5_SET(ptys_reg, in, ib_proto_capability, 574 ptys->ib_proto_cap); 575 MLX5_SET(ptys_reg, in, eth_proto_admin, ptys->eth_proto_admin); 576 MLX5_SET(ptys_reg, in, ib_link_width_admin, 577 ptys->ib_link_width_admin); 578 MLX5_SET(ptys_reg, in, ib_proto_admin, ptys->ib_proto_admin); 579 MLX5_SET(ptys_reg, in, eth_proto_oper, ptys->eth_proto_oper); 580 MLX5_SET(ptys_reg, in, ib_link_width_oper, 581 ptys->ib_link_width_oper); 582 MLX5_SET(ptys_reg, in, ib_proto_oper, ptys->ib_proto_oper); 583 MLX5_SET(ptys_reg, in, eth_proto_lp_advertise, 584 ptys->eth_proto_lp_advertise); 585 } 586 587 err = mlx5_core_access_reg(dev, in, sz, out, sz, MLX5_REG_PTYS, 0, 588 !!write); 589 if (err) 590 goto out; 591 592 if (!write) { 593 ptys->local_port = MLX5_GET(ptys_reg, out, local_port); 594 ptys->proto_mask = MLX5_GET(ptys_reg, out, proto_mask); 595 ptys->eth_proto_cap = MLX5_GET(ptys_reg, out, 596 eth_proto_capability); 597 ptys->ib_link_width_cap = MLX5_GET(ptys_reg, out, 598 ib_link_width_capability); 599 ptys->ib_proto_cap = MLX5_GET(ptys_reg, out, 600 ib_proto_capability); 601 ptys->eth_proto_admin = MLX5_GET(ptys_reg, out, 602 eth_proto_admin); 603 ptys->ib_link_width_admin = MLX5_GET(ptys_reg, out, 604 ib_link_width_admin); 605 ptys->ib_proto_admin = MLX5_GET(ptys_reg, out, ib_proto_admin); 606 ptys->eth_proto_oper = MLX5_GET(ptys_reg, out, eth_proto_oper); 607 ptys->ib_link_width_oper = MLX5_GET(ptys_reg, out, 608 ib_link_width_oper); 609 ptys->ib_proto_oper = MLX5_GET(ptys_reg, out, ib_proto_oper); 610 ptys->eth_proto_lp_advertise = MLX5_GET(ptys_reg, out, 611 eth_proto_lp_advertise); 612 } 613 614out: 615 kvfree(in); 616 kvfree(out); 617 return err; 618} 619EXPORT_SYMBOL_GPL(mlx5_core_access_ptys); 620 621static int mtu_to_ib_mtu(int mtu) 622{ 623 switch (mtu) { 624 case 256: return 1; 625 case 512: return 2; 626 case 1024: return 3; 627 case 2048: return 4; 628 case 4096: return 5; 629 default: 630 printf("mlx5_core: WARN: ""invalid mtu\n"); 631 return -1; 632 } 633} 634 635int mlx5_core_access_pmtu(struct mlx5_core_dev *dev, 636 struct mlx5_pmtu_reg *pmtu, int write) 637{ 638 int sz = MLX5_ST_SZ_BYTES(pmtu_reg); 639 void *out = NULL; 640 void *in = NULL; 641 int err; 642 643 in = mlx5_vzalloc(sz); 644 if (!in) 645 return -ENOMEM; 646 647 out = mlx5_vzalloc(sz); 648 if (!out) { 649 kfree(in); 650 return -ENOMEM; 651 } 652 653 MLX5_SET(pmtu_reg, in, local_port, pmtu->local_port); 654 if (write) 655 MLX5_SET(pmtu_reg, in, admin_mtu, pmtu->admin_mtu); 656 657 err = mlx5_core_access_reg(dev, in, sz, out, sz, MLX5_REG_PMTU, 0, 658 !!write); 659 if (err) 660 goto out; 661 662 if (!write) { 663 pmtu->local_port = MLX5_GET(pmtu_reg, out, local_port); 664 pmtu->max_mtu = mtu_to_ib_mtu(MLX5_GET(pmtu_reg, out, 665 max_mtu)); 666 pmtu->admin_mtu = mtu_to_ib_mtu(MLX5_GET(pmtu_reg, out, 667 admin_mtu)); 668 pmtu->oper_mtu = mtu_to_ib_mtu(MLX5_GET(pmtu_reg, out, 669 oper_mtu)); 670 } 671 672out: 673 kvfree(in); 674 kvfree(out); 675 return err; 676} 677EXPORT_SYMBOL_GPL(mlx5_core_access_pmtu); 678 679int mlx5_query_module_num(struct mlx5_core_dev *dev, int *module_num) 680{ 681 u32 in[MLX5_ST_SZ_DW(pmlp_reg)] = {0}; 682 u32 out[MLX5_ST_SZ_DW(pmlp_reg)] = {0}; 683 int lane = 0; 684 int err; 685 686 MLX5_SET(pmlp_reg, in, local_port, 1); 687 688 err = mlx5_core_access_reg(dev, in, sizeof(in), out, 689 sizeof(out), MLX5_REG_PMLP, 0, 0); 690 if (err) 691 return err; 692 693 lane = MLX5_GET(pmlp_reg, out, lane0_module_mapping); 694 *module_num = lane & MLX5_EEPROM_IDENTIFIER_BYTE_MASK; 695 696 return 0; 697} 698EXPORT_SYMBOL_GPL(mlx5_query_module_num); 699 700int mlx5_query_eeprom(struct mlx5_core_dev *dev, 701 int i2c_addr, int page_num, int device_addr, 702 int size, int module_num, u32 *data, int *size_read) 703{ 704 u32 in[MLX5_ST_SZ_DW(mcia_reg)] = {0}; 705 u32 out[MLX5_ST_SZ_DW(mcia_reg)] = {0}; 706 u32 *ptr = (u32 *)MLX5_ADDR_OF(mcia_reg, out, dword_0); 707 int status; 708 int err; 709 710 size = min_t(int, size, MLX5_EEPROM_MAX_BYTES); 711 712 MLX5_SET(mcia_reg, in, l, 0); 713 MLX5_SET(mcia_reg, in, module, module_num); 714 MLX5_SET(mcia_reg, in, i2c_device_address, i2c_addr); 715 MLX5_SET(mcia_reg, in, page_number, page_num); 716 MLX5_SET(mcia_reg, in, device_address, device_addr); 717 MLX5_SET(mcia_reg, in, size, size); 718 719 err = mlx5_core_access_reg(dev, in, sizeof(in), out, 720 sizeof(out), MLX5_REG_MCIA, 0, 0); 721 if (err) 722 return err; 723 724 status = MLX5_GET(mcia_reg, out, status); 725 if (status) 726 return status; 727 728 memcpy(data, ptr, size); 729 *size_read = size; 730 return 0; 731} 732EXPORT_SYMBOL_GPL(mlx5_query_eeprom); 733 734int mlx5_vxlan_udp_port_add(struct mlx5_core_dev *dev, u16 port) 735{ 736 u32 in[MLX5_ST_SZ_DW(add_vxlan_udp_dport_in)] = {0}; 737 u32 out[MLX5_ST_SZ_DW(add_vxlan_udp_dport_out)] = {0}; 738 int err; 739 740 MLX5_SET(add_vxlan_udp_dport_in, in, opcode, 741 MLX5_CMD_OP_ADD_VXLAN_UDP_DPORT); 742 MLX5_SET(add_vxlan_udp_dport_in, in, vxlan_udp_port, port); 743 744 err = mlx5_cmd_exec(dev, in, sizeof(in), out, sizeof(out)); 745 if (err) { 746 mlx5_core_err(dev, "Failed %s, port %u, err - %d", 747 mlx5_command_str(MLX5_CMD_OP_ADD_VXLAN_UDP_DPORT), 748 port, err); 749 } 750 751 return err; 752} 753 754int mlx5_vxlan_udp_port_delete(struct mlx5_core_dev *dev, u16 port) 755{ 756 u32 in[MLX5_ST_SZ_DW(delete_vxlan_udp_dport_in)] = {0}; 757 u32 out[MLX5_ST_SZ_DW(delete_vxlan_udp_dport_out)] = {0}; 758 int err; 759 760 MLX5_SET(delete_vxlan_udp_dport_in, in, opcode, 761 MLX5_CMD_OP_DELETE_VXLAN_UDP_DPORT); 762 MLX5_SET(delete_vxlan_udp_dport_in, in, vxlan_udp_port, port); 763 764 err = mlx5_cmd_exec(dev, in, sizeof(in), out, sizeof(out)); 765 if (err) { 766 mlx5_core_err(dev, "Failed %s, port %u, err - %d", 767 mlx5_command_str(MLX5_CMD_OP_DELETE_VXLAN_UDP_DPORT), 768 port, err); 769 } 770 771 return err; 772} 773 774int mlx5_query_wol(struct mlx5_core_dev *dev, u8 *wol_mode) 775{ 776 u32 in[MLX5_ST_SZ_DW(query_wol_rol_in)] = {0}; 777 u32 out[MLX5_ST_SZ_DW(query_wol_rol_out)] = {0}; 778 int err; 779 780 MLX5_SET(query_wol_rol_in, in, opcode, MLX5_CMD_OP_QUERY_WOL_ROL); 781 782 err = mlx5_cmd_exec(dev, in, sizeof(in), out, sizeof(out)); 783 784 if (!err) 785 *wol_mode = MLX5_GET(query_wol_rol_out, out, wol_mode); 786 787 return err; 788} 789EXPORT_SYMBOL_GPL(mlx5_query_wol); 790 791int mlx5_query_port_cong_status(struct mlx5_core_dev *mdev, int protocol, 792 int priority, int *is_enable) 793{ 794 u32 in[MLX5_ST_SZ_DW(query_cong_status_in)] = {0}; 795 u32 out[MLX5_ST_SZ_DW(query_cong_status_out)] = {0}; 796 int err; 797 798 *is_enable = 0; 799 800 MLX5_SET(query_cong_status_in, in, opcode, 801 MLX5_CMD_OP_QUERY_CONG_STATUS); 802 MLX5_SET(query_cong_status_in, in, cong_protocol, protocol); 803 MLX5_SET(query_cong_status_in, in, priority, priority); 804 805 err = mlx5_cmd_exec(mdev, in, sizeof(in), out, sizeof(out)); 806 if (!err) 807 *is_enable = MLX5_GET(query_cong_status_out, out, enable); 808 return err; 809} 810 811int mlx5_modify_port_cong_status(struct mlx5_core_dev *mdev, int protocol, 812 int priority, int enable) 813{ 814 u32 in[MLX5_ST_SZ_DW(modify_cong_status_in)] = {0}; 815 u32 out[MLX5_ST_SZ_DW(modify_cong_status_out)] = {0}; 816 817 MLX5_SET(modify_cong_status_in, in, opcode, 818 MLX5_CMD_OP_MODIFY_CONG_STATUS); 819 MLX5_SET(modify_cong_status_in, in, cong_protocol, protocol); 820 MLX5_SET(modify_cong_status_in, in, priority, priority); 821 MLX5_SET(modify_cong_status_in, in, enable, enable); 822 823 return mlx5_cmd_exec(mdev, in, sizeof(in), out, sizeof(out)); 824} 825 826int mlx5_query_port_cong_params(struct mlx5_core_dev *mdev, int protocol, 827 void *out, int out_size) 828{ 829 u32 in[MLX5_ST_SZ_DW(query_cong_params_in)] = {0}; 830 831 MLX5_SET(query_cong_params_in, in, opcode, 832 MLX5_CMD_OP_QUERY_CONG_PARAMS); 833 MLX5_SET(query_cong_params_in, in, cong_protocol, protocol); 834 835 return mlx5_cmd_exec(mdev, in, sizeof(in), out, out_size); 836} 837 838static int mlx5_query_port_qetcr_reg(struct mlx5_core_dev *mdev, u32 *out, 839 int outlen) 840{ 841 u32 in[MLX5_ST_SZ_DW(qetc_reg)]; 842 843 if (!MLX5_CAP_GEN(mdev, ets)) 844 return -ENOTSUPP; 845 846 memset(in, 0, sizeof(in)); 847 return mlx5_core_access_reg(mdev, in, sizeof(in), out, outlen, 848 MLX5_REG_QETCR, 0, 0); 849} 850 851int mlx5_max_tc(struct mlx5_core_dev *mdev) 852{ 853 u8 num_tc = MLX5_CAP_GEN(mdev, max_tc) ? : 8; 854 855 return num_tc - 1; 856} 857EXPORT_SYMBOL_GPL(mlx5_max_tc); 858 859static int mlx5_set_port_qetcr_reg(struct mlx5_core_dev *mdev, u32 *in, 860 int inlen) 861{ 862 u32 out[MLX5_ST_SZ_DW(qetc_reg)]; 863 864 if (!MLX5_CAP_GEN(mdev, ets)) 865 return -ENOTSUPP; 866 867 return mlx5_core_access_reg(mdev, in, inlen, out, sizeof(out), 868 MLX5_REG_QETCR, 0, 1); 869} 870 871int mlx5_query_port_tc_rate_limit(struct mlx5_core_dev *mdev, 872 u8 *max_bw_value, 873 u8 *max_bw_units) 874{ 875 u32 out[MLX5_ST_SZ_DW(qetc_reg)]; 876 void *ets_tcn_conf; 877 int err; 878 int i; 879 880 err = mlx5_query_port_qetcr_reg(mdev, out, sizeof(out)); 881 if (err) 882 return err; 883 884 for (i = 0; i <= mlx5_max_tc(mdev); i++) { 885 ets_tcn_conf = MLX5_ADDR_OF(qetc_reg, out, tc_configuration[i]); 886 887 max_bw_value[i] = MLX5_GET(ets_tcn_config_reg, ets_tcn_conf, 888 max_bw_value); 889 max_bw_units[i] = MLX5_GET(ets_tcn_config_reg, ets_tcn_conf, 890 max_bw_units); 891 } 892 893 return 0; 894} 895EXPORT_SYMBOL_GPL(mlx5_query_port_tc_rate_limit); 896 897int mlx5_modify_port_tc_rate_limit(struct mlx5_core_dev *mdev, 898 const u8 *max_bw_value, 899 const u8 *max_bw_units) 900{ 901 u32 in[MLX5_ST_SZ_DW(qetc_reg)] = {}; 902 void *ets_tcn_conf; 903 int i; 904 905 MLX5_SET(qetc_reg, in, port_number, 1); 906 907 for (i = 0; i <= mlx5_max_tc(mdev); i++) { 908 ets_tcn_conf = MLX5_ADDR_OF(qetc_reg, in, tc_configuration[i]); 909 910 MLX5_SET(ets_tcn_config_reg, ets_tcn_conf, r, 1); 911 MLX5_SET(ets_tcn_config_reg, ets_tcn_conf, max_bw_units, 912 max_bw_units[i]); 913 MLX5_SET(ets_tcn_config_reg, ets_tcn_conf, max_bw_value, 914 max_bw_value[i]); 915 } 916 917 return mlx5_set_port_qetcr_reg(mdev, in, sizeof(in)); 918} 919EXPORT_SYMBOL_GPL(mlx5_modify_port_tc_rate_limit); 920 921int mlx5_query_port_prio_tc(struct mlx5_core_dev *mdev, 922 u8 prio, u8 *tc) 923{ 924 u32 in[MLX5_ST_SZ_DW(qtct_reg)]; 925 u32 out[MLX5_ST_SZ_DW(qtct_reg)]; 926 int err; 927 928 memset(in, 0, sizeof(in)); 929 memset(out, 0, sizeof(out)); 930 931 MLX5_SET(qtct_reg, in, port_number, 1); 932 MLX5_SET(qtct_reg, in, prio, prio); 933 934 err = mlx5_core_access_reg(mdev, in, sizeof(in), out, 935 sizeof(out), MLX5_REG_QTCT, 0, 0); 936 if (!err) 937 *tc = MLX5_GET(qtct_reg, out, tclass); 938 939 return err; 940} 941EXPORT_SYMBOL_GPL(mlx5_query_port_prio_tc); 942 943int mlx5_set_port_prio_tc(struct mlx5_core_dev *mdev, int prio_index, 944 const u8 prio_tc) 945{ 946 u32 in[MLX5_ST_SZ_DW(qtct_reg)] = {}; 947 u32 out[MLX5_ST_SZ_DW(qtct_reg)]; 948 int err; 949 950 if (prio_tc > mlx5_max_tc(mdev)) 951 return -EINVAL; 952 953 MLX5_SET(qtct_reg, in, prio, prio_index); 954 MLX5_SET(qtct_reg, in, tclass, prio_tc); 955 956 err = mlx5_core_access_reg(mdev, in, sizeof(in), out, 957 sizeof(out), MLX5_REG_QTCT, 0, 1); 958 959 return (err); 960} 961EXPORT_SYMBOL_GPL(mlx5_set_port_prio_tc); 962 963int mlx5_set_port_tc_group(struct mlx5_core_dev *mdev, const u8 *tc_group) 964{ 965 u32 in[MLX5_ST_SZ_DW(qetc_reg)] = {}; 966 int i; 967 968 for (i = 0; i <= mlx5_max_tc(mdev); i++) { 969 MLX5_SET(qetc_reg, in, tc_configuration[i].g, 1); 970 MLX5_SET(qetc_reg, in, tc_configuration[i].group, tc_group[i]); 971 } 972 973 return mlx5_set_port_qetcr_reg(mdev, in, sizeof(in)); 974} 975EXPORT_SYMBOL_GPL(mlx5_set_port_tc_group); 976 977int mlx5_query_port_tc_group(struct mlx5_core_dev *mdev, 978 u8 tc, u8 *tc_group) 979{ 980 u32 out[MLX5_ST_SZ_DW(qetc_reg)]; 981 void *ets_tcn_conf; 982 int err; 983 984 err = mlx5_query_port_qetcr_reg(mdev, out, sizeof(out)); 985 if (err) 986 return err; 987 988 ets_tcn_conf = MLX5_ADDR_OF(qetc_reg, out, 989 tc_configuration[tc]); 990 991 *tc_group = MLX5_GET(ets_tcn_config_reg, ets_tcn_conf, 992 group); 993 994 return 0; 995} 996EXPORT_SYMBOL_GPL(mlx5_query_port_tc_group); 997 998int mlx5_set_port_tc_bw_alloc(struct mlx5_core_dev *mdev, const u8 *tc_bw) 999{ 1000 u32 in[MLX5_ST_SZ_DW(qetc_reg)] = {}; 1001 int i; 1002 1003 for (i = 0; i <= mlx5_max_tc(mdev); i++) { 1004 MLX5_SET(qetc_reg, in, tc_configuration[i].b, 1); 1005 MLX5_SET(qetc_reg, in, tc_configuration[i].bw_allocation, tc_bw[i]); 1006 } 1007 1008 return mlx5_set_port_qetcr_reg(mdev, in, sizeof(in)); 1009} 1010EXPORT_SYMBOL_GPL(mlx5_set_port_tc_bw_alloc); 1011 1012int mlx5_query_port_tc_bw_alloc(struct mlx5_core_dev *mdev, u8 *bw_pct) 1013{ 1014 u32 out[MLX5_ST_SZ_DW(qetc_reg)]; 1015 void *ets_tcn_conf; 1016 int err; 1017 int i; 1018 1019 err = mlx5_query_port_qetcr_reg(mdev, out, sizeof(out)); 1020 if (err) 1021 return err; 1022 1023 for (i = 0; i <= mlx5_max_tc(mdev); i++) { 1024 ets_tcn_conf = MLX5_ADDR_OF(qetc_reg, out, tc_configuration[i]); 1025 bw_pct[i] = MLX5_GET(ets_tcn_config_reg, ets_tcn_conf, bw_allocation); 1026 } 1027 return 0; 1028} 1029EXPORT_SYMBOL_GPL(mlx5_query_port_tc_bw_alloc); 1030 1031int mlx5_modify_port_cong_params(struct mlx5_core_dev *mdev, 1032 void *in, int in_size) 1033{ 1034 u32 out[MLX5_ST_SZ_DW(modify_cong_params_out)] = {0}; 1035 1036 MLX5_SET(modify_cong_params_in, in, opcode, 1037 MLX5_CMD_OP_MODIFY_CONG_PARAMS); 1038 1039 return mlx5_cmd_exec(mdev, in, in_size, out, sizeof(out)); 1040} 1041 1042int mlx5_query_port_cong_statistics(struct mlx5_core_dev *mdev, int clear, 1043 void *out, int out_size) 1044{ 1045 u32 in[MLX5_ST_SZ_DW(query_cong_statistics_in)] = {0}; 1046 1047 MLX5_SET(query_cong_statistics_in, in, opcode, 1048 MLX5_CMD_OP_QUERY_CONG_STATISTICS); 1049 MLX5_SET(query_cong_statistics_in, in, clear, clear); 1050 1051 return mlx5_cmd_exec(mdev, in, sizeof(in), out, out_size); 1052} 1053 1054int mlx5_set_diagnostic_params(struct mlx5_core_dev *mdev, void *in, 1055 int in_size) 1056{ 1057 u32 out[MLX5_ST_SZ_DW(set_diagnostic_params_out)] = {0}; 1058 1059 MLX5_SET(set_diagnostic_params_in, in, opcode, 1060 MLX5_CMD_OP_SET_DIAGNOSTICS); 1061 1062 return mlx5_cmd_exec(mdev, in, in_size, out, sizeof(out)); 1063} 1064 1065int mlx5_query_diagnostic_counters(struct mlx5_core_dev *mdev, 1066 u8 num_of_samples, u16 sample_index, 1067 void *out, int out_size) 1068{ 1069 u32 in[MLX5_ST_SZ_DW(query_diagnostic_counters_in)] = {0}; 1070 1071 MLX5_SET(query_diagnostic_counters_in, in, opcode, 1072 MLX5_CMD_OP_QUERY_DIAGNOSTICS); 1073 MLX5_SET(query_diagnostic_counters_in, in, num_of_samples, 1074 num_of_samples); 1075 MLX5_SET(query_diagnostic_counters_in, in, sample_index, sample_index); 1076 1077 return mlx5_cmd_exec(mdev, in, sizeof(in), out, out_size); 1078} 1079 1080int mlx5_set_trust_state(struct mlx5_core_dev *mdev, u8 trust_state) 1081{ 1082 u32 out[MLX5_ST_SZ_DW(qpts_reg)] = {}; 1083 u32 in[MLX5_ST_SZ_DW(qpts_reg)] = {}; 1084 int err; 1085 1086 MLX5_SET(qpts_reg, in, local_port, 1); 1087 MLX5_SET(qpts_reg, in, trust_state, trust_state); 1088 1089 err = mlx5_core_access_reg(mdev, in, sizeof(in), out, 1090 sizeof(out), MLX5_REG_QPTS, 0, 1); 1091 return err; 1092} 1093 1094int mlx5_query_trust_state(struct mlx5_core_dev *mdev, u8 *trust_state) 1095{ 1096 u32 out[MLX5_ST_SZ_DW(qpts_reg)] = {}; 1097 u32 in[MLX5_ST_SZ_DW(qpts_reg)] = {}; 1098 int err; 1099 1100 MLX5_SET(qpts_reg, in, local_port, 1); 1101 1102 err = mlx5_core_access_reg(mdev, in, sizeof(in), out, 1103 sizeof(out), MLX5_REG_QPTS, 0, 0); 1104 if (!err) 1105 *trust_state = MLX5_GET(qpts_reg, out, trust_state); 1106 1107 return err; 1108} 1109 1110int mlx5_set_dscp2prio(struct mlx5_core_dev *mdev, const u8 *dscp2prio) 1111{ 1112 int sz = MLX5_ST_SZ_BYTES(qpdpm_reg); 1113 void *qpdpm_dscp; 1114 void *out; 1115 void *in; 1116 int err; 1117 int i; 1118 1119 in = kzalloc(sz, GFP_KERNEL); 1120 out = kzalloc(sz, GFP_KERNEL); 1121 if (!in || !out) { 1122 err = -ENOMEM; 1123 goto out; 1124 } 1125 1126 MLX5_SET(qpdpm_reg, in, local_port, 1); 1127 err = mlx5_core_access_reg(mdev, in, sz, out, sz, MLX5_REG_QPDPM, 0, 0); 1128 if (err) 1129 goto out; 1130 1131 memcpy(in, out, sz); 1132 MLX5_SET(qpdpm_reg, in, local_port, 1); 1133 1134 /* Update the corresponding dscp entry */ 1135 for (i = 0; i < MLX5_MAX_SUPPORTED_DSCP; i++) { 1136 qpdpm_dscp = MLX5_ADDR_OF(qpdpm_reg, in, dscp[i]); 1137 MLX5_SET16(qpdpm_dscp_reg, qpdpm_dscp, prio, dscp2prio[i]); 1138 MLX5_SET16(qpdpm_dscp_reg, qpdpm_dscp, e, 1); 1139 } 1140 err = mlx5_core_access_reg(mdev, in, sz, out, sz, MLX5_REG_QPDPM, 0, 1); 1141out: 1142 kfree(in); 1143 kfree(out); 1144 return err; 1145} 1146 1147int mlx5_query_dscp2prio(struct mlx5_core_dev *mdev, u8 *dscp2prio) 1148{ 1149 int sz = MLX5_ST_SZ_BYTES(qpdpm_reg); 1150 void *qpdpm_dscp; 1151 void *out; 1152 void *in; 1153 int err; 1154 int i; 1155 1156 in = kzalloc(sz, GFP_KERNEL); 1157 out = kzalloc(sz, GFP_KERNEL); 1158 if (!in || !out) { 1159 err = -ENOMEM; 1160 goto out; 1161 } 1162 1163 MLX5_SET(qpdpm_reg, in, local_port, 1); 1164 err = mlx5_core_access_reg(mdev, in, sz, out, sz, MLX5_REG_QPDPM, 0, 0); 1165 if (err) 1166 goto out; 1167 1168 for (i = 0; i < MLX5_MAX_SUPPORTED_DSCP; i++) { 1169 qpdpm_dscp = MLX5_ADDR_OF(qpdpm_reg, out, dscp[i]); 1170 dscp2prio[i] = MLX5_GET16(qpdpm_dscp_reg, qpdpm_dscp, prio); 1171 } 1172out: 1173 kfree(in); 1174 kfree(out); 1175 return err; 1176} 1177 1178int mlx5_query_pddr_range_info(struct mlx5_core_dev *mdev, u8 local_port, u8 *is_er_type) 1179{ 1180 u32 pddr_reg[MLX5_ST_SZ_DW(pddr_reg)] = {}; 1181 int sz = MLX5_ST_SZ_BYTES(pddr_reg); 1182 int error; 1183 u8 ecc; 1184 u8 ci; 1185 1186 MLX5_SET(pddr_reg, pddr_reg, local_port, local_port); 1187 MLX5_SET(pddr_reg, pddr_reg, page_select, 3 /* module info page */); 1188 1189 error = mlx5_core_access_reg(mdev, pddr_reg, sz, pddr_reg, sz, 1190 MLX5_ACCESS_REG_SUMMARY_CTRL_ID_PDDR, 0, 0); 1191 if (error != 0) 1192 return (error); 1193 1194 ecc = MLX5_GET(pddr_reg, pddr_reg, page_data.pddr_module_info.ethernet_compliance_code); 1195 ci = MLX5_GET(pddr_reg, pddr_reg, page_data.pddr_module_info.cable_identifier); 1196 1197 switch (ci) { 1198 case 0: /* QSFP28 */ 1199 case 1: /* QSFP+ */ 1200 *is_er_type = 0; 1201 break; 1202 case 2: /* SFP28/SFP+ */ 1203 case 3: /* QSA (QSFP->SFP) */ 1204 *is_er_type = ((ecc & (1 << 7)) != 0); 1205 break; 1206 default: 1207 *is_er_type = 0; 1208 break; 1209 } 1210 return (0); 1211} 1212EXPORT_SYMBOL_GPL(mlx5_query_pddr_range_info); 1213 1214int 1215mlx5_query_mfrl_reg(struct mlx5_core_dev *mdev, u8 *reset_level) 1216{ 1217 u32 mfrl[MLX5_ST_SZ_DW(mfrl_reg)] = {}; 1218 int sz = MLX5_ST_SZ_BYTES(mfrl_reg); 1219 int err; 1220 1221 err = mlx5_core_access_reg(mdev, mfrl, sz, mfrl, sz, MLX5_REG_MFRL, 1222 0, 0); 1223 if (err == 0) 1224 *reset_level = MLX5_GET(mfrl_reg, mfrl, reset_level); 1225 return (err); 1226} 1227 1228int 1229mlx5_set_mfrl_reg(struct mlx5_core_dev *mdev, u8 reset_level) 1230{ 1231 u32 mfrl[MLX5_ST_SZ_DW(mfrl_reg)] = {}; 1232 int sz = MLX5_ST_SZ_BYTES(mfrl_reg); 1233 1234 MLX5_SET(mfrl_reg, mfrl, reset_level, reset_level); 1235 1236 return (mlx5_core_access_reg(mdev, mfrl, sz, mfrl, sz, MLX5_REG_MFRL, 1237 0, 1)); 1238} 1239