FILE
cmd.c
File preview with syntax highlighting.
linux-6.19.14/drivers/net/ethernet/mellanox/mlx5/core/cmd.c
1/* 2 * Copyright (c) 2013-2016, Mellanox Technologies. All rights reserved. 3 * 4 * This software is available to you under a choice of one of two 5 * licenses. You may choose to be licensed under the terms of the GNU 6 * General Public License (GPL) Version 2, available from the file 7 * COPYING in the main directory of this source tree, or the 8 * OpenIB.org BSD license below: 9 * 10 * Redistribution and use in source and binary forms, with or 11 * without modification, are permitted provided that the following 12 * conditions are met: 13 * 14 * - Redistributions of source code must retain the above 15 * copyright notice, this list of conditions and the following 16 * disclaimer. 17 * 18 * - Redistributions in binary form must reproduce the above 19 * copyright notice, this list of conditions and the following 20 * disclaimer in the documentation and/or other materials 21 * provided with the distribution. 22 * 23 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 24 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 25 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 26 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 27 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 28 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 29 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 30 * SOFTWARE. 31 */ 32 33#include <linux/highmem.h> 34#include <linux/errno.h> 35#include <linux/pci.h> 36#include <linux/dma-mapping.h> 37#include <linux/slab.h> 38#include <linux/delay.h> 39#include <linux/random.h> 40#include <linux/mlx5/driver.h> 41#include <linux/mlx5/eq.h> 42#include <linux/debugfs.h> 43 44#include "mlx5_core.h" 45#include "lib/eq.h" 46#include "lib/tout.h" 47#define CREATE_TRACE_POINTS 48#include "diag/cmd_tracepoint.h" 49 50struct mlx5_ifc_mbox_out_bits { 51 u8 status[0x8]; 52 u8 reserved_at_8[0x18]; 53 54 u8 syndrome[0x20]; 55 56 u8 reserved_at_40[0x40]; 57}; 58 59struct mlx5_ifc_mbox_in_bits { 60 u8 opcode[0x10]; 61 u8 uid[0x10]; 62 63 u8 reserved_at_20[0x10]; 64 u8 op_mod[0x10]; 65 66 u8 reserved_at_40[0x40]; 67}; 68 69enum { 70 CMD_IF_REV = 5, 71}; 72 73enum { 74 CMD_MODE_POLLING, 75 CMD_MODE_EVENTS 76}; 77 78enum { 79 MLX5_CMD_DELIVERY_STAT_OK = 0x0, 80 MLX5_CMD_DELIVERY_STAT_SIGNAT_ERR = 0x1, 81 MLX5_CMD_DELIVERY_STAT_TOK_ERR = 0x2, 82 MLX5_CMD_DELIVERY_STAT_BAD_BLK_NUM_ERR = 0x3, 83 MLX5_CMD_DELIVERY_STAT_OUT_PTR_ALIGN_ERR = 0x4, 84 MLX5_CMD_DELIVERY_STAT_IN_PTR_ALIGN_ERR = 0x5, 85 MLX5_CMD_DELIVERY_STAT_FW_ERR = 0x6, 86 MLX5_CMD_DELIVERY_STAT_IN_LENGTH_ERR = 0x7, 87 MLX5_CMD_DELIVERY_STAT_OUT_LENGTH_ERR = 0x8, 88 MLX5_CMD_DELIVERY_STAT_RES_FLD_NOT_CLR_ERR = 0x9, 89 MLX5_CMD_DELIVERY_STAT_CMD_DESCR_ERR = 0x10, 90}; 91 92static u16 in_to_opcode(void *in) 93{ 94 return MLX5_GET(mbox_in, in, opcode); 95} 96 97static u16 in_to_uid(void *in) 98{ 99 return MLX5_GET(mbox_in, in, uid); 100} 101 102/* Returns true for opcodes that might be triggered very frequently and throttle 103 * the command interface. Limit their command slots usage. 104 */ 105static bool mlx5_cmd_is_throttle_opcode(u16 op) 106{ 107 switch (op) { 108 case MLX5_CMD_OP_CREATE_GENERAL_OBJECT: 109 case MLX5_CMD_OP_DESTROY_GENERAL_OBJECT: 110 case MLX5_CMD_OP_MODIFY_GENERAL_OBJECT: 111 case MLX5_CMD_OP_QUERY_GENERAL_OBJECT: 112 case MLX5_CMD_OP_SYNC_CRYPTO: 113 return true; 114 } 115 return false; 116} 117 118static struct mlx5_cmd_work_ent * 119cmd_alloc_ent(struct mlx5_cmd *cmd, struct mlx5_cmd_msg *in, 120 struct mlx5_cmd_msg *out, void *uout, int uout_size, 121 mlx5_cmd_cbk_t cbk, void *context, int page_queue) 122{ 123 gfp_t alloc_flags = cbk ? GFP_ATOMIC : GFP_KERNEL; 124 struct mlx5_cmd_work_ent *ent; 125 126 ent = kzalloc(sizeof(*ent), alloc_flags); 127 if (!ent) 128 return ERR_PTR(-ENOMEM); 129 130 ent->idx = -EINVAL; 131 ent->in = in; 132 ent->out = out; 133 ent->uout = uout; 134 ent->uout_size = uout_size; 135 ent->callback = cbk; 136 ent->context = context; 137 ent->cmd = cmd; 138 ent->page_queue = page_queue; 139 ent->op = in_to_opcode(in->first.data); 140 refcount_set(&ent->refcnt, 1); 141 142 return ent; 143} 144 145static void cmd_free_ent(struct mlx5_cmd_work_ent *ent) 146{ 147 kfree(ent); 148} 149 150static u8 alloc_token(struct mlx5_cmd *cmd) 151{ 152 u8 token; 153 154 spin_lock(&cmd->token_lock); 155 cmd->token++; 156 if (cmd->token == 0) 157 cmd->token++; 158 token = cmd->token; 159 spin_unlock(&cmd->token_lock); 160 161 return token; 162} 163 164static int cmd_alloc_index(struct mlx5_cmd *cmd, struct mlx5_cmd_work_ent *ent) 165{ 166 unsigned long flags; 167 int ret; 168 169 spin_lock_irqsave(&cmd->alloc_lock, flags); 170 ret = find_first_bit(&cmd->vars.bitmask, cmd->vars.max_reg_cmds); 171 if (ret < cmd->vars.max_reg_cmds) { 172 clear_bit(ret, &cmd->vars.bitmask); 173 ent->idx = ret; 174 cmd->ent_arr[ent->idx] = ent; 175 } 176 spin_unlock_irqrestore(&cmd->alloc_lock, flags); 177 178 return ret < cmd->vars.max_reg_cmds ? ret : -ENOMEM; 179} 180 181static void cmd_free_index(struct mlx5_cmd *cmd, int idx) 182{ 183 lockdep_assert_held(&cmd->alloc_lock); 184 cmd->ent_arr[idx] = NULL; 185 set_bit(idx, &cmd->vars.bitmask); 186} 187 188static void cmd_ent_get(struct mlx5_cmd_work_ent *ent) 189{ 190 refcount_inc(&ent->refcnt); 191} 192 193static void cmd_ent_put(struct mlx5_cmd_work_ent *ent) 194{ 195 struct mlx5_cmd *cmd = ent->cmd; 196 unsigned long flags; 197 198 spin_lock_irqsave(&cmd->alloc_lock, flags); 199 if (!refcount_dec_and_test(&ent->refcnt)) 200 goto out; 201 202 if (ent->idx >= 0) { 203 cmd_free_index(cmd, ent->idx); 204 up(ent->page_queue ? &cmd->vars.pages_sem : &cmd->vars.sem); 205 } 206 207 cmd_free_ent(ent); 208out: 209 spin_unlock_irqrestore(&cmd->alloc_lock, flags); 210} 211 212static struct mlx5_cmd_layout *get_inst(struct mlx5_cmd *cmd, int idx) 213{ 214 return cmd->cmd_buf + (idx << cmd->vars.log_stride); 215} 216 217static int mlx5_calc_cmd_blocks(struct mlx5_cmd_msg *msg) 218{ 219 int size = msg->len; 220 int blen = size - min_t(int, sizeof(msg->first.data), size); 221 222 return DIV_ROUND_UP(blen, MLX5_CMD_DATA_BLOCK_SIZE); 223} 224 225static u8 xor8_buf(void *buf, size_t offset, int len) 226{ 227 u8 *ptr = buf; 228 u8 sum = 0; 229 int i; 230 int end = len + offset; 231 232 for (i = offset; i < end; i++) 233 sum ^= ptr[i]; 234 235 return sum; 236} 237 238static int verify_block_sig(struct mlx5_cmd_prot_block *block) 239{ 240 size_t rsvd0_off = offsetof(struct mlx5_cmd_prot_block, rsvd0); 241 int xor_len = sizeof(*block) - sizeof(block->data) - 1; 242 243 if (xor8_buf(block, rsvd0_off, xor_len) != 0xff) 244 return -EHWPOISON; 245 246 if (xor8_buf(block, 0, sizeof(*block)) != 0xff) 247 return -EHWPOISON; 248 249 return 0; 250} 251 252static void calc_block_sig(struct mlx5_cmd_prot_block *block) 253{ 254 int ctrl_xor_len = sizeof(*block) - sizeof(block->data) - 2; 255 size_t rsvd0_off = offsetof(struct mlx5_cmd_prot_block, rsvd0); 256 257 block->ctrl_sig = ~xor8_buf(block, rsvd0_off, ctrl_xor_len); 258 block->sig = ~xor8_buf(block, 0, sizeof(*block) - 1); 259} 260 261static void calc_chain_sig(struct mlx5_cmd_msg *msg) 262{ 263 struct mlx5_cmd_mailbox *next = msg->next; 264 int n = mlx5_calc_cmd_blocks(msg); 265 int i = 0; 266 267 for (i = 0; i < n && next; i++) { 268 calc_block_sig(next->buf); 269 next = next->next; 270 } 271} 272 273static void set_signature(struct mlx5_cmd_work_ent *ent, int csum) 274{ 275 ent->lay->sig = ~xor8_buf(ent->lay, 0, sizeof(*ent->lay)); 276 if (csum) { 277 calc_chain_sig(ent->in); 278 calc_chain_sig(ent->out); 279 } 280} 281 282static void poll_timeout(struct mlx5_cmd_work_ent *ent) 283{ 284 struct mlx5_core_dev *dev = container_of(ent->cmd, struct mlx5_core_dev, cmd); 285 u64 cmd_to_ms = mlx5_tout_ms(dev, CMD); 286 unsigned long poll_end; 287 u8 own; 288 289 poll_end = jiffies + msecs_to_jiffies(cmd_to_ms + 1000); 290 291 do { 292 own = READ_ONCE(ent->lay->status_own); 293 if (!(own & CMD_OWNER_HW)) { 294 ent->ret = 0; 295 return; 296 } 297 cond_resched(); 298 if (mlx5_cmd_is_down(dev)) { 299 ent->ret = -ENXIO; 300 return; 301 } 302 } while (time_before(jiffies, poll_end)); 303 304 ent->ret = -ETIMEDOUT; 305} 306 307static int verify_signature(struct mlx5_cmd_work_ent *ent) 308{ 309 struct mlx5_cmd_mailbox *next = ent->out->next; 310 int n = mlx5_calc_cmd_blocks(ent->out); 311 int err; 312 u8 sig; 313 int i = 0; 314 315 sig = xor8_buf(ent->lay, 0, sizeof(*ent->lay)); 316 if (sig != 0xff) 317 return -EHWPOISON; 318 319 for (i = 0; i < n && next; i++) { 320 err = verify_block_sig(next->buf); 321 if (err) 322 return -EHWPOISON; 323 324 next = next->next; 325 } 326 327 return 0; 328} 329 330static void dump_buf(void *buf, int size, int data_only, int offset, int idx) 331{ 332 __be32 *p = buf; 333 int i; 334 335 for (i = 0; i < size; i += 16) { 336 pr_debug("cmd[%d]: %03x: %08x %08x %08x %08x\n", idx, offset, 337 be32_to_cpu(p[0]), be32_to_cpu(p[1]), 338 be32_to_cpu(p[2]), be32_to_cpu(p[3])); 339 p += 4; 340 offset += 16; 341 } 342 if (!data_only) 343 pr_debug("\n"); 344} 345 346static int mlx5_internal_err_ret_value(struct mlx5_core_dev *dev, u16 op, 347 u32 *synd, u8 *status) 348{ 349 *synd = 0; 350 *status = 0; 351 352 switch (op) { 353 case MLX5_CMD_OP_TEARDOWN_HCA: 354 case MLX5_CMD_OP_DISABLE_HCA: 355 case MLX5_CMD_OP_MANAGE_PAGES: 356 case MLX5_CMD_OP_DESTROY_MKEY: 357 case MLX5_CMD_OP_DESTROY_EQ: 358 case MLX5_CMD_OP_DESTROY_CQ: 359 case MLX5_CMD_OP_DESTROY_QP: 360 case MLX5_CMD_OP_DESTROY_PSV: 361 case MLX5_CMD_OP_DESTROY_SRQ: 362 case MLX5_CMD_OP_DESTROY_XRC_SRQ: 363 case MLX5_CMD_OP_DESTROY_XRQ: 364 case MLX5_CMD_OP_DESTROY_DCT: 365 case MLX5_CMD_OP_DEALLOC_Q_COUNTER: 366 case MLX5_CMD_OP_DESTROY_SCHEDULING_ELEMENT: 367 case MLX5_CMD_OP_DESTROY_QOS_PARA_VPORT: 368 case MLX5_CMD_OP_DEALLOC_PD: 369 case MLX5_CMD_OP_DEALLOC_UAR: 370 case MLX5_CMD_OP_DETACH_FROM_MCG: 371 case MLX5_CMD_OP_DEALLOC_XRCD: 372 case MLX5_CMD_OP_DEALLOC_TRANSPORT_DOMAIN: 373 case MLX5_CMD_OP_DELETE_VXLAN_UDP_DPORT: 374 case MLX5_CMD_OP_DELETE_L2_TABLE_ENTRY: 375 case MLX5_CMD_OP_DESTROY_LAG: 376 case MLX5_CMD_OP_DESTROY_VPORT_LAG: 377 case MLX5_CMD_OP_DESTROY_TIR: 378 case MLX5_CMD_OP_DESTROY_SQ: 379 case MLX5_CMD_OP_DESTROY_RQ: 380 case MLX5_CMD_OP_DESTROY_RMP: 381 case MLX5_CMD_OP_DESTROY_TIS: 382 case MLX5_CMD_OP_DESTROY_RQT: 383 case MLX5_CMD_OP_DESTROY_FLOW_TABLE: 384 case MLX5_CMD_OP_DESTROY_FLOW_GROUP: 385 case MLX5_CMD_OP_DELETE_FLOW_TABLE_ENTRY: 386 case MLX5_CMD_OP_DEALLOC_FLOW_COUNTER: 387 case MLX5_CMD_OP_2ERR_QP: 388 case MLX5_CMD_OP_2RST_QP: 389 case MLX5_CMD_OP_MODIFY_NIC_VPORT_CONTEXT: 390 case MLX5_CMD_OP_MODIFY_FLOW_TABLE: 391 case MLX5_CMD_OP_SET_FLOW_TABLE_ENTRY: 392 case MLX5_CMD_OP_SET_FLOW_TABLE_ROOT: 393 case MLX5_CMD_OP_DEALLOC_PACKET_REFORMAT_CONTEXT: 394 case MLX5_CMD_OP_DEALLOC_MODIFY_HEADER_CONTEXT: 395 case MLX5_CMD_OP_FPGA_DESTROY_QP: 396 case MLX5_CMD_OP_DESTROY_GENERAL_OBJECT: 397 case MLX5_CMD_OP_DEALLOC_MEMIC: 398 case MLX5_CMD_OP_PAGE_FAULT_RESUME: 399 case MLX5_CMD_OP_QUERY_ESW_FUNCTIONS: 400 case MLX5_CMD_OP_DEALLOC_SF: 401 case MLX5_CMD_OP_DESTROY_UCTX: 402 case MLX5_CMD_OP_DESTROY_UMEM: 403 case MLX5_CMD_OP_MODIFY_RQT: 404 return MLX5_CMD_STAT_OK; 405 406 case MLX5_CMD_OP_QUERY_HCA_CAP: 407 case MLX5_CMD_OP_QUERY_ADAPTER: 408 case MLX5_CMD_OP_INIT_HCA: 409 case MLX5_CMD_OP_ENABLE_HCA: 410 case MLX5_CMD_OP_QUERY_PAGES: 411 case MLX5_CMD_OP_SET_HCA_CAP: 412 case MLX5_CMD_OP_QUERY_ISSI: 413 case MLX5_CMD_OP_SET_ISSI: 414 case MLX5_CMD_OP_CREATE_MKEY: 415 case MLX5_CMD_OP_QUERY_MKEY: 416 case MLX5_CMD_OP_QUERY_SPECIAL_CONTEXTS: 417 case MLX5_CMD_OP_CREATE_EQ: 418 case MLX5_CMD_OP_QUERY_EQ: 419 case MLX5_CMD_OP_GEN_EQE: 420 case MLX5_CMD_OP_CREATE_CQ: 421 case MLX5_CMD_OP_QUERY_CQ: 422 case MLX5_CMD_OP_MODIFY_CQ: 423 case MLX5_CMD_OP_CREATE_QP: 424 case MLX5_CMD_OP_RST2INIT_QP: 425 case MLX5_CMD_OP_INIT2RTR_QP: 426 case MLX5_CMD_OP_RTR2RTS_QP: 427 case MLX5_CMD_OP_RTS2RTS_QP: 428 case MLX5_CMD_OP_SQERR2RTS_QP: 429 case MLX5_CMD_OP_QUERY_QP: 430 case MLX5_CMD_OP_SQD_RTS_QP: 431 case MLX5_CMD_OP_INIT2INIT_QP: 432 case MLX5_CMD_OP_CREATE_PSV: 433 case MLX5_CMD_OP_CREATE_SRQ: 434 case MLX5_CMD_OP_QUERY_SRQ: 435 case MLX5_CMD_OP_ARM_RQ: 436 case MLX5_CMD_OP_CREATE_XRC_SRQ: 437 case MLX5_CMD_OP_QUERY_XRC_SRQ: 438 case MLX5_CMD_OP_ARM_XRC_SRQ: 439 case MLX5_CMD_OP_CREATE_XRQ: 440 case MLX5_CMD_OP_QUERY_XRQ: 441 case MLX5_CMD_OP_ARM_XRQ: 442 case MLX5_CMD_OP_CREATE_DCT: 443 case MLX5_CMD_OP_DRAIN_DCT: 444 case MLX5_CMD_OP_QUERY_DCT: 445 case MLX5_CMD_OP_ARM_DCT_FOR_KEY_VIOLATION: 446 case MLX5_CMD_OP_QUERY_VPORT_STATE: 447 case MLX5_CMD_OP_MODIFY_VPORT_STATE: 448 case MLX5_CMD_OP_QUERY_ESW_VPORT_CONTEXT: 449 case MLX5_CMD_OP_MODIFY_ESW_VPORT_CONTEXT: 450 case MLX5_CMD_OP_QUERY_NIC_VPORT_CONTEXT: 451 case MLX5_CMD_OP_QUERY_ROCE_ADDRESS: 452 case MLX5_CMD_OP_SET_ROCE_ADDRESS: 453 case MLX5_CMD_OP_QUERY_HCA_VPORT_CONTEXT: 454 case MLX5_CMD_OP_MODIFY_HCA_VPORT_CONTEXT: 455 case MLX5_CMD_OP_QUERY_HCA_VPORT_GID: 456 case MLX5_CMD_OP_QUERY_HCA_VPORT_PKEY: 457 case MLX5_CMD_OP_QUERY_VNIC_ENV: 458 case MLX5_CMD_OP_QUERY_VPORT_COUNTER: 459 case MLX5_CMD_OP_ALLOC_Q_COUNTER: 460 case MLX5_CMD_OP_QUERY_Q_COUNTER: 461 case MLX5_CMD_OP_SET_MONITOR_COUNTER: 462 case MLX5_CMD_OP_ARM_MONITOR_COUNTER: 463 case MLX5_CMD_OP_SET_PP_RATE_LIMIT: 464 case MLX5_CMD_OP_QUERY_RATE_LIMIT: 465 case MLX5_CMD_OP_CREATE_SCHEDULING_ELEMENT: 466 case MLX5_CMD_OP_QUERY_SCHEDULING_ELEMENT: 467 case MLX5_CMD_OP_MODIFY_SCHEDULING_ELEMENT: 468 case MLX5_CMD_OP_CREATE_QOS_PARA_VPORT: 469 case MLX5_CMD_OP_ALLOC_PD: 470 case MLX5_CMD_OP_ALLOC_UAR: 471 case MLX5_CMD_OP_CONFIG_INT_MODERATION: 472 case MLX5_CMD_OP_ACCESS_REG: 473 case MLX5_CMD_OP_ATTACH_TO_MCG: 474 case MLX5_CMD_OP_GET_DROPPED_PACKET_LOG: 475 case MLX5_CMD_OP_MAD_IFC: 476 case MLX5_CMD_OP_QUERY_MAD_DEMUX: 477 case MLX5_CMD_OP_SET_MAD_DEMUX: 478 case MLX5_CMD_OP_NOP: 479 case MLX5_CMD_OP_ALLOC_XRCD: 480 case MLX5_CMD_OP_ALLOC_TRANSPORT_DOMAIN: 481 case MLX5_CMD_OP_QUERY_CONG_STATUS: 482 case MLX5_CMD_OP_MODIFY_CONG_STATUS: 483 case MLX5_CMD_OP_QUERY_CONG_PARAMS: 484 case MLX5_CMD_OP_MODIFY_CONG_PARAMS: 485 case MLX5_CMD_OP_QUERY_CONG_STATISTICS: 486 case MLX5_CMD_OP_ADD_VXLAN_UDP_DPORT: 487 case MLX5_CMD_OP_SET_L2_TABLE_ENTRY: 488 case MLX5_CMD_OP_QUERY_L2_TABLE_ENTRY: 489 case MLX5_CMD_OP_CREATE_LAG: 490 case MLX5_CMD_OP_MODIFY_LAG: 491 case MLX5_CMD_OP_QUERY_LAG: 492 case MLX5_CMD_OP_CREATE_VPORT_LAG: 493 case MLX5_CMD_OP_CREATE_TIR: 494 case MLX5_CMD_OP_MODIFY_TIR: 495 case MLX5_CMD_OP_QUERY_TIR: 496 case MLX5_CMD_OP_CREATE_SQ: 497 case MLX5_CMD_OP_MODIFY_SQ: 498 case MLX5_CMD_OP_QUERY_SQ: 499 case MLX5_CMD_OP_CREATE_RQ: 500 case MLX5_CMD_OP_MODIFY_RQ: 501 case MLX5_CMD_OP_QUERY_RQ: 502 case MLX5_CMD_OP_CREATE_RMP: 503 case MLX5_CMD_OP_MODIFY_RMP: 504 case MLX5_CMD_OP_QUERY_RMP: 505 case MLX5_CMD_OP_CREATE_TIS: 506 case MLX5_CMD_OP_MODIFY_TIS: 507 case MLX5_CMD_OP_QUERY_TIS: 508 case MLX5_CMD_OP_CREATE_RQT: 509 case MLX5_CMD_OP_QUERY_RQT: 510 511 case MLX5_CMD_OP_CREATE_FLOW_TABLE: 512 case MLX5_CMD_OP_QUERY_FLOW_TABLE: 513 case MLX5_CMD_OP_CREATE_FLOW_GROUP: 514 case MLX5_CMD_OP_QUERY_FLOW_GROUP: 515 case MLX5_CMD_OP_QUERY_FLOW_TABLE_ENTRY: 516 case MLX5_CMD_OP_ALLOC_FLOW_COUNTER: 517 case MLX5_CMD_OP_QUERY_FLOW_COUNTER: 518 case MLX5_CMD_OP_ALLOC_PACKET_REFORMAT_CONTEXT: 519 case MLX5_CMD_OP_ALLOC_MODIFY_HEADER_CONTEXT: 520 case MLX5_CMD_OP_FPGA_CREATE_QP: 521 case MLX5_CMD_OP_FPGA_MODIFY_QP: 522 case MLX5_CMD_OP_FPGA_QUERY_QP: 523 case MLX5_CMD_OP_FPGA_QUERY_QP_COUNTERS: 524 case MLX5_CMD_OP_CREATE_GENERAL_OBJECT: 525 case MLX5_CMD_OP_MODIFY_GENERAL_OBJECT: 526 case MLX5_CMD_OP_QUERY_GENERAL_OBJECT: 527 case MLX5_CMD_OP_CREATE_UCTX: 528 case MLX5_CMD_OP_CREATE_UMEM: 529 case MLX5_CMD_OP_ALLOC_MEMIC: 530 case MLX5_CMD_OP_MODIFY_XRQ: 531 case MLX5_CMD_OP_RELEASE_XRQ_ERROR: 532 case MLX5_CMD_OP_QUERY_VHCA_STATE: 533 case MLX5_CMD_OP_MODIFY_VHCA_STATE: 534 case MLX5_CMD_OP_ALLOC_SF: 535 case MLX5_CMD_OP_SUSPEND_VHCA: 536 case MLX5_CMD_OP_RESUME_VHCA: 537 case MLX5_CMD_OP_QUERY_VHCA_MIGRATION_STATE: 538 case MLX5_CMD_OP_SAVE_VHCA_STATE: 539 case MLX5_CMD_OP_LOAD_VHCA_STATE: 540 case MLX5_CMD_OP_SYNC_CRYPTO: 541 case MLX5_CMD_OP_ALLOW_OTHER_VHCA_ACCESS: 542 *status = MLX5_DRIVER_STATUS_ABORTED; 543 *synd = MLX5_DRIVER_SYND; 544 return -ENOLINK; 545 default: 546 mlx5_core_err(dev, "Unknown FW command (%d)\n", op); 547 return -EINVAL; 548 } 549} 550 551const char *mlx5_command_str(int command) 552{ 553#define MLX5_COMMAND_STR_CASE(__cmd) case MLX5_CMD_OP_ ## __cmd: return #__cmd 554 555 switch (command) { 556 MLX5_COMMAND_STR_CASE(QUERY_HCA_CAP); 557 MLX5_COMMAND_STR_CASE(QUERY_ADAPTER); 558 MLX5_COMMAND_STR_CASE(INIT_HCA); 559 MLX5_COMMAND_STR_CASE(TEARDOWN_HCA); 560 MLX5_COMMAND_STR_CASE(ENABLE_HCA); 561 MLX5_COMMAND_STR_CASE(DISABLE_HCA); 562 MLX5_COMMAND_STR_CASE(QUERY_PAGES); 563 MLX5_COMMAND_STR_CASE(MANAGE_PAGES); 564 MLX5_COMMAND_STR_CASE(SET_HCA_CAP); 565 MLX5_COMMAND_STR_CASE(QUERY_ISSI); 566 MLX5_COMMAND_STR_CASE(SET_ISSI); 567 MLX5_COMMAND_STR_CASE(SET_DRIVER_VERSION); 568 MLX5_COMMAND_STR_CASE(CREATE_MKEY); 569 MLX5_COMMAND_STR_CASE(QUERY_MKEY); 570 MLX5_COMMAND_STR_CASE(DESTROY_MKEY); 571 MLX5_COMMAND_STR_CASE(QUERY_SPECIAL_CONTEXTS); 572 MLX5_COMMAND_STR_CASE(PAGE_FAULT_RESUME); 573 MLX5_COMMAND_STR_CASE(CREATE_EQ); 574 MLX5_COMMAND_STR_CASE(DESTROY_EQ); 575 MLX5_COMMAND_STR_CASE(QUERY_EQ); 576 MLX5_COMMAND_STR_CASE(GEN_EQE); 577 MLX5_COMMAND_STR_CASE(CREATE_CQ); 578 MLX5_COMMAND_STR_CASE(DESTROY_CQ); 579 MLX5_COMMAND_STR_CASE(QUERY_CQ); 580 MLX5_COMMAND_STR_CASE(MODIFY_CQ); 581 MLX5_COMMAND_STR_CASE(CREATE_QP); 582 MLX5_COMMAND_STR_CASE(DESTROY_QP); 583 MLX5_COMMAND_STR_CASE(RST2INIT_QP); 584 MLX5_COMMAND_STR_CASE(INIT2RTR_QP); 585 MLX5_COMMAND_STR_CASE(RTR2RTS_QP); 586 MLX5_COMMAND_STR_CASE(RTS2RTS_QP); 587 MLX5_COMMAND_STR_CASE(SQERR2RTS_QP); 588 MLX5_COMMAND_STR_CASE(2ERR_QP); 589 MLX5_COMMAND_STR_CASE(2RST_QP); 590 MLX5_COMMAND_STR_CASE(QUERY_QP); 591 MLX5_COMMAND_STR_CASE(SQD_RTS_QP); 592 MLX5_COMMAND_STR_CASE(INIT2INIT_QP); 593 MLX5_COMMAND_STR_CASE(CREATE_PSV); 594 MLX5_COMMAND_STR_CASE(DESTROY_PSV); 595 MLX5_COMMAND_STR_CASE(CREATE_SRQ); 596 MLX5_COMMAND_STR_CASE(DESTROY_SRQ); 597 MLX5_COMMAND_STR_CASE(QUERY_SRQ); 598 MLX5_COMMAND_STR_CASE(ARM_RQ); 599 MLX5_COMMAND_STR_CASE(CREATE_XRC_SRQ); 600 MLX5_COMMAND_STR_CASE(DESTROY_XRC_SRQ); 601 MLX5_COMMAND_STR_CASE(QUERY_XRC_SRQ); 602 MLX5_COMMAND_STR_CASE(ARM_XRC_SRQ); 603 MLX5_COMMAND_STR_CASE(CREATE_DCT); 604 MLX5_COMMAND_STR_CASE(DESTROY_DCT); 605 MLX5_COMMAND_STR_CASE(DRAIN_DCT); 606 MLX5_COMMAND_STR_CASE(QUERY_DCT); 607 MLX5_COMMAND_STR_CASE(ARM_DCT_FOR_KEY_VIOLATION); 608 MLX5_COMMAND_STR_CASE(QUERY_VPORT_STATE); 609 MLX5_COMMAND_STR_CASE(MODIFY_VPORT_STATE); 610 MLX5_COMMAND_STR_CASE(QUERY_ESW_VPORT_CONTEXT); 611 MLX5_COMMAND_STR_CASE(MODIFY_ESW_VPORT_CONTEXT); 612 MLX5_COMMAND_STR_CASE(QUERY_NIC_VPORT_CONTEXT); 613 MLX5_COMMAND_STR_CASE(MODIFY_NIC_VPORT_CONTEXT); 614 MLX5_COMMAND_STR_CASE(QUERY_ROCE_ADDRESS); 615 MLX5_COMMAND_STR_CASE(SET_ROCE_ADDRESS); 616 MLX5_COMMAND_STR_CASE(QUERY_HCA_VPORT_CONTEXT); 617 MLX5_COMMAND_STR_CASE(MODIFY_HCA_VPORT_CONTEXT); 618 MLX5_COMMAND_STR_CASE(QUERY_HCA_VPORT_GID); 619 MLX5_COMMAND_STR_CASE(QUERY_HCA_VPORT_PKEY); 620 MLX5_COMMAND_STR_CASE(QUERY_VNIC_ENV); 621 MLX5_COMMAND_STR_CASE(QUERY_VPORT_COUNTER); 622 MLX5_COMMAND_STR_CASE(ALLOC_Q_COUNTER); 623 MLX5_COMMAND_STR_CASE(DEALLOC_Q_COUNTER); 624 MLX5_COMMAND_STR_CASE(QUERY_Q_COUNTER); 625 MLX5_COMMAND_STR_CASE(SET_MONITOR_COUNTER); 626 MLX5_COMMAND_STR_CASE(ARM_MONITOR_COUNTER); 627 MLX5_COMMAND_STR_CASE(SET_PP_RATE_LIMIT); 628 MLX5_COMMAND_STR_CASE(QUERY_RATE_LIMIT); 629 MLX5_COMMAND_STR_CASE(CREATE_SCHEDULING_ELEMENT); 630 MLX5_COMMAND_STR_CASE(DESTROY_SCHEDULING_ELEMENT); 631 MLX5_COMMAND_STR_CASE(QUERY_SCHEDULING_ELEMENT); 632 MLX5_COMMAND_STR_CASE(MODIFY_SCHEDULING_ELEMENT); 633 MLX5_COMMAND_STR_CASE(CREATE_QOS_PARA_VPORT); 634 MLX5_COMMAND_STR_CASE(DESTROY_QOS_PARA_VPORT); 635 MLX5_COMMAND_STR_CASE(ALLOC_PD); 636 MLX5_COMMAND_STR_CASE(DEALLOC_PD); 637 MLX5_COMMAND_STR_CASE(ALLOC_UAR); 638 MLX5_COMMAND_STR_CASE(DEALLOC_UAR); 639 MLX5_COMMAND_STR_CASE(CONFIG_INT_MODERATION); 640 MLX5_COMMAND_STR_CASE(ACCESS_REG); 641 MLX5_COMMAND_STR_CASE(ATTACH_TO_MCG); 642 MLX5_COMMAND_STR_CASE(DETACH_FROM_MCG); 643 MLX5_COMMAND_STR_CASE(GET_DROPPED_PACKET_LOG); 644 MLX5_COMMAND_STR_CASE(MAD_IFC); 645 MLX5_COMMAND_STR_CASE(QUERY_MAD_DEMUX); 646 MLX5_COMMAND_STR_CASE(SET_MAD_DEMUX); 647 MLX5_COMMAND_STR_CASE(NOP); 648 MLX5_COMMAND_STR_CASE(ALLOC_XRCD); 649 MLX5_COMMAND_STR_CASE(DEALLOC_XRCD); 650 MLX5_COMMAND_STR_CASE(ALLOC_TRANSPORT_DOMAIN); 651 MLX5_COMMAND_STR_CASE(DEALLOC_TRANSPORT_DOMAIN); 652 MLX5_COMMAND_STR_CASE(QUERY_CONG_STATUS); 653 MLX5_COMMAND_STR_CASE(MODIFY_CONG_STATUS); 654 MLX5_COMMAND_STR_CASE(QUERY_CONG_PARAMS); 655 MLX5_COMMAND_STR_CASE(MODIFY_CONG_PARAMS); 656 MLX5_COMMAND_STR_CASE(QUERY_CONG_STATISTICS); 657 MLX5_COMMAND_STR_CASE(ADD_VXLAN_UDP_DPORT); 658 MLX5_COMMAND_STR_CASE(DELETE_VXLAN_UDP_DPORT); 659 MLX5_COMMAND_STR_CASE(SET_L2_TABLE_ENTRY); 660 MLX5_COMMAND_STR_CASE(QUERY_L2_TABLE_ENTRY); 661 MLX5_COMMAND_STR_CASE(DELETE_L2_TABLE_ENTRY); 662 MLX5_COMMAND_STR_CASE(SET_WOL_ROL); 663 MLX5_COMMAND_STR_CASE(QUERY_WOL_ROL); 664 MLX5_COMMAND_STR_CASE(CREATE_LAG); 665 MLX5_COMMAND_STR_CASE(MODIFY_LAG); 666 MLX5_COMMAND_STR_CASE(QUERY_LAG); 667 MLX5_COMMAND_STR_CASE(DESTROY_LAG); 668 MLX5_COMMAND_STR_CASE(CREATE_VPORT_LAG); 669 MLX5_COMMAND_STR_CASE(DESTROY_VPORT_LAG); 670 MLX5_COMMAND_STR_CASE(CREATE_TIR); 671 MLX5_COMMAND_STR_CASE(MODIFY_TIR); 672 MLX5_COMMAND_STR_CASE(DESTROY_TIR); 673 MLX5_COMMAND_STR_CASE(QUERY_TIR); 674 MLX5_COMMAND_STR_CASE(CREATE_SQ); 675 MLX5_COMMAND_STR_CASE(MODIFY_SQ); 676 MLX5_COMMAND_STR_CASE(DESTROY_SQ); 677 MLX5_COMMAND_STR_CASE(QUERY_SQ); 678 MLX5_COMMAND_STR_CASE(CREATE_RQ); 679 MLX5_COMMAND_STR_CASE(MODIFY_RQ); 680 MLX5_COMMAND_STR_CASE(DESTROY_RQ); 681 MLX5_COMMAND_STR_CASE(QUERY_RQ); 682 MLX5_COMMAND_STR_CASE(CREATE_RMP); 683 MLX5_COMMAND_STR_CASE(MODIFY_RMP); 684 MLX5_COMMAND_STR_CASE(DESTROY_RMP); 685 MLX5_COMMAND_STR_CASE(QUERY_RMP); 686 MLX5_COMMAND_STR_CASE(CREATE_TIS); 687 MLX5_COMMAND_STR_CASE(MODIFY_TIS); 688 MLX5_COMMAND_STR_CASE(DESTROY_TIS); 689 MLX5_COMMAND_STR_CASE(QUERY_TIS); 690 MLX5_COMMAND_STR_CASE(CREATE_RQT); 691 MLX5_COMMAND_STR_CASE(MODIFY_RQT); 692 MLX5_COMMAND_STR_CASE(DESTROY_RQT); 693 MLX5_COMMAND_STR_CASE(QUERY_RQT); 694 MLX5_COMMAND_STR_CASE(SET_FLOW_TABLE_ROOT); 695 MLX5_COMMAND_STR_CASE(CREATE_FLOW_TABLE); 696 MLX5_COMMAND_STR_CASE(DESTROY_FLOW_TABLE); 697 MLX5_COMMAND_STR_CASE(QUERY_FLOW_TABLE); 698 MLX5_COMMAND_STR_CASE(CREATE_FLOW_GROUP); 699 MLX5_COMMAND_STR_CASE(DESTROY_FLOW_GROUP); 700 MLX5_COMMAND_STR_CASE(QUERY_FLOW_GROUP); 701 MLX5_COMMAND_STR_CASE(SET_FLOW_TABLE_ENTRY); 702 MLX5_COMMAND_STR_CASE(QUERY_FLOW_TABLE_ENTRY); 703 MLX5_COMMAND_STR_CASE(DELETE_FLOW_TABLE_ENTRY); 704 MLX5_COMMAND_STR_CASE(ALLOC_FLOW_COUNTER); 705 MLX5_COMMAND_STR_CASE(DEALLOC_FLOW_COUNTER); 706 MLX5_COMMAND_STR_CASE(QUERY_FLOW_COUNTER); 707 MLX5_COMMAND_STR_CASE(MODIFY_FLOW_TABLE); 708 MLX5_COMMAND_STR_CASE(ALLOC_PACKET_REFORMAT_CONTEXT); 709 MLX5_COMMAND_STR_CASE(DEALLOC_PACKET_REFORMAT_CONTEXT); 710 MLX5_COMMAND_STR_CASE(ALLOC_MODIFY_HEADER_CONTEXT); 711 MLX5_COMMAND_STR_CASE(DEALLOC_MODIFY_HEADER_CONTEXT); 712 MLX5_COMMAND_STR_CASE(FPGA_CREATE_QP); 713 MLX5_COMMAND_STR_CASE(FPGA_MODIFY_QP); 714 MLX5_COMMAND_STR_CASE(FPGA_QUERY_QP); 715 MLX5_COMMAND_STR_CASE(FPGA_QUERY_QP_COUNTERS); 716 MLX5_COMMAND_STR_CASE(FPGA_DESTROY_QP); 717 MLX5_COMMAND_STR_CASE(CREATE_XRQ); 718 MLX5_COMMAND_STR_CASE(DESTROY_XRQ); 719 MLX5_COMMAND_STR_CASE(QUERY_XRQ); 720 MLX5_COMMAND_STR_CASE(ARM_XRQ); 721 MLX5_COMMAND_STR_CASE(CREATE_GENERAL_OBJECT); 722 MLX5_COMMAND_STR_CASE(DESTROY_GENERAL_OBJECT); 723 MLX5_COMMAND_STR_CASE(MODIFY_GENERAL_OBJECT); 724 MLX5_COMMAND_STR_CASE(QUERY_GENERAL_OBJECT); 725 MLX5_COMMAND_STR_CASE(QUERY_MODIFY_HEADER_CONTEXT); 726 MLX5_COMMAND_STR_CASE(ALLOC_MEMIC); 727 MLX5_COMMAND_STR_CASE(DEALLOC_MEMIC); 728 MLX5_COMMAND_STR_CASE(QUERY_ESW_FUNCTIONS); 729 MLX5_COMMAND_STR_CASE(CREATE_UCTX); 730 MLX5_COMMAND_STR_CASE(DESTROY_UCTX); 731 MLX5_COMMAND_STR_CASE(CREATE_UMEM); 732 MLX5_COMMAND_STR_CASE(DESTROY_UMEM); 733 MLX5_COMMAND_STR_CASE(RELEASE_XRQ_ERROR); 734 MLX5_COMMAND_STR_CASE(MODIFY_XRQ); 735 MLX5_COMMAND_STR_CASE(QUERY_VHCA_STATE); 736 MLX5_COMMAND_STR_CASE(MODIFY_VHCA_STATE); 737 MLX5_COMMAND_STR_CASE(ALLOC_SF); 738 MLX5_COMMAND_STR_CASE(DEALLOC_SF); 739 MLX5_COMMAND_STR_CASE(SUSPEND_VHCA); 740 MLX5_COMMAND_STR_CASE(RESUME_VHCA); 741 MLX5_COMMAND_STR_CASE(QUERY_VHCA_MIGRATION_STATE); 742 MLX5_COMMAND_STR_CASE(SAVE_VHCA_STATE); 743 MLX5_COMMAND_STR_CASE(LOAD_VHCA_STATE); 744 MLX5_COMMAND_STR_CASE(SYNC_CRYPTO); 745 MLX5_COMMAND_STR_CASE(ALLOW_OTHER_VHCA_ACCESS); 746 default: return "unknown command opcode"; 747 } 748} 749 750static const char *cmd_status_str(u8 status) 751{ 752 switch (status) { 753 case MLX5_CMD_STAT_OK: 754 return "OK"; 755 case MLX5_CMD_STAT_INT_ERR: 756 return "internal error"; 757 case MLX5_CMD_STAT_BAD_OP_ERR: 758 return "bad operation"; 759 case MLX5_CMD_STAT_BAD_PARAM_ERR: 760 return "bad parameter"; 761 case MLX5_CMD_STAT_BAD_SYS_STATE_ERR: 762 return "bad system state"; 763 case MLX5_CMD_STAT_BAD_RES_ERR: 764 return "bad resource"; 765 case MLX5_CMD_STAT_RES_BUSY: 766 return "resource busy"; 767 case MLX5_CMD_STAT_NOT_READY: 768 return "FW not ready"; 769 case MLX5_CMD_STAT_LIM_ERR: 770 return "limits exceeded"; 771 case MLX5_CMD_STAT_BAD_RES_STATE_ERR: 772 return "bad resource state"; 773 case MLX5_CMD_STAT_IX_ERR: 774 return "bad index"; 775 case MLX5_CMD_STAT_NO_RES_ERR: 776 return "no resources"; 777 case MLX5_CMD_STAT_BAD_INP_LEN_ERR: 778 return "bad input length"; 779 case MLX5_CMD_STAT_BAD_OUTP_LEN_ERR: 780 return "bad output length"; 781 case MLX5_CMD_STAT_BAD_QP_STATE_ERR: 782 return "bad QP state"; 783 case MLX5_CMD_STAT_BAD_PKT_ERR: 784 return "bad packet (discarded)"; 785 case MLX5_CMD_STAT_BAD_SIZE_OUTS_CQES_ERR: 786 return "bad size too many outstanding CQEs"; 787 default: 788 return "unknown status"; 789 } 790} 791 792static int cmd_status_to_err(u8 status) 793{ 794 switch (status) { 795 case MLX5_CMD_STAT_OK: return 0; 796 case MLX5_CMD_STAT_INT_ERR: return -EIO; 797 case MLX5_CMD_STAT_BAD_OP_ERR: return -EINVAL; 798 case MLX5_CMD_STAT_BAD_PARAM_ERR: return -EINVAL; 799 case MLX5_CMD_STAT_BAD_SYS_STATE_ERR: return -EIO; 800 case MLX5_CMD_STAT_BAD_RES_ERR: return -EINVAL; 801 case MLX5_CMD_STAT_RES_BUSY: return -EBUSY; 802 case MLX5_CMD_STAT_NOT_READY: return -EAGAIN; 803 case MLX5_CMD_STAT_LIM_ERR: return -ENOMEM; 804 case MLX5_CMD_STAT_BAD_RES_STATE_ERR: return -EINVAL; 805 case MLX5_CMD_STAT_IX_ERR: return -EINVAL; 806 case MLX5_CMD_STAT_NO_RES_ERR: return -EAGAIN; 807 case MLX5_CMD_STAT_BAD_INP_LEN_ERR: return -EIO; 808 case MLX5_CMD_STAT_BAD_OUTP_LEN_ERR: return -EIO; 809 case MLX5_CMD_STAT_BAD_QP_STATE_ERR: return -EINVAL; 810 case MLX5_CMD_STAT_BAD_PKT_ERR: return -EINVAL; 811 case MLX5_CMD_STAT_BAD_SIZE_OUTS_CQES_ERR: return -EINVAL; 812 default: return -EIO; 813 } 814} 815 816void mlx5_cmd_out_err(struct mlx5_core_dev *dev, u16 opcode, u16 op_mod, void *out) 817{ 818 u32 syndrome = MLX5_GET(mbox_out, out, syndrome); 819 u8 status = MLX5_GET(mbox_out, out, status); 820 821 mlx5_core_err_rl(dev, 822 "%s(0x%x) op_mod(0x%x) failed, status %s(0x%x), syndrome (0x%x), err(%d)\n", 823 mlx5_command_str(opcode), opcode, op_mod, 824 cmd_status_str(status), status, syndrome, cmd_status_to_err(status)); 825} 826EXPORT_SYMBOL(mlx5_cmd_out_err); 827 828static void cmd_status_print(struct mlx5_core_dev *dev, void *in, void *out) 829{ 830 u16 opcode, op_mod; 831 u8 status; 832 u16 uid; 833 834 opcode = in_to_opcode(in); 835 op_mod = MLX5_GET(mbox_in, in, op_mod); 836 uid = in_to_uid(in); 837 status = MLX5_GET(mbox_out, out, status); 838 839 if (!uid && opcode != MLX5_CMD_OP_DESTROY_MKEY && 840 opcode != MLX5_CMD_OP_CREATE_UCTX && status != MLX5_CMD_STAT_NOT_READY) 841 mlx5_cmd_out_err(dev, opcode, op_mod, out); 842} 843 844int mlx5_cmd_check(struct mlx5_core_dev *dev, int err, void *in, void *out) 845{ 846 /* aborted due to PCI error or via reset flow mlx5_cmd_trigger_completions() */ 847 if (err == -ENXIO) { 848 u16 opcode = in_to_opcode(in); 849 u32 syndrome; 850 u8 status; 851 852 /* PCI Error, emulate command return status, for smooth reset */ 853 err = mlx5_internal_err_ret_value(dev, opcode, &syndrome, &status); 854 MLX5_SET(mbox_out, out, status, status); 855 MLX5_SET(mbox_out, out, syndrome, syndrome); 856 if (!err) 857 return 0; 858 } 859 860 /* driver or FW delivery error */ 861 if (err != -EREMOTEIO && err) 862 return err; 863 864 /* check outbox status */ 865 err = cmd_status_to_err(MLX5_GET(mbox_out, out, status)); 866 if (err) 867 cmd_status_print(dev, in, out); 868 869 return err; 870} 871EXPORT_SYMBOL(mlx5_cmd_check); 872 873static void dump_command(struct mlx5_core_dev *dev, 874 struct mlx5_cmd_work_ent *ent, int input) 875{ 876 struct mlx5_cmd_msg *msg = input ? ent->in : ent->out; 877 struct mlx5_cmd_mailbox *next = msg->next; 878 int n = mlx5_calc_cmd_blocks(msg); 879 u16 op = ent->op; 880 int data_only; 881 u32 offset = 0; 882 int dump_len; 883 int i; 884 885 mlx5_core_dbg(dev, "cmd[%d]: start dump\n", ent->idx); 886 data_only = !!(mlx5_core_debug_mask & (1 << MLX5_CMD_DATA)); 887 888 if (data_only) 889 mlx5_core_dbg_mask(dev, 1 << MLX5_CMD_DATA, 890 "cmd[%d]: dump command data %s(0x%x) %s\n", 891 ent->idx, mlx5_command_str(op), op, 892 input ? "INPUT" : "OUTPUT"); 893 else 894 mlx5_core_dbg(dev, "cmd[%d]: dump command %s(0x%x) %s\n", 895 ent->idx, mlx5_command_str(op), op, 896 input ? "INPUT" : "OUTPUT"); 897 898 if (data_only) { 899 if (input) { 900 dump_buf(ent->lay->in, sizeof(ent->lay->in), 1, offset, ent->idx); 901 offset += sizeof(ent->lay->in); 902 } else { 903 dump_buf(ent->lay->out, sizeof(ent->lay->out), 1, offset, ent->idx); 904 offset += sizeof(ent->lay->out); 905 } 906 } else { 907 dump_buf(ent->lay, sizeof(*ent->lay), 0, offset, ent->idx); 908 offset += sizeof(*ent->lay); 909 } 910 911 for (i = 0; i < n && next; i++) { 912 if (data_only) { 913 dump_len = min_t(int, MLX5_CMD_DATA_BLOCK_SIZE, msg->len - offset); 914 dump_buf(next->buf, dump_len, 1, offset, ent->idx); 915 offset += MLX5_CMD_DATA_BLOCK_SIZE; 916 } else { 917 mlx5_core_dbg(dev, "cmd[%d]: command block:\n", ent->idx); 918 dump_buf(next->buf, sizeof(struct mlx5_cmd_prot_block), 0, offset, 919 ent->idx); 920 offset += sizeof(struct mlx5_cmd_prot_block); 921 } 922 next = next->next; 923 } 924 925 if (data_only) 926 pr_debug("\n"); 927 928 mlx5_core_dbg(dev, "cmd[%d]: end dump\n", ent->idx); 929} 930 931static void mlx5_cmd_comp_handler(struct mlx5_core_dev *dev, u64 vec, bool forced); 932 933static void cb_timeout_handler(struct work_struct *work) 934{ 935 struct delayed_work *dwork = to_delayed_work(work); 936 struct mlx5_cmd_work_ent *ent = container_of(dwork, 937 struct mlx5_cmd_work_ent, 938 cb_timeout_work); 939 struct mlx5_core_dev *dev = container_of(ent->cmd, struct mlx5_core_dev, 940 cmd); 941 942 mlx5_cmd_eq_recover(dev); 943 944 /* Maybe got handled by eq recover ? */ 945 if (!test_bit(MLX5_CMD_ENT_STATE_PENDING_COMP, &ent->state)) { 946 mlx5_core_warn(dev, "cmd[%d]: %s(0x%x) Async, recovered after timeout\n", ent->idx, 947 mlx5_command_str(ent->op), ent->op); 948 goto out; /* phew, already handled */ 949 } 950 951 ent->ret = -ETIMEDOUT; 952 mlx5_core_warn(dev, "cmd[%d]: %s(0x%x) Async, timeout. Will cause a leak of a command resource\n", 953 ent->idx, mlx5_command_str(ent->op), ent->op); 954 mlx5_cmd_comp_handler(dev, 1ULL << ent->idx, true); 955 956out: 957 cmd_ent_put(ent); /* for the cmd_ent_get() took on schedule delayed work */ 958} 959 960static void free_msg(struct mlx5_core_dev *dev, struct mlx5_cmd_msg *msg); 961static void mlx5_free_cmd_msg(struct mlx5_core_dev *dev, 962 struct mlx5_cmd_msg *msg); 963 964static bool opcode_allowed(struct mlx5_cmd *cmd, u16 opcode) 965{ 966 if (cmd->allowed_opcode == CMD_ALLOWED_OPCODE_ALL) 967 return true; 968 969 return cmd->allowed_opcode == opcode; 970} 971 972bool mlx5_cmd_is_down(struct mlx5_core_dev *dev) 973{ 974 return pci_channel_offline(dev->pdev) || 975 dev->cmd.state != MLX5_CMDIF_STATE_UP || 976 dev->state == MLX5_DEVICE_STATE_INTERNAL_ERROR; 977} 978 979static void cmd_work_handler(struct work_struct *work) 980{ 981 struct mlx5_cmd_work_ent *ent = container_of(work, struct mlx5_cmd_work_ent, work); 982 struct mlx5_cmd *cmd = ent->cmd; 983 bool poll_cmd = ent->polling; 984 struct mlx5_cmd_layout *lay; 985 struct mlx5_core_dev *dev; 986 unsigned long timeout; 987 unsigned long flags; 988 int alloc_ret; 989 int cmd_mode; 990 991 complete(&ent->handling); 992 993 dev = container_of(cmd, struct mlx5_core_dev, cmd); 994 timeout = msecs_to_jiffies(mlx5_tout_ms(dev, CMD)); 995 996 if (!ent->page_queue) { 997 if (down_timeout(&cmd->vars.sem, timeout)) { 998 mlx5_core_warn(dev, "%s(0x%x) timed out while waiting for a slot.\n", 999 mlx5_command_str(ent->op), ent->op); 1000 if (ent->callback) { 1001 ent->callback(-EBUSY, ent->context); 1002 mlx5_free_cmd_msg(dev, ent->out); 1003 free_msg(dev, ent->in); 1004 cmd_ent_put(ent); 1005 } else { 1006 ent->ret = -EBUSY; 1007 complete(&ent->done); 1008 } 1009 complete(&ent->slotted); 1010 return; 1011 } 1012 alloc_ret = cmd_alloc_index(cmd, ent); 1013 if (alloc_ret < 0) { 1014 mlx5_core_err_rl(dev, "failed to allocate command entry\n"); 1015 if (ent->callback) { 1016 ent->callback(-EAGAIN, ent->context); 1017 mlx5_free_cmd_msg(dev, ent->out); 1018 free_msg(dev, ent->in); 1019 cmd_ent_put(ent); 1020 } else { 1021 ent->ret = -EAGAIN; 1022 complete(&ent->done); 1023 } 1024 up(&cmd->vars.sem); 1025 complete(&ent->slotted); 1026 return; 1027 } 1028 } else { 1029 down(&cmd->vars.pages_sem); 1030 ent->idx = cmd->vars.max_reg_cmds; 1031 spin_lock_irqsave(&cmd->alloc_lock, flags); 1032 clear_bit(ent->idx, &cmd->vars.bitmask); 1033 cmd->ent_arr[ent->idx] = ent; 1034 spin_unlock_irqrestore(&cmd->alloc_lock, flags); 1035 } 1036 1037 complete(&ent->slotted); 1038 1039 lay = get_inst(cmd, ent->idx); 1040 ent->lay = lay; 1041 memset(lay, 0, sizeof(*lay)); 1042 memcpy(lay->in, ent->in->first.data, sizeof(lay->in)); 1043 if (ent->in->next) 1044 lay->in_ptr = cpu_to_be64(ent->in->next->dma); 1045 lay->inlen = cpu_to_be32(ent->in->len); 1046 if (ent->out->next) 1047 lay->out_ptr = cpu_to_be64(ent->out->next->dma); 1048 lay->outlen = cpu_to_be32(ent->out->len); 1049 lay->type = MLX5_PCI_CMD_XPORT; 1050 lay->token = ent->token; 1051 lay->status_own = CMD_OWNER_HW; 1052 set_signature(ent, !cmd->checksum_disabled); 1053 dump_command(dev, ent, 1); 1054 ent->ts1 = ktime_get_ns(); 1055 cmd_mode = cmd->mode; 1056 1057 if (ent->callback && schedule_delayed_work(&ent->cb_timeout_work, timeout)) 1058 cmd_ent_get(ent); 1059 set_bit(MLX5_CMD_ENT_STATE_PENDING_COMP, &ent->state); 1060 1061 cmd_ent_get(ent); /* for the _real_ FW event on completion */ 1062 /* Skip sending command to fw if internal error */ 1063 if (mlx5_cmd_is_down(dev) || !opcode_allowed(&dev->cmd, ent->op)) { 1064 ent->ret = -ENXIO; 1065 mlx5_cmd_comp_handler(dev, 1ULL << ent->idx, true); 1066 return; 1067 } 1068 1069 /* ring doorbell after the descriptor is valid */ 1070 mlx5_core_dbg(dev, "writing 0x%x to command doorbell\n", 1 << ent->idx); 1071 wmb(); 1072 iowrite32be(1 << ent->idx, &dev->iseg->cmd_dbell); 1073 /* if not in polling don't use ent after this point */ 1074 if (cmd_mode == CMD_MODE_POLLING || poll_cmd) { 1075 poll_timeout(ent); 1076 /* make sure we read the descriptor after ownership is SW */ 1077 rmb(); 1078 mlx5_cmd_comp_handler(dev, 1ULL << ent->idx, !!ent->ret); 1079 } 1080} 1081 1082static int deliv_status_to_err(u8 status) 1083{ 1084 switch (status) { 1085 case MLX5_CMD_DELIVERY_STAT_OK: 1086 case MLX5_DRIVER_STATUS_ABORTED: 1087 return 0; 1088 case MLX5_CMD_DELIVERY_STAT_SIGNAT_ERR: 1089 case MLX5_CMD_DELIVERY_STAT_TOK_ERR: 1090 return -EBADR; 1091 case MLX5_CMD_DELIVERY_STAT_BAD_BLK_NUM_ERR: 1092 case MLX5_CMD_DELIVERY_STAT_OUT_PTR_ALIGN_ERR: 1093 case MLX5_CMD_DELIVERY_STAT_IN_PTR_ALIGN_ERR: 1094 return -EFAULT; /* Bad address */ 1095 case MLX5_CMD_DELIVERY_STAT_IN_LENGTH_ERR: 1096 case MLX5_CMD_DELIVERY_STAT_OUT_LENGTH_ERR: 1097 case MLX5_CMD_DELIVERY_STAT_CMD_DESCR_ERR: 1098 case MLX5_CMD_DELIVERY_STAT_RES_FLD_NOT_CLR_ERR: 1099 return -ENOMSG; 1100 case MLX5_CMD_DELIVERY_STAT_FW_ERR: 1101 return -EIO; 1102 default: 1103 return -EINVAL; 1104 } 1105} 1106 1107static const char *deliv_status_to_str(u8 status) 1108{ 1109 switch (status) { 1110 case MLX5_CMD_DELIVERY_STAT_OK: 1111 return "no errors"; 1112 case MLX5_CMD_DELIVERY_STAT_SIGNAT_ERR: 1113 return "signature error"; 1114 case MLX5_CMD_DELIVERY_STAT_TOK_ERR: 1115 return "token error"; 1116 case MLX5_CMD_DELIVERY_STAT_BAD_BLK_NUM_ERR: 1117 return "bad block number"; 1118 case MLX5_CMD_DELIVERY_STAT_OUT_PTR_ALIGN_ERR: 1119 return "output pointer not aligned to block size"; 1120 case MLX5_CMD_DELIVERY_STAT_IN_PTR_ALIGN_ERR: 1121 return "input pointer not aligned to block size"; 1122 case MLX5_CMD_DELIVERY_STAT_FW_ERR: 1123 return "firmware internal error"; 1124 case MLX5_CMD_DELIVERY_STAT_IN_LENGTH_ERR: 1125 return "command input length error"; 1126 case MLX5_CMD_DELIVERY_STAT_OUT_LENGTH_ERR: 1127 return "command output length error"; 1128 case MLX5_CMD_DELIVERY_STAT_RES_FLD_NOT_CLR_ERR: 1129 return "reserved fields not cleared"; 1130 case MLX5_CMD_DELIVERY_STAT_CMD_DESCR_ERR: 1131 return "bad command descriptor type"; 1132 default: 1133 return "unknown status code"; 1134 } 1135} 1136 1137enum { 1138 MLX5_CMD_TIMEOUT_RECOVER_MSEC = 5 * 1000, 1139}; 1140 1141static void wait_func_handle_exec_timeout(struct mlx5_core_dev *dev, 1142 struct mlx5_cmd_work_ent *ent) 1143{ 1144 unsigned long timeout = msecs_to_jiffies(MLX5_CMD_TIMEOUT_RECOVER_MSEC); 1145 1146 mlx5_cmd_eq_recover(dev); 1147 1148 /* Re-wait on the ent->done after executing the recovery flow. If the 1149 * recovery flow (or any other recovery flow running simultaneously) 1150 * has recovered an EQE, it should cause the entry to be completed by 1151 * the command interface. 1152 */ 1153 if (wait_for_completion_timeout(&ent->done, timeout)) { 1154 mlx5_core_warn(dev, "cmd[%d]: %s(0x%x) recovered after timeout\n", ent->idx, 1155 mlx5_command_str(ent->op), ent->op); 1156 return; 1157 } 1158 1159 mlx5_core_warn(dev, "cmd[%d]: %s(0x%x) No done completion\n", ent->idx, 1160 mlx5_command_str(ent->op), ent->op); 1161 1162 ent->ret = -ETIMEDOUT; 1163 mlx5_cmd_comp_handler(dev, 1ULL << ent->idx, true); 1164} 1165 1166static int wait_func(struct mlx5_core_dev *dev, struct mlx5_cmd_work_ent *ent) 1167{ 1168 unsigned long timeout = msecs_to_jiffies(mlx5_tout_ms(dev, CMD)); 1169 struct mlx5_cmd *cmd = &dev->cmd; 1170 int err; 1171 1172 if (!wait_for_completion_timeout(&ent->handling, timeout) && 1173 cancel_work_sync(&ent->work)) { 1174 ent->ret = -ECANCELED; 1175 goto out_err; 1176 } 1177 1178 wait_for_completion(&ent->slotted); 1179 1180 if (cmd->mode == CMD_MODE_POLLING || ent->polling) 1181 wait_for_completion(&ent->done); 1182 else if (!wait_for_completion_timeout(&ent->done, timeout)) 1183 wait_func_handle_exec_timeout(dev, ent); 1184 1185out_err: 1186 err = ent->ret; 1187 1188 if (err == -ETIMEDOUT) { 1189 mlx5_core_warn(dev, "%s(0x%x) timeout. Will cause a leak of a command resource\n", 1190 mlx5_command_str(ent->op), ent->op); 1191 } else if (err == -ECANCELED) { 1192 mlx5_core_warn(dev, "%s(0x%x) canceled on out of queue timeout.\n", 1193 mlx5_command_str(ent->op), ent->op); 1194 } else if (err == -EBUSY) { 1195 mlx5_core_warn(dev, "%s(0x%x) timeout while waiting for command semaphore.\n", 1196 mlx5_command_str(ent->op), ent->op); 1197 } 1198 mlx5_core_dbg(dev, "err %d, delivery status %s(%d)\n", 1199 err, deliv_status_to_str(ent->status), ent->status); 1200 1201 return err; 1202} 1203 1204/* Check if all command slots are stalled (timed out and not recovered). 1205 * returns true if all slots timed out on a recent command and have not been 1206 * completed by FW yet. (stalled state) 1207 * false otherwise (at least one slot is not stalled). 1208 * 1209 * In such odd situation "all_stalled", this serves as a protection mechanism 1210 * to avoid blocking the kernel for long periods of time in case FW is not 1211 * responding to commands. 1212 */ 1213static bool mlx5_cmd_all_stalled(struct mlx5_core_dev *dev) 1214{ 1215 struct mlx5_cmd *cmd = &dev->cmd; 1216 bool all_stalled = true; 1217 unsigned long flags; 1218 int i; 1219 1220 spin_lock_irqsave(&cmd->alloc_lock, flags); 1221 1222 /* at least one command slot is free */ 1223 if (bitmap_weight(&cmd->vars.bitmask, cmd->vars.max_reg_cmds) > 0) { 1224 all_stalled = false; 1225 goto out; 1226 } 1227 1228 for_each_clear_bit(i, &cmd->vars.bitmask, cmd->vars.max_reg_cmds) { 1229 struct mlx5_cmd_work_ent *ent = dev->cmd.ent_arr[i]; 1230 1231 if (!test_bit(MLX5_CMD_ENT_STATE_TIMEDOUT, &ent->state)) { 1232 all_stalled = false; 1233 break; 1234 } 1235 } 1236out: 1237 spin_unlock_irqrestore(&cmd->alloc_lock, flags); 1238 1239 return all_stalled; 1240} 1241 1242/* Notes: 1243 * 1. Callback functions may not sleep 1244 * 2. page queue commands do not support asynchrous completion 1245 * 1246 * return value in case (!callback): 1247 * ret < 0 : Command execution couldn't be submitted by driver 1248 * ret > 0 : Command execution couldn't be performed by firmware 1249 * ret == 0: Command was executed by FW, Caller must check FW outbox status. 1250 * 1251 * return value in case (callback): 1252 * ret < 0 : Command execution couldn't be submitted by driver 1253 * ret == 0: Command will be submitted to FW for execution 1254 * and the callback will be called for further status updates 1255 */ 1256static int mlx5_cmd_invoke(struct mlx5_core_dev *dev, struct mlx5_cmd_msg *in, 1257 struct mlx5_cmd_msg *out, void *uout, int uout_size, 1258 mlx5_cmd_cbk_t callback, 1259 void *context, int page_queue, 1260 u8 token, bool force_polling) 1261{ 1262 struct mlx5_cmd *cmd = &dev->cmd; 1263 struct mlx5_cmd_work_ent *ent; 1264 struct mlx5_cmd_stats *stats; 1265 u8 status = 0; 1266 int err = 0; 1267 s64 ds; 1268 1269 if (callback && page_queue) 1270 return -EINVAL; 1271 1272 if (!page_queue && mlx5_cmd_all_stalled(dev)) { 1273 mlx5_core_err_rl(dev, 1274 "All CMD slots are stalled, aborting command\n"); 1275 /* there's no reason to wait and block the whole kernel if FW 1276 * isn't currently responding to all slots, fail immediately 1277 */ 1278 return -EAGAIN; 1279 } 1280 1281 ent = cmd_alloc_ent(cmd, in, out, uout, uout_size, 1282 callback, context, page_queue); 1283 if (IS_ERR(ent)) 1284 return PTR_ERR(ent); 1285 1286 /* put for this ent is when consumed, depending on the use case 1287 * 1) (!callback) blocking flow: by caller after wait_func completes 1288 * 2) (callback) flow: by mlx5_cmd_comp_handler() when ent is handled 1289 */ 1290 1291 ent->token = token; 1292 ent->polling = force_polling; 1293 1294 init_completion(&ent->handling); 1295 init_completion(&ent->slotted); 1296 if (!callback) 1297 init_completion(&ent->done); 1298 1299 INIT_DELAYED_WORK(&ent->cb_timeout_work, cb_timeout_handler); 1300 INIT_WORK(&ent->work, cmd_work_handler); 1301 if (page_queue) { 1302 cmd_work_handler(&ent->work); 1303 } else if (!queue_work(cmd->wq, &ent->work)) { 1304 mlx5_core_warn(dev, "failed to queue work\n"); 1305 err = -EALREADY; 1306 goto out_free; 1307 } 1308 1309 if (callback) 1310 return 0; /* mlx5_cmd_comp_handler() will put(ent) */ 1311 1312 err = wait_func(dev, ent); 1313 if (err == -ETIMEDOUT || err == -ECANCELED || err == -EBUSY) 1314 goto out_free; 1315 1316 ds = ent->ts2 - ent->ts1; 1317 stats = xa_load(&cmd->stats, ent->op); 1318 if (stats) { 1319 spin_lock_irq(&stats->lock); 1320 stats->sum += ds; 1321 ++stats->n; 1322 spin_unlock_irq(&stats->lock); 1323 } 1324 mlx5_core_dbg_mask(dev, 1 << MLX5_CMD_TIME, 1325 "fw exec time for %s is %lld nsec\n", 1326 mlx5_command_str(ent->op), ds); 1327 1328out_free: 1329 status = ent->status; 1330 cmd_ent_put(ent); 1331 return err ? : status; 1332} 1333 1334static ssize_t dbg_write(struct file *filp, const char __user *buf, 1335 size_t count, loff_t *pos) 1336{ 1337 struct mlx5_core_dev *dev = filp->private_data; 1338 struct mlx5_cmd_debug *dbg = &dev->cmd.dbg; 1339 char lbuf[3]; 1340 int err; 1341 1342 if (!dbg->in_msg || !dbg->out_msg) 1343 return -ENOMEM; 1344 1345 if (count < sizeof(lbuf) - 1) 1346 return -EINVAL; 1347 1348 if (copy_from_user(lbuf, buf, sizeof(lbuf) - 1)) 1349 return -EFAULT; 1350 1351 lbuf[sizeof(lbuf) - 1] = 0; 1352 1353 if (strcmp(lbuf, "go")) 1354 return -EINVAL; 1355 1356 err = mlx5_cmd_exec(dev, dbg->in_msg, dbg->inlen, dbg->out_msg, dbg->outlen); 1357 1358 return err ? err : count; 1359} 1360 1361static const struct file_operations fops = { 1362 .owner = THIS_MODULE, 1363 .open = simple_open, 1364 .write = dbg_write, 1365}; 1366 1367static int mlx5_copy_to_msg(struct mlx5_cmd_msg *to, void *from, int size, 1368 u8 token) 1369{ 1370 struct mlx5_cmd_prot_block *block; 1371 struct mlx5_cmd_mailbox *next; 1372 int copy; 1373 1374 if (!to || !from) 1375 return -ENOMEM; 1376 1377 copy = min_t(int, size, sizeof(to->first.data)); 1378 memcpy(to->first.data, from, copy); 1379 size -= copy; 1380 from += copy; 1381 1382 next = to->next; 1383 while (size) { 1384 if (!next) { 1385 /* this is a BUG */ 1386 return -ENOMEM; 1387 } 1388 1389 copy = min_t(int, size, MLX5_CMD_DATA_BLOCK_SIZE); 1390 block = next->buf; 1391 memcpy(block->data, from, copy); 1392 from += copy; 1393 size -= copy; 1394 block->token = token; 1395 next = next->next; 1396 } 1397 1398 return 0; 1399} 1400 1401static int mlx5_copy_from_msg(void *to, struct mlx5_cmd_msg *from, int size) 1402{ 1403 struct mlx5_cmd_prot_block *block; 1404 struct mlx5_cmd_mailbox *next; 1405 int copy; 1406 1407 if (!to || !from) 1408 return -ENOMEM; 1409 1410 copy = min_t(int, size, sizeof(from->first.data)); 1411 memcpy(to, from->first.data, copy); 1412 size -= copy; 1413 to += copy; 1414 1415 next = from->next; 1416 while (size) { 1417 if (!next) { 1418 /* this is a BUG */ 1419 return -ENOMEM; 1420 } 1421 1422 copy = min_t(int, size, MLX5_CMD_DATA_BLOCK_SIZE); 1423 block = next->buf; 1424 1425 memcpy(to, block->data, copy); 1426 to += copy; 1427 size -= copy; 1428 next = next->next; 1429 } 1430 1431 return 0; 1432} 1433 1434static struct mlx5_cmd_mailbox *alloc_cmd_box(struct mlx5_core_dev *dev, 1435 gfp_t flags) 1436{ 1437 struct mlx5_cmd_mailbox *mailbox; 1438 1439 mailbox = kmalloc(sizeof(*mailbox), flags); 1440 if (!mailbox) 1441 return ERR_PTR(-ENOMEM); 1442 1443 mailbox->buf = dma_pool_zalloc(dev->cmd.pool, flags, 1444 &mailbox->dma); 1445 if (!mailbox->buf) { 1446 mlx5_core_dbg(dev, "failed allocation\n"); 1447 kfree(mailbox); 1448 return ERR_PTR(-ENOMEM); 1449 } 1450 mailbox->next = NULL; 1451 1452 return mailbox; 1453} 1454 1455static void free_cmd_box(struct mlx5_core_dev *dev, 1456 struct mlx5_cmd_mailbox *mailbox) 1457{ 1458 dma_pool_free(dev->cmd.pool, mailbox->buf, mailbox->dma); 1459 kfree(mailbox); 1460} 1461 1462static struct mlx5_cmd_msg *mlx5_alloc_cmd_msg(struct mlx5_core_dev *dev, 1463 gfp_t flags, int size, 1464 u8 token) 1465{ 1466 struct mlx5_cmd_mailbox *tmp, *head = NULL; 1467 struct mlx5_cmd_prot_block *block; 1468 struct mlx5_cmd_msg *msg; 1469 int err; 1470 int n; 1471 int i; 1472 1473 msg = kzalloc(sizeof(*msg), flags); 1474 if (!msg) 1475 return ERR_PTR(-ENOMEM); 1476 1477 msg->len = size; 1478 n = mlx5_calc_cmd_blocks(msg); 1479 1480 for (i = 0; i < n; i++) { 1481 tmp = alloc_cmd_box(dev, flags); 1482 if (IS_ERR(tmp)) { 1483 mlx5_core_warn(dev, "failed allocating block\n"); 1484 err = PTR_ERR(tmp); 1485 goto err_alloc; 1486 } 1487 1488 block = tmp->buf; 1489 tmp->next = head; 1490 block->next = cpu_to_be64(tmp->next ? tmp->next->dma : 0); 1491 block->block_num = cpu_to_be32(n - i - 1); 1492 block->token = token; 1493 head = tmp; 1494 } 1495 msg->next = head; 1496 return msg; 1497 1498err_alloc: 1499 while (head) { 1500 tmp = head->next; 1501 free_cmd_box(dev, head); 1502 head = tmp; 1503 } 1504 kfree(msg); 1505 1506 return ERR_PTR(err); 1507} 1508 1509static void mlx5_free_cmd_msg(struct mlx5_core_dev *dev, 1510 struct mlx5_cmd_msg *msg) 1511{ 1512 struct mlx5_cmd_mailbox *head = msg->next; 1513 struct mlx5_cmd_mailbox *next; 1514 1515 while (head) { 1516 next = head->next; 1517 free_cmd_box(dev, head); 1518 head = next; 1519 } 1520 kfree(msg); 1521} 1522 1523static ssize_t data_write(struct file *filp, const char __user *buf, 1524 size_t count, loff_t *pos) 1525{ 1526 struct mlx5_core_dev *dev = filp->private_data; 1527 struct mlx5_cmd_debug *dbg = &dev->cmd.dbg; 1528 void *ptr; 1529 1530 if (*pos != 0) 1531 return -EINVAL; 1532 1533 kfree(dbg->in_msg); 1534 dbg->in_msg = NULL; 1535 dbg->inlen = 0; 1536 ptr = memdup_user(buf, count); 1537 if (IS_ERR(ptr)) 1538 return PTR_ERR(ptr); 1539 dbg->in_msg = ptr; 1540 dbg->inlen = count; 1541 1542 *pos = count; 1543 1544 return count; 1545} 1546 1547static ssize_t data_read(struct file *filp, char __user *buf, size_t count, 1548 loff_t *pos) 1549{ 1550 struct mlx5_core_dev *dev = filp->private_data; 1551 struct mlx5_cmd_debug *dbg = &dev->cmd.dbg; 1552 1553 if (!dbg->out_msg) 1554 return -ENOMEM; 1555 1556 return simple_read_from_buffer(buf, count, pos, dbg->out_msg, 1557 dbg->outlen); 1558} 1559 1560static const struct file_operations dfops = { 1561 .owner = THIS_MODULE, 1562 .open = simple_open, 1563 .write = data_write, 1564 .read = data_read, 1565}; 1566 1567static ssize_t outlen_read(struct file *filp, char __user *buf, size_t count, 1568 loff_t *pos) 1569{ 1570 struct mlx5_core_dev *dev = filp->private_data; 1571 struct mlx5_cmd_debug *dbg = &dev->cmd.dbg; 1572 char outlen[8]; 1573 int err; 1574 1575 err = snprintf(outlen, sizeof(outlen), "%d", dbg->outlen); 1576 if (err < 0) 1577 return err; 1578 1579 return simple_read_from_buffer(buf, count, pos, outlen, err); 1580} 1581 1582static ssize_t outlen_write(struct file *filp, const char __user *buf, 1583 size_t count, loff_t *pos) 1584{ 1585 struct mlx5_core_dev *dev = filp->private_data; 1586 struct mlx5_cmd_debug *dbg = &dev->cmd.dbg; 1587 char outlen_str[8] = {0}; 1588 int outlen; 1589 void *ptr; 1590 int err; 1591 1592 if (*pos != 0 || count > 6) 1593 return -EINVAL; 1594 1595 kfree(dbg->out_msg); 1596 dbg->out_msg = NULL; 1597 dbg->outlen = 0; 1598 1599 if (copy_from_user(outlen_str, buf, count)) 1600 return -EFAULT; 1601 1602 err = sscanf(outlen_str, "%d", &outlen); 1603 if (err != 1) 1604 return -EINVAL; 1605 1606 ptr = kzalloc(outlen, GFP_KERNEL); 1607 if (!ptr) 1608 return -ENOMEM; 1609 1610 dbg->out_msg = ptr; 1611 dbg->outlen = outlen; 1612 1613 *pos = count; 1614 1615 return count; 1616} 1617 1618static const struct file_operations olfops = { 1619 .owner = THIS_MODULE, 1620 .open = simple_open, 1621 .write = outlen_write, 1622 .read = outlen_read, 1623}; 1624 1625static void set_wqname(struct mlx5_core_dev *dev) 1626{ 1627 struct mlx5_cmd *cmd = &dev->cmd; 1628 1629 snprintf(cmd->wq_name, sizeof(cmd->wq_name), "mlx5_cmd_%s", 1630 dev_name(dev->device)); 1631} 1632 1633static void clean_debug_files(struct mlx5_core_dev *dev) 1634{ 1635 struct mlx5_cmd_debug *dbg = &dev->cmd.dbg; 1636 1637 if (!mlx5_debugfs_root) 1638 return; 1639 1640 debugfs_remove_recursive(dbg->dbg_root); 1641} 1642 1643static void create_debugfs_files(struct mlx5_core_dev *dev) 1644{ 1645 struct mlx5_cmd_debug *dbg = &dev->cmd.dbg; 1646 1647 dbg->dbg_root = debugfs_create_dir("cmd", mlx5_debugfs_get_dev_root(dev)); 1648 1649 debugfs_create_file("in", 0400, dbg->dbg_root, dev, &dfops); 1650 debugfs_create_file("out", 0200, dbg->dbg_root, dev, &dfops); 1651 debugfs_create_file("out_len", 0600, dbg->dbg_root, dev, &olfops); 1652 debugfs_create_u8("status", 0600, dbg->dbg_root, &dbg->status); 1653 debugfs_create_file("run", 0200, dbg->dbg_root, dev, &fops); 1654} 1655 1656void mlx5_cmd_allowed_opcode(struct mlx5_core_dev *dev, u16 opcode) 1657{ 1658 struct mlx5_cmd *cmd = &dev->cmd; 1659 int i; 1660 1661 for (i = 0; i < cmd->vars.max_reg_cmds; i++) 1662 down(&cmd->vars.sem); 1663 down(&cmd->vars.pages_sem); 1664 1665 cmd->allowed_opcode = opcode; 1666 1667 up(&cmd->vars.pages_sem); 1668 for (i = 0; i < cmd->vars.max_reg_cmds; i++) 1669 up(&cmd->vars.sem); 1670} 1671 1672static void mlx5_cmd_change_mod(struct mlx5_core_dev *dev, int mode) 1673{ 1674 struct mlx5_cmd *cmd = &dev->cmd; 1675 int i; 1676 1677 for (i = 0; i < cmd->vars.max_reg_cmds; i++) 1678 down(&cmd->vars.sem); 1679 down(&cmd->vars.pages_sem); 1680 1681 cmd->mode = mode; 1682 1683 up(&cmd->vars.pages_sem); 1684 for (i = 0; i < cmd->vars.max_reg_cmds; i++) 1685 up(&cmd->vars.sem); 1686} 1687 1688static int cmd_comp_notifier(struct notifier_block *nb, 1689 unsigned long type, void *data) 1690{ 1691 struct mlx5_core_dev *dev; 1692 struct mlx5_cmd *cmd; 1693 struct mlx5_eqe *eqe; 1694 1695 cmd = mlx5_nb_cof(nb, struct mlx5_cmd, nb); 1696 dev = container_of(cmd, struct mlx5_core_dev, cmd); 1697 eqe = data; 1698 1699 if (dev->state == MLX5_DEVICE_STATE_INTERNAL_ERROR) 1700 return NOTIFY_DONE; 1701 1702 mlx5_cmd_comp_handler(dev, be32_to_cpu(eqe->data.cmd.vector), false); 1703 1704 return NOTIFY_OK; 1705} 1706void mlx5_cmd_use_events(struct mlx5_core_dev *dev) 1707{ 1708 MLX5_NB_INIT(&dev->cmd.nb, cmd_comp_notifier, CMD); 1709 mlx5_eq_notifier_register(dev, &dev->cmd.nb); 1710 mlx5_cmd_change_mod(dev, CMD_MODE_EVENTS); 1711} 1712 1713void mlx5_cmd_use_polling(struct mlx5_core_dev *dev) 1714{ 1715 mlx5_cmd_change_mod(dev, CMD_MODE_POLLING); 1716 mlx5_eq_notifier_unregister(dev, &dev->cmd.nb); 1717} 1718 1719static void free_msg(struct mlx5_core_dev *dev, struct mlx5_cmd_msg *msg) 1720{ 1721 unsigned long flags; 1722 1723 if (msg->parent) { 1724 spin_lock_irqsave(&msg->parent->lock, flags); 1725 list_add_tail(&msg->list, &msg->parent->head); 1726 spin_unlock_irqrestore(&msg->parent->lock, flags); 1727 } else { 1728 mlx5_free_cmd_msg(dev, msg); 1729 } 1730} 1731 1732static void mlx5_cmd_comp_handler(struct mlx5_core_dev *dev, u64 vec, bool forced) 1733{ 1734 struct mlx5_cmd *cmd = &dev->cmd; 1735 struct mlx5_cmd_work_ent *ent; 1736 mlx5_cmd_cbk_t callback; 1737 void *context; 1738 int err; 1739 int i; 1740 s64 ds; 1741 struct mlx5_cmd_stats *stats; 1742 unsigned long flags; 1743 unsigned long vector; 1744 1745 /* there can be at most 32 command queues */ 1746 vector = vec & 0xffffffff; 1747 for (i = 0; i < (1 << cmd->vars.log_sz); i++) { 1748 if (test_bit(i, &vector)) { 1749 ent = cmd->ent_arr[i]; 1750 1751 if (forced && ent->ret == -ETIMEDOUT) 1752 set_bit(MLX5_CMD_ENT_STATE_TIMEDOUT, 1753 &ent->state); 1754 else if (!forced) /* real FW completion */ 1755 clear_bit(MLX5_CMD_ENT_STATE_TIMEDOUT, 1756 &ent->state); 1757 1758 /* if we already completed the command, ignore it */ 1759 if (!test_and_clear_bit(MLX5_CMD_ENT_STATE_PENDING_COMP, 1760 &ent->state)) { 1761 /* only real completion can free the cmd slot */ 1762 if (!forced) { 1763 mlx5_core_err(dev, "Command completion arrived after timeout (entry idx = %d).\n", 1764 ent->idx); 1765 cmd_ent_put(ent); 1766 } 1767 continue; 1768 } 1769 1770 if (ent->callback && cancel_delayed_work(&ent->cb_timeout_work)) 1771 cmd_ent_put(ent); /* timeout work was canceled */ 1772 1773 if (!forced || /* Real FW completion */ 1774 mlx5_cmd_is_down(dev) || /* No real FW completion is expected */ 1775 !opcode_allowed(cmd, ent->op)) 1776 cmd_ent_put(ent); 1777 1778 ent->ts2 = ktime_get_ns(); 1779 memcpy(ent->out->first.data, ent->lay->out, sizeof(ent->lay->out)); 1780 dump_command(dev, ent, 0); 1781 1782 if (vec & MLX5_TRIGGERED_CMD_COMP) 1783 ent->ret = -ENXIO; 1784 1785 if (!ent->ret) { /* Command completed by FW */ 1786 if (!cmd->checksum_disabled) 1787 ent->ret = verify_signature(ent); 1788 1789 ent->status = ent->lay->status_own >> 1; 1790 1791 mlx5_core_dbg(dev, "command completed. ret 0x%x, delivery status %s(0x%x)\n", 1792 ent->ret, deliv_status_to_str(ent->status), ent->status); 1793 } 1794 1795 if (ent->callback) { 1796 ds = ent->ts2 - ent->ts1; 1797 stats = xa_load(&cmd->stats, ent->op); 1798 if (stats) { 1799 spin_lock_irqsave(&stats->lock, flags); 1800 stats->sum += ds; 1801 ++stats->n; 1802 spin_unlock_irqrestore(&stats->lock, flags); 1803 } 1804 1805 callback = ent->callback; 1806 context = ent->context; 1807 err = ent->ret ? : ent->status; 1808 if (err > 0) /* Failed in FW, command didn't execute */ 1809 err = deliv_status_to_err(err); 1810 1811 if (!err) 1812 err = mlx5_copy_from_msg(ent->uout, 1813 ent->out, 1814 ent->uout_size); 1815 1816 mlx5_free_cmd_msg(dev, ent->out); 1817 free_msg(dev, ent->in); 1818 1819 /* final consumer is done, release ent */ 1820 cmd_ent_put(ent); 1821 callback(err, context); 1822 } else { 1823 /* release wait_func() so mlx5_cmd_invoke() 1824 * can make the final ent_put() 1825 */ 1826 complete(&ent->done); 1827 } 1828 } 1829 } 1830} 1831 1832#define MLX5_MAX_MANAGE_PAGES_CMD_ENT 1 1833#define MLX5_CMD_MASK ((1UL << (cmd->vars.max_reg_cmds + \ 1834 MLX5_MAX_MANAGE_PAGES_CMD_ENT)) - 1) 1835 1836static void mlx5_cmd_trigger_completions(struct mlx5_core_dev *dev) 1837{ 1838 struct mlx5_cmd *cmd = &dev->cmd; 1839 unsigned long bitmask; 1840 unsigned long flags; 1841 u64 vector; 1842 int i; 1843 1844 /* wait for pending handlers to complete */ 1845 mlx5_eq_synchronize_cmd_irq(dev); 1846 spin_lock_irqsave(&dev->cmd.alloc_lock, flags); 1847 vector = ~dev->cmd.vars.bitmask & MLX5_CMD_MASK; 1848 if (!vector) 1849 goto no_trig; 1850 1851 bitmask = vector; 1852 /* we must increment the allocated entries refcount before triggering the completions 1853 * to guarantee pending commands will not get freed in the meanwhile. 1854 * For that reason, it also has to be done inside the alloc_lock. 1855 */ 1856 for_each_set_bit(i, &bitmask, (1 << cmd->vars.log_sz)) 1857 cmd_ent_get(cmd->ent_arr[i]); 1858 vector |= MLX5_TRIGGERED_CMD_COMP; 1859 spin_unlock_irqrestore(&dev->cmd.alloc_lock, flags); 1860 1861 mlx5_core_dbg(dev, "vector 0x%llx\n", vector); 1862 mlx5_cmd_comp_handler(dev, vector, true); 1863 for_each_set_bit(i, &bitmask, (1 << cmd->vars.log_sz)) 1864 cmd_ent_put(cmd->ent_arr[i]); 1865 return; 1866 1867no_trig: 1868 spin_unlock_irqrestore(&dev->cmd.alloc_lock, flags); 1869} 1870 1871void mlx5_cmd_flush(struct mlx5_core_dev *dev) 1872{ 1873 struct mlx5_cmd *cmd = &dev->cmd; 1874 int i; 1875 1876 for (i = 0; i < cmd->vars.max_reg_cmds; i++) { 1877 while (down_trylock(&cmd->vars.sem)) { 1878 mlx5_cmd_trigger_completions(dev); 1879 cond_resched(); 1880 } 1881 } 1882 1883 while (down_trylock(&cmd->vars.pages_sem)) { 1884 mlx5_cmd_trigger_completions(dev); 1885 cond_resched(); 1886 } 1887 1888 /* Unlock cmdif */ 1889 up(&cmd->vars.pages_sem); 1890 for (i = 0; i < cmd->vars.max_reg_cmds; i++) 1891 up(&cmd->vars.sem); 1892} 1893 1894static struct mlx5_cmd_msg *alloc_msg(struct mlx5_core_dev *dev, int in_size, 1895 gfp_t gfp) 1896{ 1897 struct mlx5_cmd_msg *msg = ERR_PTR(-ENOMEM); 1898 struct cmd_msg_cache *ch = NULL; 1899 struct mlx5_cmd *cmd = &dev->cmd; 1900 int i; 1901 1902 if (in_size <= 16) 1903 goto cache_miss; 1904 1905 for (i = 0; i < dev->profile.num_cmd_caches; i++) { 1906 ch = &cmd->cache[i]; 1907 if (in_size > ch->max_inbox_size) 1908 continue; 1909 spin_lock_irq(&ch->lock); 1910 if (list_empty(&ch->head)) { 1911 spin_unlock_irq(&ch->lock); 1912 continue; 1913 } 1914 msg = list_entry(ch->head.next, typeof(*msg), list); 1915 /* For cached lists, we must explicitly state what is 1916 * the real size 1917 */ 1918 msg->len = in_size; 1919 list_del(&msg->list); 1920 spin_unlock_irq(&ch->lock); 1921 break; 1922 } 1923 1924 if (!IS_ERR(msg)) 1925 return msg; 1926 1927cache_miss: 1928 msg = mlx5_alloc_cmd_msg(dev, gfp, in_size, 0); 1929 return msg; 1930} 1931 1932static int is_manage_pages(void *in) 1933{ 1934 return in_to_opcode(in) == MLX5_CMD_OP_MANAGE_PAGES; 1935} 1936 1937static bool mlx5_has_privileged_uid(struct mlx5_core_dev *dev) 1938{ 1939 return !xa_empty(&dev->cmd.vars.privileged_uids); 1940} 1941 1942static bool mlx5_cmd_is_privileged_uid(struct mlx5_core_dev *dev, 1943 u16 uid) 1944{ 1945 return !!xa_load(&dev->cmd.vars.privileged_uids, uid); 1946} 1947 1948/* Notes: 1949 * 1. Callback functions may not sleep 1950 * 2. Page queue commands do not support asynchrous completion 1951 */ 1952static int cmd_exec(struct mlx5_core_dev *dev, void *in, int in_size, void *out, 1953 int out_size, mlx5_cmd_cbk_t callback, void *context, 1954 bool force_polling) 1955{ 1956 struct mlx5_cmd_msg *inb, *outb; 1957 u16 opcode = in_to_opcode(in); 1958 bool throttle_locked = false; 1959 bool unpriv_locked = false; 1960 u16 uid = in_to_uid(in); 1961 int pages_queue; 1962 gfp_t gfp; 1963 u8 token; 1964 int err; 1965 1966 if (mlx5_cmd_is_down(dev) || !opcode_allowed(&dev->cmd, opcode)) 1967 return -ENXIO; 1968 1969 if (!callback) { 1970 /* The semaphore is already held for callback commands. It was 1971 * acquired in mlx5_cmd_exec_cb() 1972 */ 1973 if (uid && mlx5_has_privileged_uid(dev)) { 1974 if (!mlx5_cmd_is_privileged_uid(dev, uid)) { 1975 unpriv_locked = true; 1976 down(&dev->cmd.vars.unprivileged_sem); 1977 } 1978 } else if (mlx5_cmd_is_throttle_opcode(opcode)) { 1979 throttle_locked = true; 1980 down(&dev->cmd.vars.throttle_sem); 1981 } 1982 } 1983 1984 pages_queue = is_manage_pages(in); 1985 gfp = callback ? GFP_ATOMIC : GFP_KERNEL; 1986 1987 inb = alloc_msg(dev, in_size, gfp); 1988 if (IS_ERR(inb)) { 1989 err = PTR_ERR(inb); 1990 goto out_up; 1991 } 1992 1993 token = alloc_token(&dev->cmd); 1994 1995 err = mlx5_copy_to_msg(inb, in, in_size, token); 1996 if (err) { 1997 mlx5_core_warn(dev, "err %d\n", err); 1998 goto out_in; 1999 } 2000 2001 outb = mlx5_alloc_cmd_msg(dev, gfp, out_size, token); 2002 if (IS_ERR(outb)) { 2003 err = PTR_ERR(outb); 2004 goto out_in; 2005 } 2006 2007 err = mlx5_cmd_invoke(dev, inb, outb, out, out_size, callback, context, 2008 pages_queue, token, force_polling); 2009 if (callback && !err) 2010 return 0; 2011 2012 if (err > 0) /* Failed in FW, command didn't execute */ 2013 err = deliv_status_to_err(err); 2014 2015 if (err) 2016 goto out_out; 2017 2018 /* command completed by FW */ 2019 err = mlx5_copy_from_msg(out, outb, out_size); 2020out_out: 2021 mlx5_free_cmd_msg(dev, outb); 2022out_in: 2023 free_msg(dev, inb); 2024out_up: 2025 if (throttle_locked) 2026 up(&dev->cmd.vars.throttle_sem); 2027 if (unpriv_locked) 2028 up(&dev->cmd.vars.unprivileged_sem); 2029 2030 return err; 2031} 2032 2033static void mlx5_cmd_err_trace(struct mlx5_core_dev *dev, u16 opcode, u16 op_mod, void *out) 2034{ 2035 u32 syndrome = MLX5_GET(mbox_out, out, syndrome); 2036 u8 status = MLX5_GET(mbox_out, out, status); 2037 2038 trace_mlx5_cmd(mlx5_command_str(opcode), opcode, op_mod, 2039 cmd_status_str(status), status, syndrome, 2040 cmd_status_to_err(status)); 2041} 2042 2043static void cmd_status_log(struct mlx5_core_dev *dev, u16 opcode, u8 status, 2044 u32 syndrome, int err) 2045{ 2046 const char *namep = mlx5_command_str(opcode); 2047 struct mlx5_cmd_stats *stats; 2048 unsigned long flags; 2049 2050 if (!err || !(strcmp(namep, "unknown command opcode"))) 2051 return; 2052 2053 stats = xa_load(&dev->cmd.stats, opcode); 2054 if (!stats) 2055 return; 2056 spin_lock_irqsave(&stats->lock, flags); 2057 stats->failed++; 2058 if (err < 0) 2059 stats->last_failed_errno = -err; 2060 if (err == -EREMOTEIO) { 2061 stats->failed_mbox_status++; 2062 stats->last_failed_mbox_status = status; 2063 stats->last_failed_syndrome = syndrome; 2064 } 2065 spin_unlock_irqrestore(&stats->lock, flags); 2066} 2067 2068/* preserve -EREMOTEIO for outbox.status != OK, otherwise return err as is */ 2069static int cmd_status_err(struct mlx5_core_dev *dev, int err, u16 opcode, u16 op_mod, void *out) 2070{ 2071 u32 syndrome = MLX5_GET(mbox_out, out, syndrome); 2072 u8 status = MLX5_GET(mbox_out, out, status); 2073 2074 if (err == -EREMOTEIO) /* -EREMOTEIO is preserved */ 2075 err = -EIO; 2076 2077 if (!err && status != MLX5_CMD_STAT_OK) { 2078 err = -EREMOTEIO; 2079 mlx5_cmd_err_trace(dev, opcode, op_mod, out); 2080 } 2081 2082 cmd_status_log(dev, opcode, status, syndrome, err); 2083 return err; 2084} 2085 2086/** 2087 * mlx5_cmd_do - Executes a fw command, wait for completion. 2088 * Unlike mlx5_cmd_exec, this function will not translate or intercept 2089 * outbox.status and will return -EREMOTEIO when 2090 * outbox.status != MLX5_CMD_STAT_OK 2091 * 2092 * @dev: mlx5 core device 2093 * @in: inbox mlx5_ifc command buffer 2094 * @in_size: inbox buffer size 2095 * @out: outbox mlx5_ifc buffer 2096 * @out_size: outbox size 2097 * 2098 * @return: 2099 * -EREMOTEIO : Command executed by FW, outbox.status != MLX5_CMD_STAT_OK. 2100 * Caller must check FW outbox status. 2101 * 0 : Command execution successful, outbox.status == MLX5_CMD_STAT_OK. 2102 * < 0 : Command execution couldn't be performed by firmware or driver 2103 */ 2104int mlx5_cmd_do(struct mlx5_core_dev *dev, void *in, int in_size, void *out, int out_size) 2105{ 2106 int err = cmd_exec(dev, in, in_size, out, out_size, NULL, NULL, false); 2107 u16 op_mod = MLX5_GET(mbox_in, in, op_mod); 2108 u16 opcode = in_to_opcode(in); 2109 2110 return cmd_status_err(dev, err, opcode, op_mod, out); 2111} 2112EXPORT_SYMBOL(mlx5_cmd_do); 2113 2114/** 2115 * mlx5_cmd_exec - Executes a fw command, wait for completion 2116 * 2117 * @dev: mlx5 core device 2118 * @in: inbox mlx5_ifc command buffer 2119 * @in_size: inbox buffer size 2120 * @out: outbox mlx5_ifc buffer 2121 * @out_size: outbox size 2122 * 2123 * @return: 0 if no error, FW command execution was successful 2124 * and outbox status is ok. 2125 */ 2126int mlx5_cmd_exec(struct mlx5_core_dev *dev, void *in, int in_size, void *out, 2127 int out_size) 2128{ 2129 int err = mlx5_cmd_do(dev, in, in_size, out, out_size); 2130 2131 return mlx5_cmd_check(dev, err, in, out); 2132} 2133EXPORT_SYMBOL(mlx5_cmd_exec); 2134 2135/** 2136 * mlx5_cmd_exec_polling - Executes a fw command, poll for completion 2137 * Needed for driver force teardown, when command completion EQ 2138 * will not be available to complete the command 2139 * 2140 * @dev: mlx5 core device 2141 * @in: inbox mlx5_ifc command buffer 2142 * @in_size: inbox buffer size 2143 * @out: outbox mlx5_ifc buffer 2144 * @out_size: outbox size 2145 * 2146 * @return: 0 if no error, FW command execution was successful 2147 * and outbox status is ok. 2148 */ 2149int mlx5_cmd_exec_polling(struct mlx5_core_dev *dev, void *in, int in_size, 2150 void *out, int out_size) 2151{ 2152 int err = cmd_exec(dev, in, in_size, out, out_size, NULL, NULL, true); 2153 u16 op_mod = MLX5_GET(mbox_in, in, op_mod); 2154 u16 opcode = in_to_opcode(in); 2155 2156 err = cmd_status_err(dev, err, opcode, op_mod, out); 2157 return mlx5_cmd_check(dev, err, in, out); 2158} 2159EXPORT_SYMBOL(mlx5_cmd_exec_polling); 2160 2161void mlx5_cmd_init_async_ctx(struct mlx5_core_dev *dev, 2162 struct mlx5_async_ctx *ctx) 2163{ 2164 ctx->dev = dev; 2165 /* Starts at 1 to avoid doing wake_up if we are not cleaning up */ 2166 atomic_set(&ctx->num_inflight, 1); 2167 init_completion(&ctx->inflight_done); 2168} 2169EXPORT_SYMBOL(mlx5_cmd_init_async_ctx); 2170 2171/** 2172 * mlx5_cmd_cleanup_async_ctx - Clean up an async_ctx 2173 * @ctx: The ctx to clean 2174 * 2175 * Upon return all callbacks given to mlx5_cmd_exec_cb() have been called. The 2176 * caller must ensure that mlx5_cmd_exec_cb() is not called during or after 2177 * the call mlx5_cleanup_async_ctx(). 2178 */ 2179void mlx5_cmd_cleanup_async_ctx(struct mlx5_async_ctx *ctx) 2180{ 2181 if (!atomic_dec_and_test(&ctx->num_inflight)) 2182 wait_for_completion(&ctx->inflight_done); 2183} 2184EXPORT_SYMBOL(mlx5_cmd_cleanup_async_ctx); 2185 2186static void mlx5_cmd_exec_cb_handler(int status, void *_work) 2187{ 2188 struct mlx5_async_work *work = _work; 2189 struct mlx5_async_ctx *ctx; 2190 struct mlx5_core_dev *dev; 2191 bool throttle_locked; 2192 bool unpriv_locked; 2193 2194 ctx = work->ctx; 2195 dev = ctx->dev; 2196 throttle_locked = work->throttle_locked; 2197 unpriv_locked = work->unpriv_locked; 2198 status = cmd_status_err(dev, status, work->opcode, work->op_mod, work->out); 2199 work->user_callback(status, work); 2200 /* Can't access "work" from this point on. It could have been freed in 2201 * the callback. 2202 */ 2203 if (throttle_locked) 2204 up(&dev->cmd.vars.throttle_sem); 2205 if (unpriv_locked) 2206 up(&dev->cmd.vars.unprivileged_sem); 2207 if (atomic_dec_and_test(&ctx->num_inflight)) 2208 complete(&ctx->inflight_done); 2209} 2210 2211int mlx5_cmd_exec_cb(struct mlx5_async_ctx *ctx, void *in, int in_size, 2212 void *out, int out_size, mlx5_async_cbk_t callback, 2213 struct mlx5_async_work *work) 2214{ 2215 struct mlx5_core_dev *dev = ctx->dev; 2216 u16 uid; 2217 int ret; 2218 2219 work->ctx = ctx; 2220 work->user_callback = callback; 2221 work->opcode = in_to_opcode(in); 2222 work->op_mod = MLX5_GET(mbox_in, in, op_mod); 2223 work->out = out; 2224 work->throttle_locked = false; 2225 work->unpriv_locked = false; 2226 uid = in_to_uid(in); 2227 2228 if (WARN_ON(!atomic_inc_not_zero(&ctx->num_inflight))) 2229 return -EIO; 2230 2231 if (uid && mlx5_has_privileged_uid(dev)) { 2232 if (!mlx5_cmd_is_privileged_uid(dev, uid)) { 2233 if (down_trylock(&dev->cmd.vars.unprivileged_sem)) { 2234 ret = -EBUSY; 2235 goto dec_num_inflight; 2236 } 2237 work->unpriv_locked = true; 2238 } 2239 } else if (mlx5_cmd_is_throttle_opcode(in_to_opcode(in))) { 2240 if (down_trylock(&dev->cmd.vars.throttle_sem)) { 2241 ret = -EBUSY; 2242 goto dec_num_inflight; 2243 } 2244 work->throttle_locked = true; 2245 } 2246 2247 ret = cmd_exec(dev, in, in_size, out, out_size, 2248 mlx5_cmd_exec_cb_handler, work, false); 2249 if (ret) 2250 goto sem_up; 2251 2252 return 0; 2253 2254sem_up: 2255 if (work->throttle_locked) 2256 up(&dev->cmd.vars.throttle_sem); 2257 if (work->unpriv_locked) 2258 up(&dev->cmd.vars.unprivileged_sem); 2259dec_num_inflight: 2260 if (atomic_dec_and_test(&ctx->num_inflight)) 2261 complete(&ctx->inflight_done); 2262 2263 return ret; 2264} 2265EXPORT_SYMBOL(mlx5_cmd_exec_cb); 2266 2267int mlx5_cmd_allow_other_vhca_access(struct mlx5_core_dev *dev, 2268 struct mlx5_cmd_allow_other_vhca_access_attr *attr) 2269{ 2270 u32 out[MLX5_ST_SZ_DW(allow_other_vhca_access_out)] = {}; 2271 u32 in[MLX5_ST_SZ_DW(allow_other_vhca_access_in)] = {}; 2272 void *key; 2273 2274 MLX5_SET(allow_other_vhca_access_in, 2275 in, opcode, MLX5_CMD_OP_ALLOW_OTHER_VHCA_ACCESS); 2276 MLX5_SET(allow_other_vhca_access_in, 2277 in, object_type_to_be_accessed, attr->obj_type); 2278 MLX5_SET(allow_other_vhca_access_in, 2279 in, object_id_to_be_accessed, attr->obj_id); 2280 2281 key = MLX5_ADDR_OF(allow_other_vhca_access_in, in, access_key); 2282 memcpy(key, attr->access_key, sizeof(attr->access_key)); 2283 2284 return mlx5_cmd_exec(dev, in, sizeof(in), out, sizeof(out)); 2285} 2286 2287int mlx5_cmd_alias_obj_create(struct mlx5_core_dev *dev, 2288 struct mlx5_cmd_alias_obj_create_attr *alias_attr, 2289 u32 *obj_id) 2290{ 2291 u32 out[MLX5_ST_SZ_DW(general_obj_out_cmd_hdr)] = {}; 2292 u32 in[MLX5_ST_SZ_DW(create_alias_obj_in)] = {}; 2293 void *param; 2294 void *attr; 2295 void *key; 2296 int ret; 2297 2298 attr = MLX5_ADDR_OF(create_alias_obj_in, in, hdr); 2299 MLX5_SET(general_obj_in_cmd_hdr, 2300 attr, opcode, MLX5_CMD_OP_CREATE_GENERAL_OBJECT); 2301 MLX5_SET(general_obj_in_cmd_hdr, 2302 attr, obj_type, alias_attr->obj_type); 2303 param = MLX5_ADDR_OF(general_obj_in_cmd_hdr, in, op_param); 2304 MLX5_SET(general_obj_create_param, param, alias_object, 1); 2305 2306 attr = MLX5_ADDR_OF(create_alias_obj_in, in, alias_ctx); 2307 MLX5_SET(alias_context, attr, vhca_id_to_be_accessed, alias_attr->vhca_id); 2308 MLX5_SET(alias_context, attr, object_id_to_be_accessed, alias_attr->obj_id); 2309 2310 key = MLX5_ADDR_OF(alias_context, attr, access_key); 2311 memcpy(key, alias_attr->access_key, sizeof(alias_attr->access_key)); 2312 2313 ret = mlx5_cmd_exec(dev, in, sizeof(in), out, sizeof(out)); 2314 if (ret) 2315 return ret; 2316 2317 *obj_id = MLX5_GET(general_obj_out_cmd_hdr, out, obj_id); 2318 2319 return 0; 2320} 2321 2322int mlx5_cmd_alias_obj_destroy(struct mlx5_core_dev *dev, u32 obj_id, 2323 u16 obj_type) 2324{ 2325 u32 out[MLX5_ST_SZ_DW(general_obj_out_cmd_hdr)] = {}; 2326 u32 in[MLX5_ST_SZ_DW(general_obj_in_cmd_hdr)] = {}; 2327 2328 MLX5_SET(general_obj_in_cmd_hdr, in, opcode, MLX5_CMD_OP_DESTROY_GENERAL_OBJECT); 2329 MLX5_SET(general_obj_in_cmd_hdr, in, obj_type, obj_type); 2330 MLX5_SET(general_obj_in_cmd_hdr, in, obj_id, obj_id); 2331 2332 return mlx5_cmd_exec(dev, in, sizeof(in), out, sizeof(out)); 2333} 2334 2335static void destroy_msg_cache(struct mlx5_core_dev *dev) 2336{ 2337 struct cmd_msg_cache *ch; 2338 struct mlx5_cmd_msg *msg; 2339 struct mlx5_cmd_msg *n; 2340 int i; 2341 2342 for (i = 0; i < dev->profile.num_cmd_caches; i++) { 2343 ch = &dev->cmd.cache[i]; 2344 list_for_each_entry_safe(msg, n, &ch->head, list) { 2345 list_del(&msg->list); 2346 mlx5_free_cmd_msg(dev, msg); 2347 } 2348 } 2349} 2350 2351static unsigned cmd_cache_num_ent[MLX5_NUM_COMMAND_CACHES] = { 2352 512, 32, 16, 8, 2 2353}; 2354 2355static unsigned cmd_cache_ent_size[MLX5_NUM_COMMAND_CACHES] = { 2356 16 + MLX5_CMD_DATA_BLOCK_SIZE, 2357 16 + MLX5_CMD_DATA_BLOCK_SIZE * 2, 2358 16 + MLX5_CMD_DATA_BLOCK_SIZE * 16, 2359 16 + MLX5_CMD_DATA_BLOCK_SIZE * 256, 2360 16 + MLX5_CMD_DATA_BLOCK_SIZE * 512, 2361}; 2362 2363static void create_msg_cache(struct mlx5_core_dev *dev) 2364{ 2365 struct mlx5_cmd *cmd = &dev->cmd; 2366 struct cmd_msg_cache *ch; 2367 struct mlx5_cmd_msg *msg; 2368 int i; 2369 int k; 2370 2371 /* Initialize and fill the caches with initial entries */ 2372 for (k = 0; k < dev->profile.num_cmd_caches; k++) { 2373 ch = &cmd->cache[k]; 2374 spin_lock_init(&ch->lock); 2375 INIT_LIST_HEAD(&ch->head); 2376 ch->num_ent = cmd_cache_num_ent[k]; 2377 ch->max_inbox_size = cmd_cache_ent_size[k]; 2378 for (i = 0; i < ch->num_ent; i++) { 2379 msg = mlx5_alloc_cmd_msg(dev, GFP_KERNEL | __GFP_NOWARN, 2380 ch->max_inbox_size, 0); 2381 if (IS_ERR(msg)) 2382 break; 2383 msg->parent = ch; 2384 list_add_tail(&msg->list, &ch->head); 2385 } 2386 } 2387} 2388 2389static int alloc_cmd_page(struct mlx5_core_dev *dev, struct mlx5_cmd *cmd) 2390{ 2391 cmd->cmd_alloc_buf = dma_alloc_coherent(mlx5_core_dma_dev(dev), MLX5_ADAPTER_PAGE_SIZE, 2392 &cmd->alloc_dma, GFP_KERNEL); 2393 if (!cmd->cmd_alloc_buf) 2394 return -ENOMEM; 2395 2396 /* make sure it is aligned to 4K */ 2397 if (!((uintptr_t)cmd->cmd_alloc_buf & (MLX5_ADAPTER_PAGE_SIZE - 1))) { 2398 cmd->cmd_buf = cmd->cmd_alloc_buf; 2399 cmd->dma = cmd->alloc_dma; 2400 cmd->alloc_size = MLX5_ADAPTER_PAGE_SIZE; 2401 return 0; 2402 } 2403 2404 dma_free_coherent(mlx5_core_dma_dev(dev), MLX5_ADAPTER_PAGE_SIZE, cmd->cmd_alloc_buf, 2405 cmd->alloc_dma); 2406 cmd->cmd_alloc_buf = dma_alloc_coherent(mlx5_core_dma_dev(dev), 2407 2 * MLX5_ADAPTER_PAGE_SIZE - 1, 2408 &cmd->alloc_dma, GFP_KERNEL); 2409 if (!cmd->cmd_alloc_buf) 2410 return -ENOMEM; 2411 2412 cmd->cmd_buf = PTR_ALIGN(cmd->cmd_alloc_buf, MLX5_ADAPTER_PAGE_SIZE); 2413 cmd->dma = ALIGN(cmd->alloc_dma, MLX5_ADAPTER_PAGE_SIZE); 2414 cmd->alloc_size = 2 * MLX5_ADAPTER_PAGE_SIZE - 1; 2415 return 0; 2416} 2417 2418static void free_cmd_page(struct mlx5_core_dev *dev, struct mlx5_cmd *cmd) 2419{ 2420 dma_free_coherent(mlx5_core_dma_dev(dev), cmd->alloc_size, cmd->cmd_alloc_buf, 2421 cmd->alloc_dma); 2422} 2423 2424static u16 cmdif_rev(struct mlx5_core_dev *dev) 2425{ 2426 return ioread32be(&dev->iseg->cmdif_rev_fw_sub) >> 16; 2427} 2428 2429int mlx5_cmd_init(struct mlx5_core_dev *dev) 2430{ 2431 struct mlx5_cmd *cmd = &dev->cmd; 2432 2433 cmd->checksum_disabled = 1; 2434 2435 spin_lock_init(&cmd->alloc_lock); 2436 spin_lock_init(&cmd->token_lock); 2437 2438 set_wqname(dev); 2439 cmd->wq = create_singlethread_workqueue(cmd->wq_name); 2440 if (!cmd->wq) { 2441 mlx5_core_err(dev, "failed to create command workqueue\n"); 2442 return -ENOMEM; 2443 } 2444 2445 mlx5_cmdif_debugfs_init(dev); 2446 2447 return 0; 2448} 2449 2450void mlx5_cmd_cleanup(struct mlx5_core_dev *dev) 2451{ 2452 struct mlx5_cmd *cmd = &dev->cmd; 2453 2454 mlx5_cmdif_debugfs_cleanup(dev); 2455 destroy_workqueue(cmd->wq); 2456} 2457 2458int mlx5_cmd_enable(struct mlx5_core_dev *dev) 2459{ 2460 int size = sizeof(struct mlx5_cmd_prot_block); 2461 int align = roundup_pow_of_two(size); 2462 struct mlx5_cmd *cmd = &dev->cmd; 2463 u32 cmd_h, cmd_l; 2464 int err; 2465 2466 memset(&cmd->vars, 0, sizeof(cmd->vars)); 2467 cmd->vars.cmdif_rev = cmdif_rev(dev); 2468 if (cmd->vars.cmdif_rev != CMD_IF_REV) { 2469 mlx5_core_err(dev, 2470 "Driver cmdif rev(%d) differs from firmware's(%d)\n", 2471 CMD_IF_REV, cmd->vars.cmdif_rev); 2472 return -EINVAL; 2473 } 2474 2475 cmd_l = ioread32be(&dev->iseg->cmdq_addr_l_sz) & 0xff; 2476 cmd->vars.log_sz = cmd_l >> 4 & 0xf; 2477 cmd->vars.log_stride = cmd_l & 0xf; 2478 if (1 << cmd->vars.log_sz > MLX5_MAX_COMMANDS) { 2479 mlx5_core_err(dev, "firmware reports too many outstanding commands %d\n", 2480 1 << cmd->vars.log_sz); 2481 return -EINVAL; 2482 } 2483 2484 if (cmd->vars.log_sz + cmd->vars.log_stride > MLX5_ADAPTER_PAGE_SHIFT) { 2485 mlx5_core_err(dev, "command queue size overflow\n"); 2486 return -EINVAL; 2487 } 2488 2489 cmd->state = MLX5_CMDIF_STATE_DOWN; 2490 cmd->vars.max_reg_cmds = (1 << cmd->vars.log_sz) - 1; 2491 cmd->vars.bitmask = MLX5_CMD_MASK; 2492 2493 sema_init(&cmd->vars.sem, cmd->vars.max_reg_cmds); 2494 sema_init(&cmd->vars.pages_sem, 1); 2495 sema_init(&cmd->vars.throttle_sem, DIV_ROUND_UP(cmd->vars.max_reg_cmds, 2)); 2496 sema_init(&cmd->vars.unprivileged_sem, 2497 DIV_ROUND_UP(cmd->vars.max_reg_cmds, 2)); 2498 2499 xa_init(&cmd->vars.privileged_uids); 2500 2501 cmd->pool = dma_pool_create("mlx5_cmd", mlx5_core_dma_dev(dev), size, align, 0); 2502 if (!cmd->pool) { 2503 err = -ENOMEM; 2504 goto err_destroy_xa; 2505 } 2506 2507 err = alloc_cmd_page(dev, cmd); 2508 if (err) 2509 goto err_free_pool; 2510 2511 cmd_h = (u32)((u64)(cmd->dma) >> 32); 2512 cmd_l = (u32)(cmd->dma); 2513 if (cmd_l & 0xfff) { 2514 mlx5_core_err(dev, "invalid command queue address\n"); 2515 err = -ENOMEM; 2516 goto err_cmd_page; 2517 } 2518 2519 iowrite32be(cmd_h, &dev->iseg->cmdq_addr_h); 2520 iowrite32be(cmd_l, &dev->iseg->cmdq_addr_l_sz); 2521 2522 /* Make sure firmware sees the complete address before we proceed */ 2523 wmb(); 2524 2525 mlx5_core_dbg(dev, "descriptor at dma 0x%llx\n", (unsigned long long)(cmd->dma)); 2526 2527 cmd->mode = CMD_MODE_POLLING; 2528 cmd->allowed_opcode = CMD_ALLOWED_OPCODE_ALL; 2529 2530 create_msg_cache(dev); 2531 create_debugfs_files(dev); 2532 2533 return 0; 2534 2535err_cmd_page: 2536 free_cmd_page(dev, cmd); 2537err_free_pool: 2538 dma_pool_destroy(cmd->pool); 2539err_destroy_xa: 2540 xa_destroy(&dev->cmd.vars.privileged_uids); 2541 return err; 2542} 2543 2544void mlx5_cmd_disable(struct mlx5_core_dev *dev) 2545{ 2546 struct mlx5_cmd *cmd = &dev->cmd; 2547 2548 flush_workqueue(cmd->wq); 2549 clean_debug_files(dev); 2550 destroy_msg_cache(dev); 2551 free_cmd_page(dev, cmd); 2552 dma_pool_destroy(cmd->pool); 2553 xa_destroy(&dev->cmd.vars.privileged_uids); 2554} 2555 2556void mlx5_cmd_set_state(struct mlx5_core_dev *dev, 2557 enum mlx5_cmdif_state cmdif_state) 2558{ 2559 dev->cmd.state = cmdif_state; 2560} 2561 2562int mlx5_cmd_add_privileged_uid(struct mlx5_core_dev *dev, u16 uid) 2563{ 2564 return xa_insert(&dev->cmd.vars.privileged_uids, uid, 2565 xa_mk_value(uid), GFP_KERNEL); 2566} 2567EXPORT_SYMBOL(mlx5_cmd_add_privileged_uid); 2568 2569void mlx5_cmd_remove_privileged_uid(struct mlx5_core_dev *dev, u16 uid) 2570{ 2571 void *data = xa_erase(&dev->cmd.vars.privileged_uids, uid); 2572 2573 WARN(!data, "Privileged UID %u does not exist\n", uid); 2574} 2575EXPORT_SYMBOL(mlx5_cmd_remove_privileged_uid);
~/
Read-only file preview.