15a2cc190SJeff Kirsher /* 25a2cc190SJeff Kirsher * Copyright (c) 2004, 2005 Topspin Communications. All rights reserved. 35a2cc190SJeff Kirsher * Copyright (c) 2005, 2006, 2007, 2008 Mellanox Technologies. All rights reserved. 45a2cc190SJeff Kirsher * Copyright (c) 2005, 2006, 2007 Cisco Systems, Inc. All rights reserved. 55a2cc190SJeff Kirsher * 65a2cc190SJeff Kirsher * This software is available to you under a choice of one of two 75a2cc190SJeff Kirsher * licenses. You may choose to be licensed under the terms of the GNU 85a2cc190SJeff Kirsher * General Public License (GPL) Version 2, available from the file 95a2cc190SJeff Kirsher * COPYING in the main directory of this source tree, or the 105a2cc190SJeff Kirsher * OpenIB.org BSD license below: 115a2cc190SJeff Kirsher * 125a2cc190SJeff Kirsher * Redistribution and use in source and binary forms, with or 135a2cc190SJeff Kirsher * without modification, are permitted provided that the following 145a2cc190SJeff Kirsher * conditions are met: 155a2cc190SJeff Kirsher * 165a2cc190SJeff Kirsher * - Redistributions of source code must retain the above 175a2cc190SJeff Kirsher * copyright notice, this list of conditions and the following 185a2cc190SJeff Kirsher * disclaimer. 195a2cc190SJeff Kirsher * 205a2cc190SJeff Kirsher * - Redistributions in binary form must reproduce the above 215a2cc190SJeff Kirsher * copyright notice, this list of conditions and the following 225a2cc190SJeff Kirsher * disclaimer in the documentation and/or other materials 235a2cc190SJeff Kirsher * provided with the distribution. 245a2cc190SJeff Kirsher * 255a2cc190SJeff Kirsher * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 265a2cc190SJeff Kirsher * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 275a2cc190SJeff Kirsher * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 285a2cc190SJeff Kirsher * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 295a2cc190SJeff Kirsher * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 305a2cc190SJeff Kirsher * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 315a2cc190SJeff Kirsher * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 325a2cc190SJeff Kirsher * SOFTWARE. 335a2cc190SJeff Kirsher */ 345a2cc190SJeff Kirsher 355a2cc190SJeff Kirsher #include <linux/sched.h> 365a2cc190SJeff Kirsher #include <linux/slab.h> 37ee40fa06SPaul Gortmaker #include <linux/export.h> 385a2cc190SJeff Kirsher #include <linux/pci.h> 395a2cc190SJeff Kirsher #include <linux/errno.h> 405a2cc190SJeff Kirsher 415a2cc190SJeff Kirsher #include <linux/mlx4/cmd.h> 42948e306dSRony Efraim #include <linux/mlx4/device.h> 43e8f081aaSYevgeny Petrilin #include <linux/semaphore.h> 440a9a0188SJack Morgenstein #include <rdma/ib_smi.h> 455a2cc190SJeff Kirsher 465a2cc190SJeff Kirsher #include <asm/io.h> 475a2cc190SJeff Kirsher 485a2cc190SJeff Kirsher #include "mlx4.h" 49e8f081aaSYevgeny Petrilin #include "fw.h" 505a2cc190SJeff Kirsher 515a2cc190SJeff Kirsher #define CMD_POLL_TOKEN 0xffff 52e8f081aaSYevgeny Petrilin #define INBOX_MASK 0xffffffffffffff00ULL 53e8f081aaSYevgeny Petrilin 54e8f081aaSYevgeny Petrilin #define CMD_CHAN_VER 1 55e8f081aaSYevgeny Petrilin #define CMD_CHAN_IF_REV 1 565a2cc190SJeff Kirsher 575a2cc190SJeff Kirsher enum { 585a2cc190SJeff Kirsher /* command completed successfully: */ 595a2cc190SJeff Kirsher CMD_STAT_OK = 0x00, 605a2cc190SJeff Kirsher /* Internal error (such as a bus error) occurred while processing command: */ 615a2cc190SJeff Kirsher CMD_STAT_INTERNAL_ERR = 0x01, 625a2cc190SJeff Kirsher /* Operation/command not supported or opcode modifier not supported: */ 635a2cc190SJeff Kirsher CMD_STAT_BAD_OP = 0x02, 645a2cc190SJeff Kirsher /* Parameter not supported or parameter out of range: */ 655a2cc190SJeff Kirsher CMD_STAT_BAD_PARAM = 0x03, 665a2cc190SJeff Kirsher /* System not enabled or bad system state: */ 675a2cc190SJeff Kirsher CMD_STAT_BAD_SYS_STATE = 0x04, 685a2cc190SJeff Kirsher /* Attempt to access reserved or unallocaterd resource: */ 695a2cc190SJeff Kirsher CMD_STAT_BAD_RESOURCE = 0x05, 705a2cc190SJeff Kirsher /* Requested resource is currently executing a command, or is otherwise busy: */ 715a2cc190SJeff Kirsher CMD_STAT_RESOURCE_BUSY = 0x06, 725a2cc190SJeff Kirsher /* Required capability exceeds device limits: */ 735a2cc190SJeff Kirsher CMD_STAT_EXCEED_LIM = 0x08, 745a2cc190SJeff Kirsher /* Resource is not in the appropriate state or ownership: */ 755a2cc190SJeff Kirsher CMD_STAT_BAD_RES_STATE = 0x09, 765a2cc190SJeff Kirsher /* Index out of range: */ 775a2cc190SJeff Kirsher CMD_STAT_BAD_INDEX = 0x0a, 785a2cc190SJeff Kirsher /* FW image corrupted: */ 795a2cc190SJeff Kirsher CMD_STAT_BAD_NVMEM = 0x0b, 805a2cc190SJeff Kirsher /* Error in ICM mapping (e.g. not enough auxiliary ICM pages to execute command): */ 815a2cc190SJeff Kirsher CMD_STAT_ICM_ERROR = 0x0c, 825a2cc190SJeff Kirsher /* Attempt to modify a QP/EE which is not in the presumed state: */ 835a2cc190SJeff Kirsher CMD_STAT_BAD_QP_STATE = 0x10, 845a2cc190SJeff Kirsher /* Bad segment parameters (Address/Size): */ 855a2cc190SJeff Kirsher CMD_STAT_BAD_SEG_PARAM = 0x20, 865a2cc190SJeff Kirsher /* Memory Region has Memory Windows bound to: */ 875a2cc190SJeff Kirsher CMD_STAT_REG_BOUND = 0x21, 885a2cc190SJeff Kirsher /* HCA local attached memory not present: */ 895a2cc190SJeff Kirsher CMD_STAT_LAM_NOT_PRE = 0x22, 905a2cc190SJeff Kirsher /* Bad management packet (silently discarded): */ 915a2cc190SJeff Kirsher CMD_STAT_BAD_PKT = 0x30, 925a2cc190SJeff Kirsher /* More outstanding CQEs in CQ than new CQ size: */ 935a2cc190SJeff Kirsher CMD_STAT_BAD_SIZE = 0x40, 945a2cc190SJeff Kirsher /* Multi Function device support required: */ 955a2cc190SJeff Kirsher CMD_STAT_MULTI_FUNC_REQ = 0x50, 965a2cc190SJeff Kirsher }; 975a2cc190SJeff Kirsher 985a2cc190SJeff Kirsher enum { 995a2cc190SJeff Kirsher HCR_IN_PARAM_OFFSET = 0x00, 1005a2cc190SJeff Kirsher HCR_IN_MODIFIER_OFFSET = 0x08, 1015a2cc190SJeff Kirsher HCR_OUT_PARAM_OFFSET = 0x0c, 1025a2cc190SJeff Kirsher HCR_TOKEN_OFFSET = 0x14, 1035a2cc190SJeff Kirsher HCR_STATUS_OFFSET = 0x18, 1045a2cc190SJeff Kirsher 1055a2cc190SJeff Kirsher HCR_OPMOD_SHIFT = 12, 1065a2cc190SJeff Kirsher HCR_T_BIT = 21, 1075a2cc190SJeff Kirsher HCR_E_BIT = 22, 1085a2cc190SJeff Kirsher HCR_GO_BIT = 23 1095a2cc190SJeff Kirsher }; 1105a2cc190SJeff Kirsher 1115a2cc190SJeff Kirsher enum { 1125a2cc190SJeff Kirsher GO_BIT_TIMEOUT_MSECS = 10000 1135a2cc190SJeff Kirsher }; 1145a2cc190SJeff Kirsher 115b01978caSJack Morgenstein enum mlx4_vlan_transition { 116b01978caSJack Morgenstein MLX4_VLAN_TRANSITION_VST_VST = 0, 117b01978caSJack Morgenstein MLX4_VLAN_TRANSITION_VST_VGT = 1, 118b01978caSJack Morgenstein MLX4_VLAN_TRANSITION_VGT_VST = 2, 119b01978caSJack Morgenstein MLX4_VLAN_TRANSITION_VGT_VGT = 3, 120b01978caSJack Morgenstein }; 121b01978caSJack Morgenstein 122b01978caSJack Morgenstein 1235a2cc190SJeff Kirsher struct mlx4_cmd_context { 1245a2cc190SJeff Kirsher struct completion done; 1255a2cc190SJeff Kirsher int result; 1265a2cc190SJeff Kirsher int next; 1275a2cc190SJeff Kirsher u64 out_param; 1285a2cc190SJeff Kirsher u16 token; 129e8f081aaSYevgeny Petrilin u8 fw_status; 1305a2cc190SJeff Kirsher }; 1315a2cc190SJeff Kirsher 132e8f081aaSYevgeny Petrilin static int mlx4_master_process_vhcr(struct mlx4_dev *dev, int slave, 133e8f081aaSYevgeny Petrilin struct mlx4_vhcr_cmd *in_vhcr); 134e8f081aaSYevgeny Petrilin 1355a2cc190SJeff Kirsher static int mlx4_status_to_errno(u8 status) 1365a2cc190SJeff Kirsher { 1375a2cc190SJeff Kirsher static const int trans_table[] = { 1385a2cc190SJeff Kirsher [CMD_STAT_INTERNAL_ERR] = -EIO, 1395a2cc190SJeff Kirsher [CMD_STAT_BAD_OP] = -EPERM, 1405a2cc190SJeff Kirsher [CMD_STAT_BAD_PARAM] = -EINVAL, 1415a2cc190SJeff Kirsher [CMD_STAT_BAD_SYS_STATE] = -ENXIO, 1425a2cc190SJeff Kirsher [CMD_STAT_BAD_RESOURCE] = -EBADF, 1435a2cc190SJeff Kirsher [CMD_STAT_RESOURCE_BUSY] = -EBUSY, 1445a2cc190SJeff Kirsher [CMD_STAT_EXCEED_LIM] = -ENOMEM, 1455a2cc190SJeff Kirsher [CMD_STAT_BAD_RES_STATE] = -EBADF, 1465a2cc190SJeff Kirsher [CMD_STAT_BAD_INDEX] = -EBADF, 1475a2cc190SJeff Kirsher [CMD_STAT_BAD_NVMEM] = -EFAULT, 1485a2cc190SJeff Kirsher [CMD_STAT_ICM_ERROR] = -ENFILE, 1495a2cc190SJeff Kirsher [CMD_STAT_BAD_QP_STATE] = -EINVAL, 1505a2cc190SJeff Kirsher [CMD_STAT_BAD_SEG_PARAM] = -EFAULT, 1515a2cc190SJeff Kirsher [CMD_STAT_REG_BOUND] = -EBUSY, 1525a2cc190SJeff Kirsher [CMD_STAT_LAM_NOT_PRE] = -EAGAIN, 1535a2cc190SJeff Kirsher [CMD_STAT_BAD_PKT] = -EINVAL, 1545a2cc190SJeff Kirsher [CMD_STAT_BAD_SIZE] = -ENOMEM, 1555a2cc190SJeff Kirsher [CMD_STAT_MULTI_FUNC_REQ] = -EACCES, 1565a2cc190SJeff Kirsher }; 1575a2cc190SJeff Kirsher 1585a2cc190SJeff Kirsher if (status >= ARRAY_SIZE(trans_table) || 1595a2cc190SJeff Kirsher (status != CMD_STAT_OK && trans_table[status] == 0)) 1605a2cc190SJeff Kirsher return -EIO; 1615a2cc190SJeff Kirsher 1625a2cc190SJeff Kirsher return trans_table[status]; 1635a2cc190SJeff Kirsher } 1645a2cc190SJeff Kirsher 16572be84f1SYevgeny Petrilin static u8 mlx4_errno_to_status(int errno) 16672be84f1SYevgeny Petrilin { 16772be84f1SYevgeny Petrilin switch (errno) { 16872be84f1SYevgeny Petrilin case -EPERM: 16972be84f1SYevgeny Petrilin return CMD_STAT_BAD_OP; 17072be84f1SYevgeny Petrilin case -EINVAL: 17172be84f1SYevgeny Petrilin return CMD_STAT_BAD_PARAM; 17272be84f1SYevgeny Petrilin case -ENXIO: 17372be84f1SYevgeny Petrilin return CMD_STAT_BAD_SYS_STATE; 17472be84f1SYevgeny Petrilin case -EBUSY: 17572be84f1SYevgeny Petrilin return CMD_STAT_RESOURCE_BUSY; 17672be84f1SYevgeny Petrilin case -ENOMEM: 17772be84f1SYevgeny Petrilin return CMD_STAT_EXCEED_LIM; 17872be84f1SYevgeny Petrilin case -ENFILE: 17972be84f1SYevgeny Petrilin return CMD_STAT_ICM_ERROR; 18072be84f1SYevgeny Petrilin default: 18172be84f1SYevgeny Petrilin return CMD_STAT_INTERNAL_ERR; 18272be84f1SYevgeny Petrilin } 18372be84f1SYevgeny Petrilin } 18472be84f1SYevgeny Petrilin 185*f5aef5aaSYishai Hadas static int mlx4_internal_err_ret_value(struct mlx4_dev *dev, u16 op, 186*f5aef5aaSYishai Hadas u8 op_modifier) 187*f5aef5aaSYishai Hadas { 188*f5aef5aaSYishai Hadas switch (op) { 189*f5aef5aaSYishai Hadas case MLX4_CMD_UNMAP_ICM: 190*f5aef5aaSYishai Hadas case MLX4_CMD_UNMAP_ICM_AUX: 191*f5aef5aaSYishai Hadas case MLX4_CMD_UNMAP_FA: 192*f5aef5aaSYishai Hadas case MLX4_CMD_2RST_QP: 193*f5aef5aaSYishai Hadas case MLX4_CMD_HW2SW_EQ: 194*f5aef5aaSYishai Hadas case MLX4_CMD_HW2SW_CQ: 195*f5aef5aaSYishai Hadas case MLX4_CMD_HW2SW_SRQ: 196*f5aef5aaSYishai Hadas case MLX4_CMD_HW2SW_MPT: 197*f5aef5aaSYishai Hadas case MLX4_CMD_CLOSE_HCA: 198*f5aef5aaSYishai Hadas case MLX4_QP_FLOW_STEERING_DETACH: 199*f5aef5aaSYishai Hadas case MLX4_CMD_FREE_RES: 200*f5aef5aaSYishai Hadas case MLX4_CMD_CLOSE_PORT: 201*f5aef5aaSYishai Hadas return CMD_STAT_OK; 202*f5aef5aaSYishai Hadas 203*f5aef5aaSYishai Hadas case MLX4_CMD_QP_ATTACH: 204*f5aef5aaSYishai Hadas /* On Detach case return success */ 205*f5aef5aaSYishai Hadas if (op_modifier == 0) 206*f5aef5aaSYishai Hadas return CMD_STAT_OK; 207*f5aef5aaSYishai Hadas return mlx4_status_to_errno(CMD_STAT_INTERNAL_ERR); 208*f5aef5aaSYishai Hadas 209*f5aef5aaSYishai Hadas default: 210*f5aef5aaSYishai Hadas return mlx4_status_to_errno(CMD_STAT_INTERNAL_ERR); 211*f5aef5aaSYishai Hadas } 212*f5aef5aaSYishai Hadas } 213*f5aef5aaSYishai Hadas 214*f5aef5aaSYishai Hadas static int mlx4_closing_cmd_fatal_error(u16 op, u8 fw_status) 215*f5aef5aaSYishai Hadas { 216*f5aef5aaSYishai Hadas /* Any error during the closing commands below is considered fatal */ 217*f5aef5aaSYishai Hadas if (op == MLX4_CMD_CLOSE_HCA || 218*f5aef5aaSYishai Hadas op == MLX4_CMD_HW2SW_EQ || 219*f5aef5aaSYishai Hadas op == MLX4_CMD_HW2SW_CQ || 220*f5aef5aaSYishai Hadas op == MLX4_CMD_2RST_QP || 221*f5aef5aaSYishai Hadas op == MLX4_CMD_HW2SW_SRQ || 222*f5aef5aaSYishai Hadas op == MLX4_CMD_SYNC_TPT || 223*f5aef5aaSYishai Hadas op == MLX4_CMD_UNMAP_ICM || 224*f5aef5aaSYishai Hadas op == MLX4_CMD_UNMAP_ICM_AUX || 225*f5aef5aaSYishai Hadas op == MLX4_CMD_UNMAP_FA) 226*f5aef5aaSYishai Hadas return 1; 227*f5aef5aaSYishai Hadas /* Error on MLX4_CMD_HW2SW_MPT is fatal except when fw status equals 228*f5aef5aaSYishai Hadas * CMD_STAT_REG_BOUND. 229*f5aef5aaSYishai Hadas * This status indicates that memory region has memory windows bound to it 230*f5aef5aaSYishai Hadas * which may result from invalid user space usage and is not fatal. 231*f5aef5aaSYishai Hadas */ 232*f5aef5aaSYishai Hadas if (op == MLX4_CMD_HW2SW_MPT && fw_status != CMD_STAT_REG_BOUND) 233*f5aef5aaSYishai Hadas return 1; 234*f5aef5aaSYishai Hadas return 0; 235*f5aef5aaSYishai Hadas } 236*f5aef5aaSYishai Hadas 237*f5aef5aaSYishai Hadas static int mlx4_cmd_reset_flow(struct mlx4_dev *dev, u16 op, u8 op_modifier, 238*f5aef5aaSYishai Hadas int err) 239*f5aef5aaSYishai Hadas { 240*f5aef5aaSYishai Hadas /* Only if reset flow is really active return code is based on 241*f5aef5aaSYishai Hadas * command, otherwise current error code is returned. 242*f5aef5aaSYishai Hadas */ 243*f5aef5aaSYishai Hadas if (mlx4_internal_err_reset) { 244*f5aef5aaSYishai Hadas mlx4_enter_error_state(dev->persist); 245*f5aef5aaSYishai Hadas err = mlx4_internal_err_ret_value(dev, op, op_modifier); 246*f5aef5aaSYishai Hadas } 247*f5aef5aaSYishai Hadas 248*f5aef5aaSYishai Hadas return err; 249*f5aef5aaSYishai Hadas } 250*f5aef5aaSYishai Hadas 251e8f081aaSYevgeny Petrilin static int comm_pending(struct mlx4_dev *dev) 252e8f081aaSYevgeny Petrilin { 253e8f081aaSYevgeny Petrilin struct mlx4_priv *priv = mlx4_priv(dev); 254e8f081aaSYevgeny Petrilin u32 status = readl(&priv->mfunc.comm->slave_read); 255e8f081aaSYevgeny Petrilin 256e8f081aaSYevgeny Petrilin return (swab32(status) >> 31) != priv->cmd.comm_toggle; 257e8f081aaSYevgeny Petrilin } 258e8f081aaSYevgeny Petrilin 259e8f081aaSYevgeny Petrilin static void mlx4_comm_cmd_post(struct mlx4_dev *dev, u8 cmd, u16 param) 260e8f081aaSYevgeny Petrilin { 261e8f081aaSYevgeny Petrilin struct mlx4_priv *priv = mlx4_priv(dev); 262e8f081aaSYevgeny Petrilin u32 val; 263e8f081aaSYevgeny Petrilin 264e8f081aaSYevgeny Petrilin priv->cmd.comm_toggle ^= 1; 265e8f081aaSYevgeny Petrilin val = param | (cmd << 16) | (priv->cmd.comm_toggle << 31); 266e8f081aaSYevgeny Petrilin __raw_writel((__force u32) cpu_to_be32(val), 267e8f081aaSYevgeny Petrilin &priv->mfunc.comm->slave_write); 268e8f081aaSYevgeny Petrilin mmiowb(); 269e8f081aaSYevgeny Petrilin } 270e8f081aaSYevgeny Petrilin 271e8f081aaSYevgeny Petrilin static int mlx4_comm_cmd_poll(struct mlx4_dev *dev, u8 cmd, u16 param, 272e8f081aaSYevgeny Petrilin unsigned long timeout) 273e8f081aaSYevgeny Petrilin { 274e8f081aaSYevgeny Petrilin struct mlx4_priv *priv = mlx4_priv(dev); 275e8f081aaSYevgeny Petrilin unsigned long end; 276e8f081aaSYevgeny Petrilin int err = 0; 277e8f081aaSYevgeny Petrilin int ret_from_pending = 0; 278e8f081aaSYevgeny Petrilin 279e8f081aaSYevgeny Petrilin /* First, verify that the master reports correct status */ 280e8f081aaSYevgeny Petrilin if (comm_pending(dev)) { 2811a91de28SJoe Perches mlx4_warn(dev, "Communication channel is not idle - my toggle is %d (cmd:0x%x)\n", 282e8f081aaSYevgeny Petrilin priv->cmd.comm_toggle, cmd); 283e8f081aaSYevgeny Petrilin return -EAGAIN; 284e8f081aaSYevgeny Petrilin } 285e8f081aaSYevgeny Petrilin 286e8f081aaSYevgeny Petrilin /* Write command */ 287e8f081aaSYevgeny Petrilin down(&priv->cmd.poll_sem); 288e8f081aaSYevgeny Petrilin mlx4_comm_cmd_post(dev, cmd, param); 289e8f081aaSYevgeny Petrilin 290e8f081aaSYevgeny Petrilin end = msecs_to_jiffies(timeout) + jiffies; 291e8f081aaSYevgeny Petrilin while (comm_pending(dev) && time_before(jiffies, end)) 292e8f081aaSYevgeny Petrilin cond_resched(); 293e8f081aaSYevgeny Petrilin ret_from_pending = comm_pending(dev); 294e8f081aaSYevgeny Petrilin if (ret_from_pending) { 295e8f081aaSYevgeny Petrilin /* check if the slave is trying to boot in the middle of 296e8f081aaSYevgeny Petrilin * FLR process. The only non-zero result in the RESET command 297e8f081aaSYevgeny Petrilin * is MLX4_DELAY_RESET_SLAVE*/ 298e8f081aaSYevgeny Petrilin if ((MLX4_COMM_CMD_RESET == cmd)) { 299e8f081aaSYevgeny Petrilin err = MLX4_DELAY_RESET_SLAVE; 300e8f081aaSYevgeny Petrilin } else { 301e8f081aaSYevgeny Petrilin mlx4_warn(dev, "Communication channel timed out\n"); 302e8f081aaSYevgeny Petrilin err = -ETIMEDOUT; 303e8f081aaSYevgeny Petrilin } 304e8f081aaSYevgeny Petrilin } 305e8f081aaSYevgeny Petrilin 306e8f081aaSYevgeny Petrilin up(&priv->cmd.poll_sem); 307e8f081aaSYevgeny Petrilin return err; 308e8f081aaSYevgeny Petrilin } 309e8f081aaSYevgeny Petrilin 310e8f081aaSYevgeny Petrilin static int mlx4_comm_cmd_wait(struct mlx4_dev *dev, u8 op, 311e8f081aaSYevgeny Petrilin u16 param, unsigned long timeout) 312e8f081aaSYevgeny Petrilin { 313e8f081aaSYevgeny Petrilin struct mlx4_cmd *cmd = &mlx4_priv(dev)->cmd; 314e8f081aaSYevgeny Petrilin struct mlx4_cmd_context *context; 31558a3de05SEugenia Emantayev unsigned long end; 316e8f081aaSYevgeny Petrilin int err = 0; 317e8f081aaSYevgeny Petrilin 318e8f081aaSYevgeny Petrilin down(&cmd->event_sem); 319e8f081aaSYevgeny Petrilin 320e8f081aaSYevgeny Petrilin spin_lock(&cmd->context_lock); 321e8f081aaSYevgeny Petrilin BUG_ON(cmd->free_head < 0); 322e8f081aaSYevgeny Petrilin context = &cmd->context[cmd->free_head]; 323e8f081aaSYevgeny Petrilin context->token += cmd->token_mask + 1; 324e8f081aaSYevgeny Petrilin cmd->free_head = context->next; 325e8f081aaSYevgeny Petrilin spin_unlock(&cmd->context_lock); 326e8f081aaSYevgeny Petrilin 327*f5aef5aaSYishai Hadas reinit_completion(&context->done); 328e8f081aaSYevgeny Petrilin 329e8f081aaSYevgeny Petrilin mlx4_comm_cmd_post(dev, op, param); 330e8f081aaSYevgeny Petrilin 331e8f081aaSYevgeny Petrilin if (!wait_for_completion_timeout(&context->done, 332e8f081aaSYevgeny Petrilin msecs_to_jiffies(timeout))) { 333674925edSDotan Barak mlx4_warn(dev, "communication channel command 0x%x timed out\n", 334674925edSDotan Barak op); 335e8f081aaSYevgeny Petrilin err = -EBUSY; 336e8f081aaSYevgeny Petrilin goto out; 337e8f081aaSYevgeny Petrilin } 338e8f081aaSYevgeny Petrilin 339e8f081aaSYevgeny Petrilin err = context->result; 340e8f081aaSYevgeny Petrilin if (err && context->fw_status != CMD_STAT_MULTI_FUNC_REQ) { 341e8f081aaSYevgeny Petrilin mlx4_err(dev, "command 0x%x failed: fw status = 0x%x\n", 342e8f081aaSYevgeny Petrilin op, context->fw_status); 343e8f081aaSYevgeny Petrilin goto out; 344e8f081aaSYevgeny Petrilin } 345e8f081aaSYevgeny Petrilin 346e8f081aaSYevgeny Petrilin out: 34758a3de05SEugenia Emantayev /* wait for comm channel ready 34858a3de05SEugenia Emantayev * this is necessary for prevention the race 34958a3de05SEugenia Emantayev * when switching between event to polling mode 35058a3de05SEugenia Emantayev */ 35158a3de05SEugenia Emantayev end = msecs_to_jiffies(timeout) + jiffies; 35258a3de05SEugenia Emantayev while (comm_pending(dev) && time_before(jiffies, end)) 35358a3de05SEugenia Emantayev cond_resched(); 35458a3de05SEugenia Emantayev 355e8f081aaSYevgeny Petrilin spin_lock(&cmd->context_lock); 356e8f081aaSYevgeny Petrilin context->next = cmd->free_head; 357e8f081aaSYevgeny Petrilin cmd->free_head = context - cmd->context; 358e8f081aaSYevgeny Petrilin spin_unlock(&cmd->context_lock); 359e8f081aaSYevgeny Petrilin 360e8f081aaSYevgeny Petrilin up(&cmd->event_sem); 361e8f081aaSYevgeny Petrilin return err; 362e8f081aaSYevgeny Petrilin } 363e8f081aaSYevgeny Petrilin 364ab9c17a0SJack Morgenstein int mlx4_comm_cmd(struct mlx4_dev *dev, u8 cmd, u16 param, 365e8f081aaSYevgeny Petrilin unsigned long timeout) 366e8f081aaSYevgeny Petrilin { 367e8f081aaSYevgeny Petrilin if (mlx4_priv(dev)->cmd.use_events) 368e8f081aaSYevgeny Petrilin return mlx4_comm_cmd_wait(dev, cmd, param, timeout); 369e8f081aaSYevgeny Petrilin return mlx4_comm_cmd_poll(dev, cmd, param, timeout); 370e8f081aaSYevgeny Petrilin } 371e8f081aaSYevgeny Petrilin 3725a2cc190SJeff Kirsher static int cmd_pending(struct mlx4_dev *dev) 3735a2cc190SJeff Kirsher { 37457dbf29aSKleber Sacilotto de Souza u32 status; 37557dbf29aSKleber Sacilotto de Souza 376872bf2fbSYishai Hadas if (pci_channel_offline(dev->persist->pdev)) 37757dbf29aSKleber Sacilotto de Souza return -EIO; 37857dbf29aSKleber Sacilotto de Souza 37957dbf29aSKleber Sacilotto de Souza status = readl(mlx4_priv(dev)->cmd.hcr + HCR_STATUS_OFFSET); 3805a2cc190SJeff Kirsher 3815a2cc190SJeff Kirsher return (status & swab32(1 << HCR_GO_BIT)) || 3825a2cc190SJeff Kirsher (mlx4_priv(dev)->cmd.toggle == 3835a2cc190SJeff Kirsher !!(status & swab32(1 << HCR_T_BIT))); 3845a2cc190SJeff Kirsher } 3855a2cc190SJeff Kirsher 3865a2cc190SJeff Kirsher static int mlx4_cmd_post(struct mlx4_dev *dev, u64 in_param, u64 out_param, 3875a2cc190SJeff Kirsher u32 in_modifier, u8 op_modifier, u16 op, u16 token, 3885a2cc190SJeff Kirsher int event) 3895a2cc190SJeff Kirsher { 3905a2cc190SJeff Kirsher struct mlx4_cmd *cmd = &mlx4_priv(dev)->cmd; 3915a2cc190SJeff Kirsher u32 __iomem *hcr = cmd->hcr; 392*f5aef5aaSYishai Hadas int ret = -EIO; 3935a2cc190SJeff Kirsher unsigned long end; 3945a2cc190SJeff Kirsher 395*f5aef5aaSYishai Hadas mutex_lock(&dev->persist->device_state_mutex); 396*f5aef5aaSYishai Hadas /* To avoid writing to unknown addresses after the device state was 397*f5aef5aaSYishai Hadas * changed to internal error and the chip was reset, 398*f5aef5aaSYishai Hadas * check the INTERNAL_ERROR flag which is updated under 399*f5aef5aaSYishai Hadas * device_state_mutex lock. 400*f5aef5aaSYishai Hadas */ 401*f5aef5aaSYishai Hadas if (pci_channel_offline(dev->persist->pdev) || 402*f5aef5aaSYishai Hadas (dev->persist->state & MLX4_DEVICE_STATE_INTERNAL_ERROR)) { 40357dbf29aSKleber Sacilotto de Souza /* 40457dbf29aSKleber Sacilotto de Souza * Device is going through error recovery 40557dbf29aSKleber Sacilotto de Souza * and cannot accept commands. 40657dbf29aSKleber Sacilotto de Souza */ 40757dbf29aSKleber Sacilotto de Souza goto out; 40857dbf29aSKleber Sacilotto de Souza } 40957dbf29aSKleber Sacilotto de Souza 4105a2cc190SJeff Kirsher end = jiffies; 4115a2cc190SJeff Kirsher if (event) 4125a2cc190SJeff Kirsher end += msecs_to_jiffies(GO_BIT_TIMEOUT_MSECS); 4135a2cc190SJeff Kirsher 4145a2cc190SJeff Kirsher while (cmd_pending(dev)) { 415872bf2fbSYishai Hadas if (pci_channel_offline(dev->persist->pdev)) { 41657dbf29aSKleber Sacilotto de Souza /* 41757dbf29aSKleber Sacilotto de Souza * Device is going through error recovery 41857dbf29aSKleber Sacilotto de Souza * and cannot accept commands. 41957dbf29aSKleber Sacilotto de Souza */ 42057dbf29aSKleber Sacilotto de Souza goto out; 42157dbf29aSKleber Sacilotto de Souza } 42257dbf29aSKleber Sacilotto de Souza 423e8f081aaSYevgeny Petrilin if (time_after_eq(jiffies, end)) { 424e8f081aaSYevgeny Petrilin mlx4_err(dev, "%s:cmd_pending failed\n", __func__); 4255a2cc190SJeff Kirsher goto out; 426e8f081aaSYevgeny Petrilin } 4275a2cc190SJeff Kirsher cond_resched(); 4285a2cc190SJeff Kirsher } 4295a2cc190SJeff Kirsher 4305a2cc190SJeff Kirsher /* 4315a2cc190SJeff Kirsher * We use writel (instead of something like memcpy_toio) 4325a2cc190SJeff Kirsher * because writes of less than 32 bits to the HCR don't work 4335a2cc190SJeff Kirsher * (and some architectures such as ia64 implement memcpy_toio 4345a2cc190SJeff Kirsher * in terms of writeb). 4355a2cc190SJeff Kirsher */ 4365a2cc190SJeff Kirsher __raw_writel((__force u32) cpu_to_be32(in_param >> 32), hcr + 0); 4375a2cc190SJeff Kirsher __raw_writel((__force u32) cpu_to_be32(in_param & 0xfffffffful), hcr + 1); 4385a2cc190SJeff Kirsher __raw_writel((__force u32) cpu_to_be32(in_modifier), hcr + 2); 4395a2cc190SJeff Kirsher __raw_writel((__force u32) cpu_to_be32(out_param >> 32), hcr + 3); 4405a2cc190SJeff Kirsher __raw_writel((__force u32) cpu_to_be32(out_param & 0xfffffffful), hcr + 4); 4415a2cc190SJeff Kirsher __raw_writel((__force u32) cpu_to_be32(token << 16), hcr + 5); 4425a2cc190SJeff Kirsher 4435a2cc190SJeff Kirsher /* __raw_writel may not order writes. */ 4445a2cc190SJeff Kirsher wmb(); 4455a2cc190SJeff Kirsher 4465a2cc190SJeff Kirsher __raw_writel((__force u32) cpu_to_be32((1 << HCR_GO_BIT) | 4475a2cc190SJeff Kirsher (cmd->toggle << HCR_T_BIT) | 4485a2cc190SJeff Kirsher (event ? (1 << HCR_E_BIT) : 0) | 4495a2cc190SJeff Kirsher (op_modifier << HCR_OPMOD_SHIFT) | 4505a2cc190SJeff Kirsher op), hcr + 6); 4515a2cc190SJeff Kirsher 4525a2cc190SJeff Kirsher /* 4535a2cc190SJeff Kirsher * Make sure that our HCR writes don't get mixed in with 4545a2cc190SJeff Kirsher * writes from another CPU starting a FW command. 4555a2cc190SJeff Kirsher */ 4565a2cc190SJeff Kirsher mmiowb(); 4575a2cc190SJeff Kirsher 4585a2cc190SJeff Kirsher cmd->toggle = cmd->toggle ^ 1; 4595a2cc190SJeff Kirsher 4605a2cc190SJeff Kirsher ret = 0; 4615a2cc190SJeff Kirsher 4625a2cc190SJeff Kirsher out: 463*f5aef5aaSYishai Hadas if (ret) 464*f5aef5aaSYishai Hadas mlx4_warn(dev, "Could not post command 0x%x: ret=%d, in_param=0x%llx, in_mod=0x%x, op_mod=0x%x\n", 465*f5aef5aaSYishai Hadas op, ret, in_param, in_modifier, op_modifier); 466*f5aef5aaSYishai Hadas mutex_unlock(&dev->persist->device_state_mutex); 467*f5aef5aaSYishai Hadas 4685a2cc190SJeff Kirsher return ret; 4695a2cc190SJeff Kirsher } 4705a2cc190SJeff Kirsher 471e8f081aaSYevgeny Petrilin static int mlx4_slave_cmd(struct mlx4_dev *dev, u64 in_param, u64 *out_param, 472e8f081aaSYevgeny Petrilin int out_is_imm, u32 in_modifier, u8 op_modifier, 473e8f081aaSYevgeny Petrilin u16 op, unsigned long timeout) 474e8f081aaSYevgeny Petrilin { 475e8f081aaSYevgeny Petrilin struct mlx4_priv *priv = mlx4_priv(dev); 476e8f081aaSYevgeny Petrilin struct mlx4_vhcr_cmd *vhcr = priv->mfunc.vhcr; 477e8f081aaSYevgeny Petrilin int ret; 478e8f081aaSYevgeny Petrilin 479f3d4c89eSRoland Dreier mutex_lock(&priv->cmd.slave_cmd_mutex); 480f3d4c89eSRoland Dreier 481e8f081aaSYevgeny Petrilin vhcr->in_param = cpu_to_be64(in_param); 482e8f081aaSYevgeny Petrilin vhcr->out_param = out_param ? cpu_to_be64(*out_param) : 0; 483e8f081aaSYevgeny Petrilin vhcr->in_modifier = cpu_to_be32(in_modifier); 484e8f081aaSYevgeny Petrilin vhcr->opcode = cpu_to_be16((((u16) op_modifier) << 12) | (op & 0xfff)); 485e8f081aaSYevgeny Petrilin vhcr->token = cpu_to_be16(CMD_POLL_TOKEN); 486e8f081aaSYevgeny Petrilin vhcr->status = 0; 487e8f081aaSYevgeny Petrilin vhcr->flags = !!(priv->cmd.use_events) << 6; 488f3d4c89eSRoland Dreier 489e8f081aaSYevgeny Petrilin if (mlx4_is_master(dev)) { 490e8f081aaSYevgeny Petrilin ret = mlx4_master_process_vhcr(dev, dev->caps.function, vhcr); 491e8f081aaSYevgeny Petrilin if (!ret) { 492e8f081aaSYevgeny Petrilin if (out_is_imm) { 493e8f081aaSYevgeny Petrilin if (out_param) 494e8f081aaSYevgeny Petrilin *out_param = 495e8f081aaSYevgeny Petrilin be64_to_cpu(vhcr->out_param); 496e8f081aaSYevgeny Petrilin else { 4971a91de28SJoe Perches mlx4_err(dev, "response expected while output mailbox is NULL for command 0x%x\n", 4981a91de28SJoe Perches op); 49972be84f1SYevgeny Petrilin vhcr->status = CMD_STAT_BAD_PARAM; 500e8f081aaSYevgeny Petrilin } 501e8f081aaSYevgeny Petrilin } 50272be84f1SYevgeny Petrilin ret = mlx4_status_to_errno(vhcr->status); 503e8f081aaSYevgeny Petrilin } 504e8f081aaSYevgeny Petrilin } else { 505e8f081aaSYevgeny Petrilin ret = mlx4_comm_cmd(dev, MLX4_COMM_CMD_VHCR_POST, 0, 506e8f081aaSYevgeny Petrilin MLX4_COMM_TIME + timeout); 507e8f081aaSYevgeny Petrilin if (!ret) { 508e8f081aaSYevgeny Petrilin if (out_is_imm) { 509e8f081aaSYevgeny Petrilin if (out_param) 510e8f081aaSYevgeny Petrilin *out_param = 511e8f081aaSYevgeny Petrilin be64_to_cpu(vhcr->out_param); 512e8f081aaSYevgeny Petrilin else { 5131a91de28SJoe Perches mlx4_err(dev, "response expected while output mailbox is NULL for command 0x%x\n", 5141a91de28SJoe Perches op); 51572be84f1SYevgeny Petrilin vhcr->status = CMD_STAT_BAD_PARAM; 516e8f081aaSYevgeny Petrilin } 517e8f081aaSYevgeny Petrilin } 51872be84f1SYevgeny Petrilin ret = mlx4_status_to_errno(vhcr->status); 519e8f081aaSYevgeny Petrilin } else 5201a91de28SJoe Perches mlx4_err(dev, "failed execution of VHCR_POST command opcode 0x%x\n", 5211a91de28SJoe Perches op); 522e8f081aaSYevgeny Petrilin } 523f3d4c89eSRoland Dreier 524f3d4c89eSRoland Dreier mutex_unlock(&priv->cmd.slave_cmd_mutex); 525e8f081aaSYevgeny Petrilin return ret; 526e8f081aaSYevgeny Petrilin } 527e8f081aaSYevgeny Petrilin 5285a2cc190SJeff Kirsher static int mlx4_cmd_poll(struct mlx4_dev *dev, u64 in_param, u64 *out_param, 5295a2cc190SJeff Kirsher int out_is_imm, u32 in_modifier, u8 op_modifier, 5305a2cc190SJeff Kirsher u16 op, unsigned long timeout) 5315a2cc190SJeff Kirsher { 5325a2cc190SJeff Kirsher struct mlx4_priv *priv = mlx4_priv(dev); 5335a2cc190SJeff Kirsher void __iomem *hcr = priv->cmd.hcr; 5345a2cc190SJeff Kirsher int err = 0; 5355a2cc190SJeff Kirsher unsigned long end; 536e8f081aaSYevgeny Petrilin u32 stat; 5375a2cc190SJeff Kirsher 5385a2cc190SJeff Kirsher down(&priv->cmd.poll_sem); 5395a2cc190SJeff Kirsher 540*f5aef5aaSYishai Hadas if (dev->persist->state & MLX4_DEVICE_STATE_INTERNAL_ERROR) { 54157dbf29aSKleber Sacilotto de Souza /* 54257dbf29aSKleber Sacilotto de Souza * Device is going through error recovery 54357dbf29aSKleber Sacilotto de Souza * and cannot accept commands. 54457dbf29aSKleber Sacilotto de Souza */ 545*f5aef5aaSYishai Hadas err = mlx4_internal_err_ret_value(dev, op, op_modifier); 54657dbf29aSKleber Sacilotto de Souza goto out; 54757dbf29aSKleber Sacilotto de Souza } 54857dbf29aSKleber Sacilotto de Souza 549c05a116fSEyal Perry if (out_is_imm && !out_param) { 550c05a116fSEyal Perry mlx4_err(dev, "response expected while output mailbox is NULL for command 0x%x\n", 551c05a116fSEyal Perry op); 552c05a116fSEyal Perry err = -EINVAL; 553c05a116fSEyal Perry goto out; 554c05a116fSEyal Perry } 555c05a116fSEyal Perry 5565a2cc190SJeff Kirsher err = mlx4_cmd_post(dev, in_param, out_param ? *out_param : 0, 5575a2cc190SJeff Kirsher in_modifier, op_modifier, op, CMD_POLL_TOKEN, 0); 5585a2cc190SJeff Kirsher if (err) 559*f5aef5aaSYishai Hadas goto out_reset; 5605a2cc190SJeff Kirsher 5615a2cc190SJeff Kirsher end = msecs_to_jiffies(timeout) + jiffies; 56257dbf29aSKleber Sacilotto de Souza while (cmd_pending(dev) && time_before(jiffies, end)) { 563872bf2fbSYishai Hadas if (pci_channel_offline(dev->persist->pdev)) { 56457dbf29aSKleber Sacilotto de Souza /* 56557dbf29aSKleber Sacilotto de Souza * Device is going through error recovery 56657dbf29aSKleber Sacilotto de Souza * and cannot accept commands. 56757dbf29aSKleber Sacilotto de Souza */ 56857dbf29aSKleber Sacilotto de Souza err = -EIO; 569*f5aef5aaSYishai Hadas goto out_reset; 570*f5aef5aaSYishai Hadas } 571*f5aef5aaSYishai Hadas 572*f5aef5aaSYishai Hadas if (dev->persist->state & MLX4_DEVICE_STATE_INTERNAL_ERROR) { 573*f5aef5aaSYishai Hadas err = mlx4_internal_err_ret_value(dev, op, op_modifier); 57457dbf29aSKleber Sacilotto de Souza goto out; 57557dbf29aSKleber Sacilotto de Souza } 57657dbf29aSKleber Sacilotto de Souza 5775a2cc190SJeff Kirsher cond_resched(); 57857dbf29aSKleber Sacilotto de Souza } 5795a2cc190SJeff Kirsher 5805a2cc190SJeff Kirsher if (cmd_pending(dev)) { 581674925edSDotan Barak mlx4_warn(dev, "command 0x%x timed out (go bit not cleared)\n", 582674925edSDotan Barak op); 583*f5aef5aaSYishai Hadas err = -EIO; 584*f5aef5aaSYishai Hadas goto out_reset; 5855a2cc190SJeff Kirsher } 5865a2cc190SJeff Kirsher 5875a2cc190SJeff Kirsher if (out_is_imm) 5885a2cc190SJeff Kirsher *out_param = 5895a2cc190SJeff Kirsher (u64) be32_to_cpu((__force __be32) 5905a2cc190SJeff Kirsher __raw_readl(hcr + HCR_OUT_PARAM_OFFSET)) << 32 | 5915a2cc190SJeff Kirsher (u64) be32_to_cpu((__force __be32) 5925a2cc190SJeff Kirsher __raw_readl(hcr + HCR_OUT_PARAM_OFFSET + 4)); 593e8f081aaSYevgeny Petrilin stat = be32_to_cpu((__force __be32) 594e8f081aaSYevgeny Petrilin __raw_readl(hcr + HCR_STATUS_OFFSET)) >> 24; 595e8f081aaSYevgeny Petrilin err = mlx4_status_to_errno(stat); 596*f5aef5aaSYishai Hadas if (err) { 597e8f081aaSYevgeny Petrilin mlx4_err(dev, "command 0x%x failed: fw status = 0x%x\n", 598e8f081aaSYevgeny Petrilin op, stat); 599*f5aef5aaSYishai Hadas if (mlx4_closing_cmd_fatal_error(op, stat)) 600*f5aef5aaSYishai Hadas goto out_reset; 601*f5aef5aaSYishai Hadas goto out; 602*f5aef5aaSYishai Hadas } 6035a2cc190SJeff Kirsher 604*f5aef5aaSYishai Hadas out_reset: 605*f5aef5aaSYishai Hadas if (err) 606*f5aef5aaSYishai Hadas err = mlx4_cmd_reset_flow(dev, op, op_modifier, err); 6075a2cc190SJeff Kirsher out: 6085a2cc190SJeff Kirsher up(&priv->cmd.poll_sem); 6095a2cc190SJeff Kirsher return err; 6105a2cc190SJeff Kirsher } 6115a2cc190SJeff Kirsher 6125a2cc190SJeff Kirsher void mlx4_cmd_event(struct mlx4_dev *dev, u16 token, u8 status, u64 out_param) 6135a2cc190SJeff Kirsher { 6145a2cc190SJeff Kirsher struct mlx4_priv *priv = mlx4_priv(dev); 6155a2cc190SJeff Kirsher struct mlx4_cmd_context *context = 6165a2cc190SJeff Kirsher &priv->cmd.context[token & priv->cmd.token_mask]; 6175a2cc190SJeff Kirsher 6185a2cc190SJeff Kirsher /* previously timed out command completing at long last */ 6195a2cc190SJeff Kirsher if (token != context->token) 6205a2cc190SJeff Kirsher return; 6215a2cc190SJeff Kirsher 622e8f081aaSYevgeny Petrilin context->fw_status = status; 6235a2cc190SJeff Kirsher context->result = mlx4_status_to_errno(status); 6245a2cc190SJeff Kirsher context->out_param = out_param; 6255a2cc190SJeff Kirsher 6265a2cc190SJeff Kirsher complete(&context->done); 6275a2cc190SJeff Kirsher } 6285a2cc190SJeff Kirsher 6295a2cc190SJeff Kirsher static int mlx4_cmd_wait(struct mlx4_dev *dev, u64 in_param, u64 *out_param, 6305a2cc190SJeff Kirsher int out_is_imm, u32 in_modifier, u8 op_modifier, 6315a2cc190SJeff Kirsher u16 op, unsigned long timeout) 6325a2cc190SJeff Kirsher { 6335a2cc190SJeff Kirsher struct mlx4_cmd *cmd = &mlx4_priv(dev)->cmd; 6345a2cc190SJeff Kirsher struct mlx4_cmd_context *context; 6355a2cc190SJeff Kirsher int err = 0; 6365a2cc190SJeff Kirsher 6375a2cc190SJeff Kirsher down(&cmd->event_sem); 6385a2cc190SJeff Kirsher 6395a2cc190SJeff Kirsher spin_lock(&cmd->context_lock); 6405a2cc190SJeff Kirsher BUG_ON(cmd->free_head < 0); 6415a2cc190SJeff Kirsher context = &cmd->context[cmd->free_head]; 6425a2cc190SJeff Kirsher context->token += cmd->token_mask + 1; 6435a2cc190SJeff Kirsher cmd->free_head = context->next; 6445a2cc190SJeff Kirsher spin_unlock(&cmd->context_lock); 6455a2cc190SJeff Kirsher 646c05a116fSEyal Perry if (out_is_imm && !out_param) { 647c05a116fSEyal Perry mlx4_err(dev, "response expected while output mailbox is NULL for command 0x%x\n", 648c05a116fSEyal Perry op); 649c05a116fSEyal Perry err = -EINVAL; 650c05a116fSEyal Perry goto out; 651c05a116fSEyal Perry } 652c05a116fSEyal Perry 653*f5aef5aaSYishai Hadas reinit_completion(&context->done); 6545a2cc190SJeff Kirsher 655*f5aef5aaSYishai Hadas err = mlx4_cmd_post(dev, in_param, out_param ? *out_param : 0, 6565a2cc190SJeff Kirsher in_modifier, op_modifier, op, context->token, 1); 657*f5aef5aaSYishai Hadas if (err) 658*f5aef5aaSYishai Hadas goto out_reset; 6595a2cc190SJeff Kirsher 660e8f081aaSYevgeny Petrilin if (!wait_for_completion_timeout(&context->done, 661e8f081aaSYevgeny Petrilin msecs_to_jiffies(timeout))) { 662674925edSDotan Barak mlx4_warn(dev, "command 0x%x timed out (go bit not cleared)\n", 663674925edSDotan Barak op); 664*f5aef5aaSYishai Hadas err = -EIO; 665*f5aef5aaSYishai Hadas goto out_reset; 6665a2cc190SJeff Kirsher } 6675a2cc190SJeff Kirsher 6685a2cc190SJeff Kirsher err = context->result; 669e8f081aaSYevgeny Petrilin if (err) { 6701daa4303SJack Morgenstein /* Since we do not want to have this error message always 6711daa4303SJack Morgenstein * displayed at driver start when there are ConnectX2 HCAs 6721daa4303SJack Morgenstein * on the host, we deprecate the error message for this 6731daa4303SJack Morgenstein * specific command/input_mod/opcode_mod/fw-status to be debug. 6741daa4303SJack Morgenstein */ 6751daa4303SJack Morgenstein if (op == MLX4_CMD_SET_PORT && in_modifier == 1 && 6761daa4303SJack Morgenstein op_modifier == 0 && context->fw_status == CMD_STAT_BAD_SIZE) 6771daa4303SJack Morgenstein mlx4_dbg(dev, "command 0x%x failed: fw status = 0x%x\n", 6781daa4303SJack Morgenstein op, context->fw_status); 6791daa4303SJack Morgenstein else 680e8f081aaSYevgeny Petrilin mlx4_err(dev, "command 0x%x failed: fw status = 0x%x\n", 681e8f081aaSYevgeny Petrilin op, context->fw_status); 682*f5aef5aaSYishai Hadas if (dev->persist->state & MLX4_DEVICE_STATE_INTERNAL_ERROR) 683*f5aef5aaSYishai Hadas err = mlx4_internal_err_ret_value(dev, op, op_modifier); 684*f5aef5aaSYishai Hadas else if (mlx4_closing_cmd_fatal_error(op, context->fw_status)) 685*f5aef5aaSYishai Hadas goto out_reset; 686*f5aef5aaSYishai Hadas 6875a2cc190SJeff Kirsher goto out; 688e8f081aaSYevgeny Petrilin } 6895a2cc190SJeff Kirsher 6905a2cc190SJeff Kirsher if (out_is_imm) 6915a2cc190SJeff Kirsher *out_param = context->out_param; 6925a2cc190SJeff Kirsher 693*f5aef5aaSYishai Hadas out_reset: 694*f5aef5aaSYishai Hadas if (err) 695*f5aef5aaSYishai Hadas err = mlx4_cmd_reset_flow(dev, op, op_modifier, err); 6965a2cc190SJeff Kirsher out: 6975a2cc190SJeff Kirsher spin_lock(&cmd->context_lock); 6985a2cc190SJeff Kirsher context->next = cmd->free_head; 6995a2cc190SJeff Kirsher cmd->free_head = context - cmd->context; 7005a2cc190SJeff Kirsher spin_unlock(&cmd->context_lock); 7015a2cc190SJeff Kirsher 7025a2cc190SJeff Kirsher up(&cmd->event_sem); 7035a2cc190SJeff Kirsher return err; 7045a2cc190SJeff Kirsher } 7055a2cc190SJeff Kirsher 7065a2cc190SJeff Kirsher int __mlx4_cmd(struct mlx4_dev *dev, u64 in_param, u64 *out_param, 7075a2cc190SJeff Kirsher int out_is_imm, u32 in_modifier, u8 op_modifier, 708f9baff50SJack Morgenstein u16 op, unsigned long timeout, int native) 7095a2cc190SJeff Kirsher { 710872bf2fbSYishai Hadas if (pci_channel_offline(dev->persist->pdev)) 711*f5aef5aaSYishai Hadas return mlx4_cmd_reset_flow(dev, op, op_modifier, -EIO); 71257dbf29aSKleber Sacilotto de Souza 713e8f081aaSYevgeny Petrilin if (!mlx4_is_mfunc(dev) || (native && mlx4_is_master(dev))) { 714*f5aef5aaSYishai Hadas if (dev->persist->state & MLX4_DEVICE_STATE_INTERNAL_ERROR) 715*f5aef5aaSYishai Hadas return mlx4_internal_err_ret_value(dev, op, 716*f5aef5aaSYishai Hadas op_modifier); 7175a2cc190SJeff Kirsher if (mlx4_priv(dev)->cmd.use_events) 718e8f081aaSYevgeny Petrilin return mlx4_cmd_wait(dev, in_param, out_param, 719e8f081aaSYevgeny Petrilin out_is_imm, in_modifier, 720e8f081aaSYevgeny Petrilin op_modifier, op, timeout); 7215a2cc190SJeff Kirsher else 722e8f081aaSYevgeny Petrilin return mlx4_cmd_poll(dev, in_param, out_param, 723e8f081aaSYevgeny Petrilin out_is_imm, in_modifier, 724e8f081aaSYevgeny Petrilin op_modifier, op, timeout); 725e8f081aaSYevgeny Petrilin } 726e8f081aaSYevgeny Petrilin return mlx4_slave_cmd(dev, in_param, out_param, out_is_imm, 7275a2cc190SJeff Kirsher in_modifier, op_modifier, op, timeout); 7285a2cc190SJeff Kirsher } 7295a2cc190SJeff Kirsher EXPORT_SYMBOL_GPL(__mlx4_cmd); 7305a2cc190SJeff Kirsher 731e8f081aaSYevgeny Petrilin 732e8f081aaSYevgeny Petrilin static int mlx4_ARM_COMM_CHANNEL(struct mlx4_dev *dev) 733e8f081aaSYevgeny Petrilin { 734e8f081aaSYevgeny Petrilin return mlx4_cmd(dev, 0, 0, 0, MLX4_CMD_ARM_COMM_CHANNEL, 735e8f081aaSYevgeny Petrilin MLX4_CMD_TIME_CLASS_B, MLX4_CMD_NATIVE); 736e8f081aaSYevgeny Petrilin } 737e8f081aaSYevgeny Petrilin 738e8f081aaSYevgeny Petrilin static int mlx4_ACCESS_MEM(struct mlx4_dev *dev, u64 master_addr, 739e8f081aaSYevgeny Petrilin int slave, u64 slave_addr, 740e8f081aaSYevgeny Petrilin int size, int is_read) 741e8f081aaSYevgeny Petrilin { 742e8f081aaSYevgeny Petrilin u64 in_param; 743e8f081aaSYevgeny Petrilin u64 out_param; 744e8f081aaSYevgeny Petrilin 745e8f081aaSYevgeny Petrilin if ((slave_addr & 0xfff) | (master_addr & 0xfff) | 746e8f081aaSYevgeny Petrilin (slave & ~0x7f) | (size & 0xff)) { 7471a91de28SJoe Perches mlx4_err(dev, "Bad access mem params - slave_addr:0x%llx master_addr:0x%llx slave_id:%d size:%d\n", 748e8f081aaSYevgeny Petrilin slave_addr, master_addr, slave, size); 749e8f081aaSYevgeny Petrilin return -EINVAL; 750e8f081aaSYevgeny Petrilin } 751e8f081aaSYevgeny Petrilin 752e8f081aaSYevgeny Petrilin if (is_read) { 753e8f081aaSYevgeny Petrilin in_param = (u64) slave | slave_addr; 754e8f081aaSYevgeny Petrilin out_param = (u64) dev->caps.function | master_addr; 755e8f081aaSYevgeny Petrilin } else { 756e8f081aaSYevgeny Petrilin in_param = (u64) dev->caps.function | master_addr; 757e8f081aaSYevgeny Petrilin out_param = (u64) slave | slave_addr; 758e8f081aaSYevgeny Petrilin } 759e8f081aaSYevgeny Petrilin 760e8f081aaSYevgeny Petrilin return mlx4_cmd_imm(dev, in_param, &out_param, size, 0, 761e8f081aaSYevgeny Petrilin MLX4_CMD_ACCESS_MEM, 762e8f081aaSYevgeny Petrilin MLX4_CMD_TIME_CLASS_A, MLX4_CMD_NATIVE); 763e8f081aaSYevgeny Petrilin } 764e8f081aaSYevgeny Petrilin 7650a9a0188SJack Morgenstein static int query_pkey_block(struct mlx4_dev *dev, u8 port, u16 index, u16 *pkey, 7660a9a0188SJack Morgenstein struct mlx4_cmd_mailbox *inbox, 7670a9a0188SJack Morgenstein struct mlx4_cmd_mailbox *outbox) 7680a9a0188SJack Morgenstein { 7690a9a0188SJack Morgenstein struct ib_smp *in_mad = (struct ib_smp *)(inbox->buf); 7700a9a0188SJack Morgenstein struct ib_smp *out_mad = (struct ib_smp *)(outbox->buf); 7710a9a0188SJack Morgenstein int err; 7720a9a0188SJack Morgenstein int i; 7730a9a0188SJack Morgenstein 7740a9a0188SJack Morgenstein if (index & 0x1f) 7750a9a0188SJack Morgenstein return -EINVAL; 7760a9a0188SJack Morgenstein 7770a9a0188SJack Morgenstein in_mad->attr_mod = cpu_to_be32(index / 32); 7780a9a0188SJack Morgenstein 7790a9a0188SJack Morgenstein err = mlx4_cmd_box(dev, inbox->dma, outbox->dma, port, 3, 7800a9a0188SJack Morgenstein MLX4_CMD_MAD_IFC, MLX4_CMD_TIME_CLASS_C, 7810a9a0188SJack Morgenstein MLX4_CMD_NATIVE); 7820a9a0188SJack Morgenstein if (err) 7830a9a0188SJack Morgenstein return err; 7840a9a0188SJack Morgenstein 7850a9a0188SJack Morgenstein for (i = 0; i < 32; ++i) 7860a9a0188SJack Morgenstein pkey[i] = be16_to_cpu(((__be16 *) out_mad->data)[i]); 7870a9a0188SJack Morgenstein 7880a9a0188SJack Morgenstein return err; 7890a9a0188SJack Morgenstein } 7900a9a0188SJack Morgenstein 7910a9a0188SJack Morgenstein static int get_full_pkey_table(struct mlx4_dev *dev, u8 port, u16 *table, 7920a9a0188SJack Morgenstein struct mlx4_cmd_mailbox *inbox, 7930a9a0188SJack Morgenstein struct mlx4_cmd_mailbox *outbox) 7940a9a0188SJack Morgenstein { 7950a9a0188SJack Morgenstein int i; 7960a9a0188SJack Morgenstein int err; 7970a9a0188SJack Morgenstein 7980a9a0188SJack Morgenstein for (i = 0; i < dev->caps.pkey_table_len[port]; i += 32) { 7990a9a0188SJack Morgenstein err = query_pkey_block(dev, port, i, table + i, inbox, outbox); 8000a9a0188SJack Morgenstein if (err) 8010a9a0188SJack Morgenstein return err; 8020a9a0188SJack Morgenstein } 8030a9a0188SJack Morgenstein 8040a9a0188SJack Morgenstein return 0; 8050a9a0188SJack Morgenstein } 8060a9a0188SJack Morgenstein #define PORT_CAPABILITY_LOCATION_IN_SMP 20 8070a9a0188SJack Morgenstein #define PORT_STATE_OFFSET 32 8080a9a0188SJack Morgenstein 8090a9a0188SJack Morgenstein static enum ib_port_state vf_port_state(struct mlx4_dev *dev, int port, int vf) 8100a9a0188SJack Morgenstein { 811a0c64a17SJack Morgenstein if (mlx4_get_slave_port_state(dev, vf, port) == SLAVE_PORT_UP) 812a0c64a17SJack Morgenstein return IB_PORT_ACTIVE; 813a0c64a17SJack Morgenstein else 8140a9a0188SJack Morgenstein return IB_PORT_DOWN; 8150a9a0188SJack Morgenstein } 8160a9a0188SJack Morgenstein 8170a9a0188SJack Morgenstein static int mlx4_MAD_IFC_wrapper(struct mlx4_dev *dev, int slave, 8180a9a0188SJack Morgenstein struct mlx4_vhcr *vhcr, 8190a9a0188SJack Morgenstein struct mlx4_cmd_mailbox *inbox, 8200a9a0188SJack Morgenstein struct mlx4_cmd_mailbox *outbox, 8210a9a0188SJack Morgenstein struct mlx4_cmd_info *cmd) 8220a9a0188SJack Morgenstein { 8230a9a0188SJack Morgenstein struct ib_smp *smp = inbox->buf; 8240a9a0188SJack Morgenstein u32 index; 8250a9a0188SJack Morgenstein u8 port; 82697982f5aSJack Morgenstein u8 opcode_modifier; 8270a9a0188SJack Morgenstein u16 *table; 8280a9a0188SJack Morgenstein int err; 8290a9a0188SJack Morgenstein int vidx, pidx; 83097982f5aSJack Morgenstein int network_view; 8310a9a0188SJack Morgenstein struct mlx4_priv *priv = mlx4_priv(dev); 8320a9a0188SJack Morgenstein struct ib_smp *outsmp = outbox->buf; 8330a9a0188SJack Morgenstein __be16 *outtab = (__be16 *)(outsmp->data); 8340a9a0188SJack Morgenstein __be32 slave_cap_mask; 835afa8fd1dSJack Morgenstein __be64 slave_node_guid; 83697982f5aSJack Morgenstein 8370a9a0188SJack Morgenstein port = vhcr->in_modifier; 8380a9a0188SJack Morgenstein 83997982f5aSJack Morgenstein /* network-view bit is for driver use only, and should not be passed to FW */ 84097982f5aSJack Morgenstein opcode_modifier = vhcr->op_modifier & ~0x8; /* clear netw view bit */ 84197982f5aSJack Morgenstein network_view = !!(vhcr->op_modifier & 0x8); 84297982f5aSJack Morgenstein 8430a9a0188SJack Morgenstein if (smp->base_version == 1 && 8440a9a0188SJack Morgenstein smp->mgmt_class == IB_MGMT_CLASS_SUBN_LID_ROUTED && 8450a9a0188SJack Morgenstein smp->class_version == 1) { 84697982f5aSJack Morgenstein /* host view is paravirtualized */ 84797982f5aSJack Morgenstein if (!network_view && smp->method == IB_MGMT_METHOD_GET) { 8480a9a0188SJack Morgenstein if (smp->attr_id == IB_SMP_ATTR_PKEY_TABLE) { 8490a9a0188SJack Morgenstein index = be32_to_cpu(smp->attr_mod); 8500a9a0188SJack Morgenstein if (port < 1 || port > dev->caps.num_ports) 8510a9a0188SJack Morgenstein return -EINVAL; 8520a9a0188SJack Morgenstein table = kcalloc(dev->caps.pkey_table_len[port], sizeof *table, GFP_KERNEL); 8530a9a0188SJack Morgenstein if (!table) 8540a9a0188SJack Morgenstein return -ENOMEM; 8550a9a0188SJack Morgenstein /* need to get the full pkey table because the paravirtualized 8560a9a0188SJack Morgenstein * pkeys may be scattered among several pkey blocks. 8570a9a0188SJack Morgenstein */ 8580a9a0188SJack Morgenstein err = get_full_pkey_table(dev, port, table, inbox, outbox); 8590a9a0188SJack Morgenstein if (!err) { 8600a9a0188SJack Morgenstein for (vidx = index * 32; vidx < (index + 1) * 32; ++vidx) { 8610a9a0188SJack Morgenstein pidx = priv->virt2phys_pkey[slave][port - 1][vidx]; 8620a9a0188SJack Morgenstein outtab[vidx % 32] = cpu_to_be16(table[pidx]); 8630a9a0188SJack Morgenstein } 8640a9a0188SJack Morgenstein } 8650a9a0188SJack Morgenstein kfree(table); 8660a9a0188SJack Morgenstein return err; 8670a9a0188SJack Morgenstein } 8680a9a0188SJack Morgenstein if (smp->attr_id == IB_SMP_ATTR_PORT_INFO) { 8690a9a0188SJack Morgenstein /*get the slave specific caps:*/ 8700a9a0188SJack Morgenstein /*do the command */ 8710a9a0188SJack Morgenstein err = mlx4_cmd_box(dev, inbox->dma, outbox->dma, 87297982f5aSJack Morgenstein vhcr->in_modifier, opcode_modifier, 8730a9a0188SJack Morgenstein vhcr->op, MLX4_CMD_TIME_CLASS_C, MLX4_CMD_NATIVE); 8740a9a0188SJack Morgenstein /* modify the response for slaves */ 8750a9a0188SJack Morgenstein if (!err && slave != mlx4_master_func_num(dev)) { 8760a9a0188SJack Morgenstein u8 *state = outsmp->data + PORT_STATE_OFFSET; 8770a9a0188SJack Morgenstein 8780a9a0188SJack Morgenstein *state = (*state & 0xf0) | vf_port_state(dev, port, slave); 8790a9a0188SJack Morgenstein slave_cap_mask = priv->mfunc.master.slave_state[slave].ib_cap_mask[port]; 8800a9a0188SJack Morgenstein memcpy(outsmp->data + PORT_CAPABILITY_LOCATION_IN_SMP, &slave_cap_mask, 4); 8810a9a0188SJack Morgenstein } 8820a9a0188SJack Morgenstein return err; 8830a9a0188SJack Morgenstein } 8840a9a0188SJack Morgenstein if (smp->attr_id == IB_SMP_ATTR_GUID_INFO) { 8850a9a0188SJack Morgenstein /* compute slave's gid block */ 8860a9a0188SJack Morgenstein smp->attr_mod = cpu_to_be32(slave / 8); 8870a9a0188SJack Morgenstein /* execute cmd */ 8880a9a0188SJack Morgenstein err = mlx4_cmd_box(dev, inbox->dma, outbox->dma, 88997982f5aSJack Morgenstein vhcr->in_modifier, opcode_modifier, 8900a9a0188SJack Morgenstein vhcr->op, MLX4_CMD_TIME_CLASS_C, MLX4_CMD_NATIVE); 8910a9a0188SJack Morgenstein if (!err) { 8920a9a0188SJack Morgenstein /* if needed, move slave gid to index 0 */ 8930a9a0188SJack Morgenstein if (slave % 8) 8940a9a0188SJack Morgenstein memcpy(outsmp->data, 8950a9a0188SJack Morgenstein outsmp->data + (slave % 8) * 8, 8); 8960a9a0188SJack Morgenstein /* delete all other gids */ 8970a9a0188SJack Morgenstein memset(outsmp->data + 8, 0, 56); 8980a9a0188SJack Morgenstein } 8990a9a0188SJack Morgenstein return err; 9000a9a0188SJack Morgenstein } 901afa8fd1dSJack Morgenstein if (smp->attr_id == IB_SMP_ATTR_NODE_INFO) { 902afa8fd1dSJack Morgenstein err = mlx4_cmd_box(dev, inbox->dma, outbox->dma, 90397982f5aSJack Morgenstein vhcr->in_modifier, opcode_modifier, 904afa8fd1dSJack Morgenstein vhcr->op, MLX4_CMD_TIME_CLASS_C, MLX4_CMD_NATIVE); 905afa8fd1dSJack Morgenstein if (!err) { 906afa8fd1dSJack Morgenstein slave_node_guid = mlx4_get_slave_node_guid(dev, slave); 907afa8fd1dSJack Morgenstein memcpy(outsmp->data + 12, &slave_node_guid, 8); 908afa8fd1dSJack Morgenstein } 909afa8fd1dSJack Morgenstein return err; 910afa8fd1dSJack Morgenstein } 9110a9a0188SJack Morgenstein } 9120a9a0188SJack Morgenstein } 91397982f5aSJack Morgenstein 91497982f5aSJack Morgenstein /* Non-privileged VFs are only allowed "host" view LID-routed 'Get' MADs. 91597982f5aSJack Morgenstein * These are the MADs used by ib verbs (such as ib_query_gids). 91697982f5aSJack Morgenstein */ 9170a9a0188SJack Morgenstein if (slave != mlx4_master_func_num(dev) && 91897982f5aSJack Morgenstein !mlx4_vf_smi_enabled(dev, slave, port)) { 91997982f5aSJack Morgenstein if (!(smp->mgmt_class == IB_MGMT_CLASS_SUBN_LID_ROUTED && 92097982f5aSJack Morgenstein smp->method == IB_MGMT_METHOD_GET) || network_view) { 92197982f5aSJack Morgenstein mlx4_err(dev, "Unprivileged slave %d is trying to execute a Subnet MGMT MAD, class 0x%x, method 0x%x, view=%s for attr 0x%x. Rejecting\n", 9220a9a0188SJack Morgenstein slave, smp->method, smp->mgmt_class, 92397982f5aSJack Morgenstein network_view ? "Network" : "Host", 9240a9a0188SJack Morgenstein be16_to_cpu(smp->attr_id)); 9250a9a0188SJack Morgenstein return -EPERM; 9260a9a0188SJack Morgenstein } 92797982f5aSJack Morgenstein } 92897982f5aSJack Morgenstein 9290a9a0188SJack Morgenstein return mlx4_cmd_box(dev, inbox->dma, outbox->dma, 93097982f5aSJack Morgenstein vhcr->in_modifier, opcode_modifier, 9310a9a0188SJack Morgenstein vhcr->op, MLX4_CMD_TIME_CLASS_C, MLX4_CMD_NATIVE); 9320a9a0188SJack Morgenstein } 9330a9a0188SJack Morgenstein 934b7475794SOr Gerlitz static int mlx4_CMD_EPERM_wrapper(struct mlx4_dev *dev, int slave, 935fe6f700dSYevgeny Petrilin struct mlx4_vhcr *vhcr, 936fe6f700dSYevgeny Petrilin struct mlx4_cmd_mailbox *inbox, 937fe6f700dSYevgeny Petrilin struct mlx4_cmd_mailbox *outbox, 938fe6f700dSYevgeny Petrilin struct mlx4_cmd_info *cmd) 939fe6f700dSYevgeny Petrilin { 940fe6f700dSYevgeny Petrilin return -EPERM; 941fe6f700dSYevgeny Petrilin } 942fe6f700dSYevgeny Petrilin 943e8f081aaSYevgeny Petrilin int mlx4_DMA_wrapper(struct mlx4_dev *dev, int slave, 944e8f081aaSYevgeny Petrilin struct mlx4_vhcr *vhcr, 945e8f081aaSYevgeny Petrilin struct mlx4_cmd_mailbox *inbox, 946e8f081aaSYevgeny Petrilin struct mlx4_cmd_mailbox *outbox, 947e8f081aaSYevgeny Petrilin struct mlx4_cmd_info *cmd) 948e8f081aaSYevgeny Petrilin { 949e8f081aaSYevgeny Petrilin u64 in_param; 950e8f081aaSYevgeny Petrilin u64 out_param; 951e8f081aaSYevgeny Petrilin int err; 952e8f081aaSYevgeny Petrilin 953e8f081aaSYevgeny Petrilin in_param = cmd->has_inbox ? (u64) inbox->dma : vhcr->in_param; 954e8f081aaSYevgeny Petrilin out_param = cmd->has_outbox ? (u64) outbox->dma : vhcr->out_param; 955e8f081aaSYevgeny Petrilin if (cmd->encode_slave_id) { 956e8f081aaSYevgeny Petrilin in_param &= 0xffffffffffffff00ll; 957e8f081aaSYevgeny Petrilin in_param |= slave; 958e8f081aaSYevgeny Petrilin } 959e8f081aaSYevgeny Petrilin 960e8f081aaSYevgeny Petrilin err = __mlx4_cmd(dev, in_param, &out_param, cmd->out_is_imm, 961e8f081aaSYevgeny Petrilin vhcr->in_modifier, vhcr->op_modifier, vhcr->op, 962e8f081aaSYevgeny Petrilin MLX4_CMD_TIME_CLASS_A, MLX4_CMD_NATIVE); 963e8f081aaSYevgeny Petrilin 964e8f081aaSYevgeny Petrilin if (cmd->out_is_imm) 965e8f081aaSYevgeny Petrilin vhcr->out_param = out_param; 966e8f081aaSYevgeny Petrilin 967e8f081aaSYevgeny Petrilin return err; 968e8f081aaSYevgeny Petrilin } 969e8f081aaSYevgeny Petrilin 970e8f081aaSYevgeny Petrilin static struct mlx4_cmd_info cmd_info[] = { 971e8f081aaSYevgeny Petrilin { 972e8f081aaSYevgeny Petrilin .opcode = MLX4_CMD_QUERY_FW, 973e8f081aaSYevgeny Petrilin .has_inbox = false, 974e8f081aaSYevgeny Petrilin .has_outbox = true, 975e8f081aaSYevgeny Petrilin .out_is_imm = false, 976e8f081aaSYevgeny Petrilin .encode_slave_id = false, 977e8f081aaSYevgeny Petrilin .verify = NULL, 978b91cb3ebSJack Morgenstein .wrapper = mlx4_QUERY_FW_wrapper 979e8f081aaSYevgeny Petrilin }, 980e8f081aaSYevgeny Petrilin { 981e8f081aaSYevgeny Petrilin .opcode = MLX4_CMD_QUERY_HCA, 982e8f081aaSYevgeny Petrilin .has_inbox = false, 983e8f081aaSYevgeny Petrilin .has_outbox = true, 984e8f081aaSYevgeny Petrilin .out_is_imm = false, 985e8f081aaSYevgeny Petrilin .encode_slave_id = false, 986e8f081aaSYevgeny Petrilin .verify = NULL, 987e8f081aaSYevgeny Petrilin .wrapper = NULL 988e8f081aaSYevgeny Petrilin }, 989e8f081aaSYevgeny Petrilin { 990e8f081aaSYevgeny Petrilin .opcode = MLX4_CMD_QUERY_DEV_CAP, 991e8f081aaSYevgeny Petrilin .has_inbox = false, 992e8f081aaSYevgeny Petrilin .has_outbox = true, 993e8f081aaSYevgeny Petrilin .out_is_imm = false, 994e8f081aaSYevgeny Petrilin .encode_slave_id = false, 995e8f081aaSYevgeny Petrilin .verify = NULL, 996b91cb3ebSJack Morgenstein .wrapper = mlx4_QUERY_DEV_CAP_wrapper 997e8f081aaSYevgeny Petrilin }, 998c82e9aa0SEli Cohen { 999c82e9aa0SEli Cohen .opcode = MLX4_CMD_QUERY_FUNC_CAP, 1000c82e9aa0SEli Cohen .has_inbox = false, 1001c82e9aa0SEli Cohen .has_outbox = true, 1002c82e9aa0SEli Cohen .out_is_imm = false, 1003c82e9aa0SEli Cohen .encode_slave_id = false, 1004c82e9aa0SEli Cohen .verify = NULL, 1005c82e9aa0SEli Cohen .wrapper = mlx4_QUERY_FUNC_CAP_wrapper 1006c82e9aa0SEli Cohen }, 1007c82e9aa0SEli Cohen { 1008c82e9aa0SEli Cohen .opcode = MLX4_CMD_QUERY_ADAPTER, 1009c82e9aa0SEli Cohen .has_inbox = false, 1010c82e9aa0SEli Cohen .has_outbox = true, 1011c82e9aa0SEli Cohen .out_is_imm = false, 1012c82e9aa0SEli Cohen .encode_slave_id = false, 1013c82e9aa0SEli Cohen .verify = NULL, 1014c82e9aa0SEli Cohen .wrapper = NULL 1015c82e9aa0SEli Cohen }, 1016c82e9aa0SEli Cohen { 1017c82e9aa0SEli Cohen .opcode = MLX4_CMD_INIT_PORT, 1018c82e9aa0SEli Cohen .has_inbox = false, 1019c82e9aa0SEli Cohen .has_outbox = false, 1020c82e9aa0SEli Cohen .out_is_imm = false, 1021c82e9aa0SEli Cohen .encode_slave_id = false, 1022c82e9aa0SEli Cohen .verify = NULL, 1023c82e9aa0SEli Cohen .wrapper = mlx4_INIT_PORT_wrapper 1024c82e9aa0SEli Cohen }, 1025c82e9aa0SEli Cohen { 1026c82e9aa0SEli Cohen .opcode = MLX4_CMD_CLOSE_PORT, 1027c82e9aa0SEli Cohen .has_inbox = false, 1028c82e9aa0SEli Cohen .has_outbox = false, 1029c82e9aa0SEli Cohen .out_is_imm = false, 1030c82e9aa0SEli Cohen .encode_slave_id = false, 1031c82e9aa0SEli Cohen .verify = NULL, 1032c82e9aa0SEli Cohen .wrapper = mlx4_CLOSE_PORT_wrapper 1033c82e9aa0SEli Cohen }, 1034c82e9aa0SEli Cohen { 1035c82e9aa0SEli Cohen .opcode = MLX4_CMD_QUERY_PORT, 1036c82e9aa0SEli Cohen .has_inbox = false, 1037c82e9aa0SEli Cohen .has_outbox = true, 1038c82e9aa0SEli Cohen .out_is_imm = false, 1039c82e9aa0SEli Cohen .encode_slave_id = false, 1040c82e9aa0SEli Cohen .verify = NULL, 1041c82e9aa0SEli Cohen .wrapper = mlx4_QUERY_PORT_wrapper 1042c82e9aa0SEli Cohen }, 1043c82e9aa0SEli Cohen { 1044ffe455adSEugenia Emantayev .opcode = MLX4_CMD_SET_PORT, 1045ffe455adSEugenia Emantayev .has_inbox = true, 1046ffe455adSEugenia Emantayev .has_outbox = false, 1047ffe455adSEugenia Emantayev .out_is_imm = false, 1048ffe455adSEugenia Emantayev .encode_slave_id = false, 1049ffe455adSEugenia Emantayev .verify = NULL, 1050ffe455adSEugenia Emantayev .wrapper = mlx4_SET_PORT_wrapper 1051ffe455adSEugenia Emantayev }, 1052ffe455adSEugenia Emantayev { 1053c82e9aa0SEli Cohen .opcode = MLX4_CMD_MAP_EQ, 1054c82e9aa0SEli Cohen .has_inbox = false, 1055c82e9aa0SEli Cohen .has_outbox = false, 1056c82e9aa0SEli Cohen .out_is_imm = false, 1057c82e9aa0SEli Cohen .encode_slave_id = false, 1058c82e9aa0SEli Cohen .verify = NULL, 1059c82e9aa0SEli Cohen .wrapper = mlx4_MAP_EQ_wrapper 1060c82e9aa0SEli Cohen }, 1061c82e9aa0SEli Cohen { 1062c82e9aa0SEli Cohen .opcode = MLX4_CMD_SW2HW_EQ, 1063c82e9aa0SEli Cohen .has_inbox = true, 1064c82e9aa0SEli Cohen .has_outbox = false, 1065c82e9aa0SEli Cohen .out_is_imm = false, 1066c82e9aa0SEli Cohen .encode_slave_id = true, 1067c82e9aa0SEli Cohen .verify = NULL, 1068c82e9aa0SEli Cohen .wrapper = mlx4_SW2HW_EQ_wrapper 1069c82e9aa0SEli Cohen }, 1070c82e9aa0SEli Cohen { 1071c82e9aa0SEli Cohen .opcode = MLX4_CMD_HW_HEALTH_CHECK, 1072c82e9aa0SEli Cohen .has_inbox = false, 1073c82e9aa0SEli Cohen .has_outbox = false, 1074c82e9aa0SEli Cohen .out_is_imm = false, 1075c82e9aa0SEli Cohen .encode_slave_id = false, 1076c82e9aa0SEli Cohen .verify = NULL, 1077c82e9aa0SEli Cohen .wrapper = NULL 1078c82e9aa0SEli Cohen }, 1079c82e9aa0SEli Cohen { 1080c82e9aa0SEli Cohen .opcode = MLX4_CMD_NOP, 1081c82e9aa0SEli Cohen .has_inbox = false, 1082c82e9aa0SEli Cohen .has_outbox = false, 1083c82e9aa0SEli Cohen .out_is_imm = false, 1084c82e9aa0SEli Cohen .encode_slave_id = false, 1085c82e9aa0SEli Cohen .verify = NULL, 1086c82e9aa0SEli Cohen .wrapper = NULL 1087c82e9aa0SEli Cohen }, 1088c82e9aa0SEli Cohen { 1089d18f141aSOr Gerlitz .opcode = MLX4_CMD_CONFIG_DEV, 1090d18f141aSOr Gerlitz .has_inbox = false, 1091d475c95bSMatan Barak .has_outbox = true, 1092d18f141aSOr Gerlitz .out_is_imm = false, 1093d18f141aSOr Gerlitz .encode_slave_id = false, 1094d18f141aSOr Gerlitz .verify = NULL, 1095d475c95bSMatan Barak .wrapper = mlx4_CONFIG_DEV_wrapper 1096d18f141aSOr Gerlitz }, 1097d18f141aSOr Gerlitz { 1098c82e9aa0SEli Cohen .opcode = MLX4_CMD_ALLOC_RES, 1099c82e9aa0SEli Cohen .has_inbox = false, 1100c82e9aa0SEli Cohen .has_outbox = false, 1101c82e9aa0SEli Cohen .out_is_imm = true, 1102c82e9aa0SEli Cohen .encode_slave_id = false, 1103c82e9aa0SEli Cohen .verify = NULL, 1104c82e9aa0SEli Cohen .wrapper = mlx4_ALLOC_RES_wrapper 1105c82e9aa0SEli Cohen }, 1106c82e9aa0SEli Cohen { 1107c82e9aa0SEli Cohen .opcode = MLX4_CMD_FREE_RES, 1108c82e9aa0SEli Cohen .has_inbox = false, 1109c82e9aa0SEli Cohen .has_outbox = false, 1110c82e9aa0SEli Cohen .out_is_imm = false, 1111c82e9aa0SEli Cohen .encode_slave_id = false, 1112c82e9aa0SEli Cohen .verify = NULL, 1113c82e9aa0SEli Cohen .wrapper = mlx4_FREE_RES_wrapper 1114c82e9aa0SEli Cohen }, 1115c82e9aa0SEli Cohen { 1116c82e9aa0SEli Cohen .opcode = MLX4_CMD_SW2HW_MPT, 1117c82e9aa0SEli Cohen .has_inbox = true, 1118c82e9aa0SEli Cohen .has_outbox = false, 1119c82e9aa0SEli Cohen .out_is_imm = false, 1120c82e9aa0SEli Cohen .encode_slave_id = true, 1121c82e9aa0SEli Cohen .verify = NULL, 1122c82e9aa0SEli Cohen .wrapper = mlx4_SW2HW_MPT_wrapper 1123c82e9aa0SEli Cohen }, 1124c82e9aa0SEli Cohen { 1125c82e9aa0SEli Cohen .opcode = MLX4_CMD_QUERY_MPT, 1126c82e9aa0SEli Cohen .has_inbox = false, 1127c82e9aa0SEli Cohen .has_outbox = true, 1128c82e9aa0SEli Cohen .out_is_imm = false, 1129c82e9aa0SEli Cohen .encode_slave_id = false, 1130c82e9aa0SEli Cohen .verify = NULL, 1131c82e9aa0SEli Cohen .wrapper = mlx4_QUERY_MPT_wrapper 1132c82e9aa0SEli Cohen }, 1133c82e9aa0SEli Cohen { 1134c82e9aa0SEli Cohen .opcode = MLX4_CMD_HW2SW_MPT, 1135c82e9aa0SEli Cohen .has_inbox = false, 1136c82e9aa0SEli Cohen .has_outbox = false, 1137c82e9aa0SEli Cohen .out_is_imm = false, 1138c82e9aa0SEli Cohen .encode_slave_id = false, 1139c82e9aa0SEli Cohen .verify = NULL, 1140c82e9aa0SEli Cohen .wrapper = mlx4_HW2SW_MPT_wrapper 1141c82e9aa0SEli Cohen }, 1142c82e9aa0SEli Cohen { 1143c82e9aa0SEli Cohen .opcode = MLX4_CMD_READ_MTT, 1144c82e9aa0SEli Cohen .has_inbox = false, 1145c82e9aa0SEli Cohen .has_outbox = true, 1146c82e9aa0SEli Cohen .out_is_imm = false, 1147c82e9aa0SEli Cohen .encode_slave_id = false, 1148c82e9aa0SEli Cohen .verify = NULL, 1149c82e9aa0SEli Cohen .wrapper = NULL 1150c82e9aa0SEli Cohen }, 1151c82e9aa0SEli Cohen { 1152c82e9aa0SEli Cohen .opcode = MLX4_CMD_WRITE_MTT, 1153c82e9aa0SEli Cohen .has_inbox = true, 1154c82e9aa0SEli Cohen .has_outbox = false, 1155c82e9aa0SEli Cohen .out_is_imm = false, 1156c82e9aa0SEli Cohen .encode_slave_id = false, 1157c82e9aa0SEli Cohen .verify = NULL, 1158c82e9aa0SEli Cohen .wrapper = mlx4_WRITE_MTT_wrapper 1159c82e9aa0SEli Cohen }, 1160c82e9aa0SEli Cohen { 1161c82e9aa0SEli Cohen .opcode = MLX4_CMD_SYNC_TPT, 1162c82e9aa0SEli Cohen .has_inbox = true, 1163c82e9aa0SEli Cohen .has_outbox = false, 1164c82e9aa0SEli Cohen .out_is_imm = false, 1165c82e9aa0SEli Cohen .encode_slave_id = false, 1166c82e9aa0SEli Cohen .verify = NULL, 1167c82e9aa0SEli Cohen .wrapper = NULL 1168c82e9aa0SEli Cohen }, 1169c82e9aa0SEli Cohen { 1170c82e9aa0SEli Cohen .opcode = MLX4_CMD_HW2SW_EQ, 1171c82e9aa0SEli Cohen .has_inbox = false, 1172c82e9aa0SEli Cohen .has_outbox = true, 1173c82e9aa0SEli Cohen .out_is_imm = false, 1174c82e9aa0SEli Cohen .encode_slave_id = true, 1175c82e9aa0SEli Cohen .verify = NULL, 1176c82e9aa0SEli Cohen .wrapper = mlx4_HW2SW_EQ_wrapper 1177c82e9aa0SEli Cohen }, 1178c82e9aa0SEli Cohen { 1179c82e9aa0SEli Cohen .opcode = MLX4_CMD_QUERY_EQ, 1180c82e9aa0SEli Cohen .has_inbox = false, 1181c82e9aa0SEli Cohen .has_outbox = true, 1182c82e9aa0SEli Cohen .out_is_imm = false, 1183c82e9aa0SEli Cohen .encode_slave_id = true, 1184c82e9aa0SEli Cohen .verify = NULL, 1185c82e9aa0SEli Cohen .wrapper = mlx4_QUERY_EQ_wrapper 1186c82e9aa0SEli Cohen }, 1187c82e9aa0SEli Cohen { 1188c82e9aa0SEli Cohen .opcode = MLX4_CMD_SW2HW_CQ, 1189c82e9aa0SEli Cohen .has_inbox = true, 1190c82e9aa0SEli Cohen .has_outbox = false, 1191c82e9aa0SEli Cohen .out_is_imm = false, 1192c82e9aa0SEli Cohen .encode_slave_id = true, 1193c82e9aa0SEli Cohen .verify = NULL, 1194c82e9aa0SEli Cohen .wrapper = mlx4_SW2HW_CQ_wrapper 1195c82e9aa0SEli Cohen }, 1196c82e9aa0SEli Cohen { 1197c82e9aa0SEli Cohen .opcode = MLX4_CMD_HW2SW_CQ, 1198c82e9aa0SEli Cohen .has_inbox = false, 1199c82e9aa0SEli Cohen .has_outbox = false, 1200c82e9aa0SEli Cohen .out_is_imm = false, 1201c82e9aa0SEli Cohen .encode_slave_id = false, 1202c82e9aa0SEli Cohen .verify = NULL, 1203c82e9aa0SEli Cohen .wrapper = mlx4_HW2SW_CQ_wrapper 1204c82e9aa0SEli Cohen }, 1205c82e9aa0SEli Cohen { 1206c82e9aa0SEli Cohen .opcode = MLX4_CMD_QUERY_CQ, 1207c82e9aa0SEli Cohen .has_inbox = false, 1208c82e9aa0SEli Cohen .has_outbox = true, 1209c82e9aa0SEli Cohen .out_is_imm = false, 1210c82e9aa0SEli Cohen .encode_slave_id = false, 1211c82e9aa0SEli Cohen .verify = NULL, 1212c82e9aa0SEli Cohen .wrapper = mlx4_QUERY_CQ_wrapper 1213c82e9aa0SEli Cohen }, 1214c82e9aa0SEli Cohen { 1215c82e9aa0SEli Cohen .opcode = MLX4_CMD_MODIFY_CQ, 1216c82e9aa0SEli Cohen .has_inbox = true, 1217c82e9aa0SEli Cohen .has_outbox = false, 1218c82e9aa0SEli Cohen .out_is_imm = true, 1219c82e9aa0SEli Cohen .encode_slave_id = false, 1220c82e9aa0SEli Cohen .verify = NULL, 1221c82e9aa0SEli Cohen .wrapper = mlx4_MODIFY_CQ_wrapper 1222c82e9aa0SEli Cohen }, 1223c82e9aa0SEli Cohen { 1224c82e9aa0SEli Cohen .opcode = MLX4_CMD_SW2HW_SRQ, 1225c82e9aa0SEli Cohen .has_inbox = true, 1226c82e9aa0SEli Cohen .has_outbox = false, 1227c82e9aa0SEli Cohen .out_is_imm = false, 1228c82e9aa0SEli Cohen .encode_slave_id = true, 1229c82e9aa0SEli Cohen .verify = NULL, 1230c82e9aa0SEli Cohen .wrapper = mlx4_SW2HW_SRQ_wrapper 1231c82e9aa0SEli Cohen }, 1232c82e9aa0SEli Cohen { 1233c82e9aa0SEli Cohen .opcode = MLX4_CMD_HW2SW_SRQ, 1234c82e9aa0SEli Cohen .has_inbox = false, 1235c82e9aa0SEli Cohen .has_outbox = false, 1236c82e9aa0SEli Cohen .out_is_imm = false, 1237c82e9aa0SEli Cohen .encode_slave_id = false, 1238c82e9aa0SEli Cohen .verify = NULL, 1239c82e9aa0SEli Cohen .wrapper = mlx4_HW2SW_SRQ_wrapper 1240c82e9aa0SEli Cohen }, 1241c82e9aa0SEli Cohen { 1242c82e9aa0SEli Cohen .opcode = MLX4_CMD_QUERY_SRQ, 1243c82e9aa0SEli Cohen .has_inbox = false, 1244c82e9aa0SEli Cohen .has_outbox = true, 1245c82e9aa0SEli Cohen .out_is_imm = false, 1246c82e9aa0SEli Cohen .encode_slave_id = false, 1247c82e9aa0SEli Cohen .verify = NULL, 1248c82e9aa0SEli Cohen .wrapper = mlx4_QUERY_SRQ_wrapper 1249c82e9aa0SEli Cohen }, 1250c82e9aa0SEli Cohen { 1251c82e9aa0SEli Cohen .opcode = MLX4_CMD_ARM_SRQ, 1252c82e9aa0SEli Cohen .has_inbox = false, 1253c82e9aa0SEli Cohen .has_outbox = false, 1254c82e9aa0SEli Cohen .out_is_imm = false, 1255c82e9aa0SEli Cohen .encode_slave_id = false, 1256c82e9aa0SEli Cohen .verify = NULL, 1257c82e9aa0SEli Cohen .wrapper = mlx4_ARM_SRQ_wrapper 1258c82e9aa0SEli Cohen }, 1259c82e9aa0SEli Cohen { 1260c82e9aa0SEli Cohen .opcode = MLX4_CMD_RST2INIT_QP, 1261c82e9aa0SEli Cohen .has_inbox = true, 1262c82e9aa0SEli Cohen .has_outbox = false, 1263c82e9aa0SEli Cohen .out_is_imm = false, 1264c82e9aa0SEli Cohen .encode_slave_id = true, 1265c82e9aa0SEli Cohen .verify = NULL, 1266c82e9aa0SEli Cohen .wrapper = mlx4_RST2INIT_QP_wrapper 1267c82e9aa0SEli Cohen }, 1268c82e9aa0SEli Cohen { 1269c82e9aa0SEli Cohen .opcode = MLX4_CMD_INIT2INIT_QP, 1270c82e9aa0SEli Cohen .has_inbox = true, 1271c82e9aa0SEli Cohen .has_outbox = false, 1272c82e9aa0SEli Cohen .out_is_imm = false, 1273c82e9aa0SEli Cohen .encode_slave_id = false, 1274c82e9aa0SEli Cohen .verify = NULL, 127554679e14SJack Morgenstein .wrapper = mlx4_INIT2INIT_QP_wrapper 1276c82e9aa0SEli Cohen }, 1277c82e9aa0SEli Cohen { 1278c82e9aa0SEli Cohen .opcode = MLX4_CMD_INIT2RTR_QP, 1279c82e9aa0SEli Cohen .has_inbox = true, 1280c82e9aa0SEli Cohen .has_outbox = false, 1281c82e9aa0SEli Cohen .out_is_imm = false, 1282c82e9aa0SEli Cohen .encode_slave_id = false, 1283c82e9aa0SEli Cohen .verify = NULL, 1284c82e9aa0SEli Cohen .wrapper = mlx4_INIT2RTR_QP_wrapper 1285c82e9aa0SEli Cohen }, 1286c82e9aa0SEli Cohen { 1287c82e9aa0SEli Cohen .opcode = MLX4_CMD_RTR2RTS_QP, 1288c82e9aa0SEli Cohen .has_inbox = true, 1289c82e9aa0SEli Cohen .has_outbox = false, 1290c82e9aa0SEli Cohen .out_is_imm = false, 1291c82e9aa0SEli Cohen .encode_slave_id = false, 1292c82e9aa0SEli Cohen .verify = NULL, 129354679e14SJack Morgenstein .wrapper = mlx4_RTR2RTS_QP_wrapper 1294c82e9aa0SEli Cohen }, 1295c82e9aa0SEli Cohen { 1296c82e9aa0SEli Cohen .opcode = MLX4_CMD_RTS2RTS_QP, 1297c82e9aa0SEli Cohen .has_inbox = true, 1298c82e9aa0SEli Cohen .has_outbox = false, 1299c82e9aa0SEli Cohen .out_is_imm = false, 1300c82e9aa0SEli Cohen .encode_slave_id = false, 1301c82e9aa0SEli Cohen .verify = NULL, 130254679e14SJack Morgenstein .wrapper = mlx4_RTS2RTS_QP_wrapper 1303c82e9aa0SEli Cohen }, 1304c82e9aa0SEli Cohen { 1305c82e9aa0SEli Cohen .opcode = MLX4_CMD_SQERR2RTS_QP, 1306c82e9aa0SEli Cohen .has_inbox = true, 1307c82e9aa0SEli Cohen .has_outbox = false, 1308c82e9aa0SEli Cohen .out_is_imm = false, 1309c82e9aa0SEli Cohen .encode_slave_id = false, 1310c82e9aa0SEli Cohen .verify = NULL, 131154679e14SJack Morgenstein .wrapper = mlx4_SQERR2RTS_QP_wrapper 1312c82e9aa0SEli Cohen }, 1313c82e9aa0SEli Cohen { 1314c82e9aa0SEli Cohen .opcode = MLX4_CMD_2ERR_QP, 1315c82e9aa0SEli Cohen .has_inbox = false, 1316c82e9aa0SEli Cohen .has_outbox = false, 1317c82e9aa0SEli Cohen .out_is_imm = false, 1318c82e9aa0SEli Cohen .encode_slave_id = false, 1319c82e9aa0SEli Cohen .verify = NULL, 1320c82e9aa0SEli Cohen .wrapper = mlx4_GEN_QP_wrapper 1321c82e9aa0SEli Cohen }, 1322c82e9aa0SEli Cohen { 1323c82e9aa0SEli Cohen .opcode = MLX4_CMD_RTS2SQD_QP, 1324c82e9aa0SEli Cohen .has_inbox = false, 1325c82e9aa0SEli Cohen .has_outbox = false, 1326c82e9aa0SEli Cohen .out_is_imm = false, 1327c82e9aa0SEli Cohen .encode_slave_id = false, 1328c82e9aa0SEli Cohen .verify = NULL, 1329c82e9aa0SEli Cohen .wrapper = mlx4_GEN_QP_wrapper 1330c82e9aa0SEli Cohen }, 1331c82e9aa0SEli Cohen { 1332c82e9aa0SEli Cohen .opcode = MLX4_CMD_SQD2SQD_QP, 1333c82e9aa0SEli Cohen .has_inbox = true, 1334c82e9aa0SEli Cohen .has_outbox = false, 1335c82e9aa0SEli Cohen .out_is_imm = false, 1336c82e9aa0SEli Cohen .encode_slave_id = false, 1337c82e9aa0SEli Cohen .verify = NULL, 133854679e14SJack Morgenstein .wrapper = mlx4_SQD2SQD_QP_wrapper 1339c82e9aa0SEli Cohen }, 1340c82e9aa0SEli Cohen { 1341c82e9aa0SEli Cohen .opcode = MLX4_CMD_SQD2RTS_QP, 1342c82e9aa0SEli Cohen .has_inbox = true, 1343c82e9aa0SEli Cohen .has_outbox = false, 1344c82e9aa0SEli Cohen .out_is_imm = false, 1345c82e9aa0SEli Cohen .encode_slave_id = false, 1346c82e9aa0SEli Cohen .verify = NULL, 134754679e14SJack Morgenstein .wrapper = mlx4_SQD2RTS_QP_wrapper 1348c82e9aa0SEli Cohen }, 1349c82e9aa0SEli Cohen { 1350c82e9aa0SEli Cohen .opcode = MLX4_CMD_2RST_QP, 1351c82e9aa0SEli Cohen .has_inbox = false, 1352c82e9aa0SEli Cohen .has_outbox = false, 1353c82e9aa0SEli Cohen .out_is_imm = false, 1354c82e9aa0SEli Cohen .encode_slave_id = false, 1355c82e9aa0SEli Cohen .verify = NULL, 1356c82e9aa0SEli Cohen .wrapper = mlx4_2RST_QP_wrapper 1357c82e9aa0SEli Cohen }, 1358c82e9aa0SEli Cohen { 1359c82e9aa0SEli Cohen .opcode = MLX4_CMD_QUERY_QP, 1360c82e9aa0SEli Cohen .has_inbox = false, 1361c82e9aa0SEli Cohen .has_outbox = true, 1362c82e9aa0SEli Cohen .out_is_imm = false, 1363c82e9aa0SEli Cohen .encode_slave_id = false, 1364c82e9aa0SEli Cohen .verify = NULL, 1365c82e9aa0SEli Cohen .wrapper = mlx4_GEN_QP_wrapper 1366c82e9aa0SEli Cohen }, 1367c82e9aa0SEli Cohen { 1368c82e9aa0SEli Cohen .opcode = MLX4_CMD_SUSPEND_QP, 1369c82e9aa0SEli Cohen .has_inbox = false, 1370c82e9aa0SEli Cohen .has_outbox = false, 1371c82e9aa0SEli Cohen .out_is_imm = false, 1372c82e9aa0SEli Cohen .encode_slave_id = false, 1373c82e9aa0SEli Cohen .verify = NULL, 1374c82e9aa0SEli Cohen .wrapper = mlx4_GEN_QP_wrapper 1375c82e9aa0SEli Cohen }, 1376c82e9aa0SEli Cohen { 1377c82e9aa0SEli Cohen .opcode = MLX4_CMD_UNSUSPEND_QP, 1378c82e9aa0SEli Cohen .has_inbox = false, 1379c82e9aa0SEli Cohen .has_outbox = false, 1380c82e9aa0SEli Cohen .out_is_imm = false, 1381c82e9aa0SEli Cohen .encode_slave_id = false, 1382c82e9aa0SEli Cohen .verify = NULL, 1383c82e9aa0SEli Cohen .wrapper = mlx4_GEN_QP_wrapper 1384c82e9aa0SEli Cohen }, 1385c82e9aa0SEli Cohen { 1386b01978caSJack Morgenstein .opcode = MLX4_CMD_UPDATE_QP, 1387ce8d9e0dSMatan Barak .has_inbox = true, 1388b01978caSJack Morgenstein .has_outbox = false, 1389b01978caSJack Morgenstein .out_is_imm = false, 1390b01978caSJack Morgenstein .encode_slave_id = false, 1391b01978caSJack Morgenstein .verify = NULL, 1392ce8d9e0dSMatan Barak .wrapper = mlx4_UPDATE_QP_wrapper 1393b01978caSJack Morgenstein }, 1394b01978caSJack Morgenstein { 1395fe6f700dSYevgeny Petrilin .opcode = MLX4_CMD_GET_OP_REQ, 1396fe6f700dSYevgeny Petrilin .has_inbox = false, 1397fe6f700dSYevgeny Petrilin .has_outbox = false, 1398fe6f700dSYevgeny Petrilin .out_is_imm = false, 1399fe6f700dSYevgeny Petrilin .encode_slave_id = false, 1400fe6f700dSYevgeny Petrilin .verify = NULL, 1401b7475794SOr Gerlitz .wrapper = mlx4_CMD_EPERM_wrapper, 1402fe6f700dSYevgeny Petrilin }, 1403fe6f700dSYevgeny Petrilin { 14040a9a0188SJack Morgenstein .opcode = MLX4_CMD_CONF_SPECIAL_QP, 14050a9a0188SJack Morgenstein .has_inbox = false, 14060a9a0188SJack Morgenstein .has_outbox = false, 14070a9a0188SJack Morgenstein .out_is_imm = false, 14080a9a0188SJack Morgenstein .encode_slave_id = false, 14090a9a0188SJack Morgenstein .verify = NULL, /* XXX verify: only demux can do this */ 14100a9a0188SJack Morgenstein .wrapper = NULL 14110a9a0188SJack Morgenstein }, 14120a9a0188SJack Morgenstein { 14130a9a0188SJack Morgenstein .opcode = MLX4_CMD_MAD_IFC, 14140a9a0188SJack Morgenstein .has_inbox = true, 14150a9a0188SJack Morgenstein .has_outbox = true, 14160a9a0188SJack Morgenstein .out_is_imm = false, 14170a9a0188SJack Morgenstein .encode_slave_id = false, 14180a9a0188SJack Morgenstein .verify = NULL, 14190a9a0188SJack Morgenstein .wrapper = mlx4_MAD_IFC_wrapper 14200a9a0188SJack Morgenstein }, 14210a9a0188SJack Morgenstein { 1422114840c3SJack Morgenstein .opcode = MLX4_CMD_MAD_DEMUX, 1423114840c3SJack Morgenstein .has_inbox = false, 1424114840c3SJack Morgenstein .has_outbox = false, 1425114840c3SJack Morgenstein .out_is_imm = false, 1426114840c3SJack Morgenstein .encode_slave_id = false, 1427114840c3SJack Morgenstein .verify = NULL, 1428114840c3SJack Morgenstein .wrapper = mlx4_CMD_EPERM_wrapper 1429114840c3SJack Morgenstein }, 1430114840c3SJack Morgenstein { 1431c82e9aa0SEli Cohen .opcode = MLX4_CMD_QUERY_IF_STAT, 1432c82e9aa0SEli Cohen .has_inbox = false, 1433c82e9aa0SEli Cohen .has_outbox = true, 1434c82e9aa0SEli Cohen .out_is_imm = false, 1435c82e9aa0SEli Cohen .encode_slave_id = false, 1436c82e9aa0SEli Cohen .verify = NULL, 1437c82e9aa0SEli Cohen .wrapper = mlx4_QUERY_IF_STAT_wrapper 1438c82e9aa0SEli Cohen }, 1439adbc7ac5SSaeed Mahameed { 1440adbc7ac5SSaeed Mahameed .opcode = MLX4_CMD_ACCESS_REG, 1441adbc7ac5SSaeed Mahameed .has_inbox = true, 1442adbc7ac5SSaeed Mahameed .has_outbox = true, 1443adbc7ac5SSaeed Mahameed .out_is_imm = false, 1444adbc7ac5SSaeed Mahameed .encode_slave_id = false, 1445adbc7ac5SSaeed Mahameed .verify = NULL, 14466e806699SSaeed Mahameed .wrapper = mlx4_ACCESS_REG_wrapper, 1447adbc7ac5SSaeed Mahameed }, 1448c82e9aa0SEli Cohen /* Native multicast commands are not available for guests */ 1449c82e9aa0SEli Cohen { 1450c82e9aa0SEli Cohen .opcode = MLX4_CMD_QP_ATTACH, 1451c82e9aa0SEli Cohen .has_inbox = true, 1452c82e9aa0SEli Cohen .has_outbox = false, 1453c82e9aa0SEli Cohen .out_is_imm = false, 1454c82e9aa0SEli Cohen .encode_slave_id = false, 1455c82e9aa0SEli Cohen .verify = NULL, 1456c82e9aa0SEli Cohen .wrapper = mlx4_QP_ATTACH_wrapper 1457c82e9aa0SEli Cohen }, 1458c82e9aa0SEli Cohen { 14590ec2c0f8SEugenia Emantayev .opcode = MLX4_CMD_PROMISC, 14600ec2c0f8SEugenia Emantayev .has_inbox = false, 14610ec2c0f8SEugenia Emantayev .has_outbox = false, 14620ec2c0f8SEugenia Emantayev .out_is_imm = false, 14630ec2c0f8SEugenia Emantayev .encode_slave_id = false, 14640ec2c0f8SEugenia Emantayev .verify = NULL, 14650ec2c0f8SEugenia Emantayev .wrapper = mlx4_PROMISC_wrapper 14660ec2c0f8SEugenia Emantayev }, 1467ffe455adSEugenia Emantayev /* Ethernet specific commands */ 1468ffe455adSEugenia Emantayev { 1469ffe455adSEugenia Emantayev .opcode = MLX4_CMD_SET_VLAN_FLTR, 1470ffe455adSEugenia Emantayev .has_inbox = true, 1471ffe455adSEugenia Emantayev .has_outbox = false, 1472ffe455adSEugenia Emantayev .out_is_imm = false, 1473ffe455adSEugenia Emantayev .encode_slave_id = false, 1474ffe455adSEugenia Emantayev .verify = NULL, 1475ffe455adSEugenia Emantayev .wrapper = mlx4_SET_VLAN_FLTR_wrapper 1476ffe455adSEugenia Emantayev }, 1477ffe455adSEugenia Emantayev { 1478ffe455adSEugenia Emantayev .opcode = MLX4_CMD_SET_MCAST_FLTR, 1479ffe455adSEugenia Emantayev .has_inbox = false, 1480ffe455adSEugenia Emantayev .has_outbox = false, 1481ffe455adSEugenia Emantayev .out_is_imm = false, 1482ffe455adSEugenia Emantayev .encode_slave_id = false, 1483ffe455adSEugenia Emantayev .verify = NULL, 1484ffe455adSEugenia Emantayev .wrapper = mlx4_SET_MCAST_FLTR_wrapper 1485ffe455adSEugenia Emantayev }, 1486ffe455adSEugenia Emantayev { 1487ffe455adSEugenia Emantayev .opcode = MLX4_CMD_DUMP_ETH_STATS, 1488ffe455adSEugenia Emantayev .has_inbox = false, 1489ffe455adSEugenia Emantayev .has_outbox = true, 1490ffe455adSEugenia Emantayev .out_is_imm = false, 1491ffe455adSEugenia Emantayev .encode_slave_id = false, 1492ffe455adSEugenia Emantayev .verify = NULL, 1493ffe455adSEugenia Emantayev .wrapper = mlx4_DUMP_ETH_STATS_wrapper 1494ffe455adSEugenia Emantayev }, 14950ec2c0f8SEugenia Emantayev { 1496c82e9aa0SEli Cohen .opcode = MLX4_CMD_INFORM_FLR_DONE, 1497c82e9aa0SEli Cohen .has_inbox = false, 1498c82e9aa0SEli Cohen .has_outbox = false, 1499c82e9aa0SEli Cohen .out_is_imm = false, 1500c82e9aa0SEli Cohen .encode_slave_id = false, 1501c82e9aa0SEli Cohen .verify = NULL, 1502c82e9aa0SEli Cohen .wrapper = NULL 1503c82e9aa0SEli Cohen }, 15048fcfb4dbSHadar Hen Zion /* flow steering commands */ 15058fcfb4dbSHadar Hen Zion { 15068fcfb4dbSHadar Hen Zion .opcode = MLX4_QP_FLOW_STEERING_ATTACH, 15078fcfb4dbSHadar Hen Zion .has_inbox = true, 15088fcfb4dbSHadar Hen Zion .has_outbox = false, 15098fcfb4dbSHadar Hen Zion .out_is_imm = true, 15108fcfb4dbSHadar Hen Zion .encode_slave_id = false, 15118fcfb4dbSHadar Hen Zion .verify = NULL, 15128fcfb4dbSHadar Hen Zion .wrapper = mlx4_QP_FLOW_STEERING_ATTACH_wrapper 15138fcfb4dbSHadar Hen Zion }, 15148fcfb4dbSHadar Hen Zion { 15158fcfb4dbSHadar Hen Zion .opcode = MLX4_QP_FLOW_STEERING_DETACH, 15168fcfb4dbSHadar Hen Zion .has_inbox = false, 15178fcfb4dbSHadar Hen Zion .has_outbox = false, 15188fcfb4dbSHadar Hen Zion .out_is_imm = false, 15198fcfb4dbSHadar Hen Zion .encode_slave_id = false, 15208fcfb4dbSHadar Hen Zion .verify = NULL, 15218fcfb4dbSHadar Hen Zion .wrapper = mlx4_QP_FLOW_STEERING_DETACH_wrapper 15228fcfb4dbSHadar Hen Zion }, 15234de65803SMatan Barak { 15244de65803SMatan Barak .opcode = MLX4_FLOW_STEERING_IB_UC_QP_RANGE, 15254de65803SMatan Barak .has_inbox = false, 15264de65803SMatan Barak .has_outbox = false, 15274de65803SMatan Barak .out_is_imm = false, 15284de65803SMatan Barak .encode_slave_id = false, 15294de65803SMatan Barak .verify = NULL, 1530b7475794SOr Gerlitz .wrapper = mlx4_CMD_EPERM_wrapper 15314de65803SMatan Barak }, 1532e8f081aaSYevgeny Petrilin }; 1533e8f081aaSYevgeny Petrilin 1534e8f081aaSYevgeny Petrilin static int mlx4_master_process_vhcr(struct mlx4_dev *dev, int slave, 1535e8f081aaSYevgeny Petrilin struct mlx4_vhcr_cmd *in_vhcr) 1536e8f081aaSYevgeny Petrilin { 1537e8f081aaSYevgeny Petrilin struct mlx4_priv *priv = mlx4_priv(dev); 1538e8f081aaSYevgeny Petrilin struct mlx4_cmd_info *cmd = NULL; 1539e8f081aaSYevgeny Petrilin struct mlx4_vhcr_cmd *vhcr_cmd = in_vhcr ? in_vhcr : priv->mfunc.vhcr; 1540e8f081aaSYevgeny Petrilin struct mlx4_vhcr *vhcr; 1541e8f081aaSYevgeny Petrilin struct mlx4_cmd_mailbox *inbox = NULL; 1542e8f081aaSYevgeny Petrilin struct mlx4_cmd_mailbox *outbox = NULL; 1543e8f081aaSYevgeny Petrilin u64 in_param; 1544e8f081aaSYevgeny Petrilin u64 out_param; 1545e8f081aaSYevgeny Petrilin int ret = 0; 1546e8f081aaSYevgeny Petrilin int i; 154772be84f1SYevgeny Petrilin int err = 0; 1548e8f081aaSYevgeny Petrilin 1549e8f081aaSYevgeny Petrilin /* Create sw representation of Virtual HCR */ 1550e8f081aaSYevgeny Petrilin vhcr = kzalloc(sizeof(struct mlx4_vhcr), GFP_KERNEL); 1551e8f081aaSYevgeny Petrilin if (!vhcr) 1552e8f081aaSYevgeny Petrilin return -ENOMEM; 1553e8f081aaSYevgeny Petrilin 1554e8f081aaSYevgeny Petrilin /* DMA in the vHCR */ 1555e8f081aaSYevgeny Petrilin if (!in_vhcr) { 1556e8f081aaSYevgeny Petrilin ret = mlx4_ACCESS_MEM(dev, priv->mfunc.vhcr_dma, slave, 1557e8f081aaSYevgeny Petrilin priv->mfunc.master.slave_state[slave].vhcr_dma, 1558e8f081aaSYevgeny Petrilin ALIGN(sizeof(struct mlx4_vhcr_cmd), 1559e8f081aaSYevgeny Petrilin MLX4_ACCESS_MEM_ALIGN), 1); 1560e8f081aaSYevgeny Petrilin if (ret) { 15611a91de28SJoe Perches mlx4_err(dev, "%s: Failed reading vhcr ret: 0x%x\n", 15621a91de28SJoe Perches __func__, ret); 1563e8f081aaSYevgeny Petrilin kfree(vhcr); 1564e8f081aaSYevgeny Petrilin return ret; 1565e8f081aaSYevgeny Petrilin } 1566e8f081aaSYevgeny Petrilin } 1567e8f081aaSYevgeny Petrilin 1568e8f081aaSYevgeny Petrilin /* Fill SW VHCR fields */ 1569e8f081aaSYevgeny Petrilin vhcr->in_param = be64_to_cpu(vhcr_cmd->in_param); 1570e8f081aaSYevgeny Petrilin vhcr->out_param = be64_to_cpu(vhcr_cmd->out_param); 1571e8f081aaSYevgeny Petrilin vhcr->in_modifier = be32_to_cpu(vhcr_cmd->in_modifier); 1572e8f081aaSYevgeny Petrilin vhcr->token = be16_to_cpu(vhcr_cmd->token); 1573e8f081aaSYevgeny Petrilin vhcr->op = be16_to_cpu(vhcr_cmd->opcode) & 0xfff; 1574e8f081aaSYevgeny Petrilin vhcr->op_modifier = (u8) (be16_to_cpu(vhcr_cmd->opcode) >> 12); 1575e8f081aaSYevgeny Petrilin vhcr->e_bit = vhcr_cmd->flags & (1 << 6); 1576e8f081aaSYevgeny Petrilin 1577e8f081aaSYevgeny Petrilin /* Lookup command */ 1578e8f081aaSYevgeny Petrilin for (i = 0; i < ARRAY_SIZE(cmd_info); ++i) { 1579e8f081aaSYevgeny Petrilin if (vhcr->op == cmd_info[i].opcode) { 1580e8f081aaSYevgeny Petrilin cmd = &cmd_info[i]; 1581e8f081aaSYevgeny Petrilin break; 1582e8f081aaSYevgeny Petrilin } 1583e8f081aaSYevgeny Petrilin } 1584e8f081aaSYevgeny Petrilin if (!cmd) { 1585e8f081aaSYevgeny Petrilin mlx4_err(dev, "Unknown command:0x%x accepted from slave:%d\n", 1586e8f081aaSYevgeny Petrilin vhcr->op, slave); 158772be84f1SYevgeny Petrilin vhcr_cmd->status = CMD_STAT_BAD_PARAM; 1588e8f081aaSYevgeny Petrilin goto out_status; 1589e8f081aaSYevgeny Petrilin } 1590e8f081aaSYevgeny Petrilin 1591e8f081aaSYevgeny Petrilin /* Read inbox */ 1592e8f081aaSYevgeny Petrilin if (cmd->has_inbox) { 1593e8f081aaSYevgeny Petrilin vhcr->in_param &= INBOX_MASK; 1594e8f081aaSYevgeny Petrilin inbox = mlx4_alloc_cmd_mailbox(dev); 1595e8f081aaSYevgeny Petrilin if (IS_ERR(inbox)) { 159672be84f1SYevgeny Petrilin vhcr_cmd->status = CMD_STAT_BAD_SIZE; 1597e8f081aaSYevgeny Petrilin inbox = NULL; 159872be84f1SYevgeny Petrilin goto out_status; 1599e8f081aaSYevgeny Petrilin } 1600e8f081aaSYevgeny Petrilin 160172be84f1SYevgeny Petrilin if (mlx4_ACCESS_MEM(dev, inbox->dma, slave, 1602e8f081aaSYevgeny Petrilin vhcr->in_param, 160372be84f1SYevgeny Petrilin MLX4_MAILBOX_SIZE, 1)) { 1604e8f081aaSYevgeny Petrilin mlx4_err(dev, "%s: Failed reading inbox (cmd:0x%x)\n", 1605e8f081aaSYevgeny Petrilin __func__, cmd->opcode); 160672be84f1SYevgeny Petrilin vhcr_cmd->status = CMD_STAT_INTERNAL_ERR; 160772be84f1SYevgeny Petrilin goto out_status; 1608e8f081aaSYevgeny Petrilin } 1609e8f081aaSYevgeny Petrilin } 1610e8f081aaSYevgeny Petrilin 1611e8f081aaSYevgeny Petrilin /* Apply permission and bound checks if applicable */ 1612e8f081aaSYevgeny Petrilin if (cmd->verify && cmd->verify(dev, slave, vhcr, inbox)) { 16131a91de28SJoe Perches mlx4_warn(dev, "Command:0x%x from slave: %d failed protection checks for resource_id:%d\n", 16141a91de28SJoe Perches vhcr->op, slave, vhcr->in_modifier); 161572be84f1SYevgeny Petrilin vhcr_cmd->status = CMD_STAT_BAD_OP; 1616e8f081aaSYevgeny Petrilin goto out_status; 1617e8f081aaSYevgeny Petrilin } 1618e8f081aaSYevgeny Petrilin 1619e8f081aaSYevgeny Petrilin /* Allocate outbox */ 1620e8f081aaSYevgeny Petrilin if (cmd->has_outbox) { 1621e8f081aaSYevgeny Petrilin outbox = mlx4_alloc_cmd_mailbox(dev); 1622e8f081aaSYevgeny Petrilin if (IS_ERR(outbox)) { 162372be84f1SYevgeny Petrilin vhcr_cmd->status = CMD_STAT_BAD_SIZE; 1624e8f081aaSYevgeny Petrilin outbox = NULL; 162572be84f1SYevgeny Petrilin goto out_status; 1626e8f081aaSYevgeny Petrilin } 1627e8f081aaSYevgeny Petrilin } 1628e8f081aaSYevgeny Petrilin 1629e8f081aaSYevgeny Petrilin /* Execute the command! */ 1630e8f081aaSYevgeny Petrilin if (cmd->wrapper) { 163172be84f1SYevgeny Petrilin err = cmd->wrapper(dev, slave, vhcr, inbox, outbox, 1632e8f081aaSYevgeny Petrilin cmd); 1633e8f081aaSYevgeny Petrilin if (cmd->out_is_imm) 1634e8f081aaSYevgeny Petrilin vhcr_cmd->out_param = cpu_to_be64(vhcr->out_param); 1635e8f081aaSYevgeny Petrilin } else { 1636e8f081aaSYevgeny Petrilin in_param = cmd->has_inbox ? (u64) inbox->dma : 1637e8f081aaSYevgeny Petrilin vhcr->in_param; 1638e8f081aaSYevgeny Petrilin out_param = cmd->has_outbox ? (u64) outbox->dma : 1639e8f081aaSYevgeny Petrilin vhcr->out_param; 164072be84f1SYevgeny Petrilin err = __mlx4_cmd(dev, in_param, &out_param, 1641e8f081aaSYevgeny Petrilin cmd->out_is_imm, vhcr->in_modifier, 1642e8f081aaSYevgeny Petrilin vhcr->op_modifier, vhcr->op, 1643e8f081aaSYevgeny Petrilin MLX4_CMD_TIME_CLASS_A, 1644e8f081aaSYevgeny Petrilin MLX4_CMD_NATIVE); 1645e8f081aaSYevgeny Petrilin 1646e8f081aaSYevgeny Petrilin if (cmd->out_is_imm) { 1647e8f081aaSYevgeny Petrilin vhcr->out_param = out_param; 1648e8f081aaSYevgeny Petrilin vhcr_cmd->out_param = cpu_to_be64(vhcr->out_param); 1649e8f081aaSYevgeny Petrilin } 1650e8f081aaSYevgeny Petrilin } 1651e8f081aaSYevgeny Petrilin 165272be84f1SYevgeny Petrilin if (err) { 16531a91de28SJoe Perches mlx4_warn(dev, "vhcr command:0x%x slave:%d failed with error:%d, status %d\n", 165472be84f1SYevgeny Petrilin vhcr->op, slave, vhcr->errno, err); 165572be84f1SYevgeny Petrilin vhcr_cmd->status = mlx4_errno_to_status(err); 165672be84f1SYevgeny Petrilin goto out_status; 165772be84f1SYevgeny Petrilin } 165872be84f1SYevgeny Petrilin 165972be84f1SYevgeny Petrilin 1660e8f081aaSYevgeny Petrilin /* Write outbox if command completed successfully */ 166172be84f1SYevgeny Petrilin if (cmd->has_outbox && !vhcr_cmd->status) { 1662e8f081aaSYevgeny Petrilin ret = mlx4_ACCESS_MEM(dev, outbox->dma, slave, 1663e8f081aaSYevgeny Petrilin vhcr->out_param, 1664e8f081aaSYevgeny Petrilin MLX4_MAILBOX_SIZE, MLX4_CMD_WRAPPED); 1665e8f081aaSYevgeny Petrilin if (ret) { 166672be84f1SYevgeny Petrilin /* If we failed to write back the outbox after the 166772be84f1SYevgeny Petrilin *command was successfully executed, we must fail this 166872be84f1SYevgeny Petrilin * slave, as it is now in undefined state */ 1669e8f081aaSYevgeny Petrilin mlx4_err(dev, "%s:Failed writing outbox\n", __func__); 1670e8f081aaSYevgeny Petrilin goto out; 1671e8f081aaSYevgeny Petrilin } 1672e8f081aaSYevgeny Petrilin } 1673e8f081aaSYevgeny Petrilin 1674e8f081aaSYevgeny Petrilin out_status: 1675e8f081aaSYevgeny Petrilin /* DMA back vhcr result */ 1676e8f081aaSYevgeny Petrilin if (!in_vhcr) { 1677e8f081aaSYevgeny Petrilin ret = mlx4_ACCESS_MEM(dev, priv->mfunc.vhcr_dma, slave, 1678e8f081aaSYevgeny Petrilin priv->mfunc.master.slave_state[slave].vhcr_dma, 1679e8f081aaSYevgeny Petrilin ALIGN(sizeof(struct mlx4_vhcr), 1680e8f081aaSYevgeny Petrilin MLX4_ACCESS_MEM_ALIGN), 1681e8f081aaSYevgeny Petrilin MLX4_CMD_WRAPPED); 1682e8f081aaSYevgeny Petrilin if (ret) 1683e8f081aaSYevgeny Petrilin mlx4_err(dev, "%s:Failed writing vhcr result\n", 1684e8f081aaSYevgeny Petrilin __func__); 1685e8f081aaSYevgeny Petrilin else if (vhcr->e_bit && 1686e8f081aaSYevgeny Petrilin mlx4_GEN_EQE(dev, slave, &priv->mfunc.master.cmd_eqe)) 16871a91de28SJoe Perches mlx4_warn(dev, "Failed to generate command completion eqe for slave %d\n", 16881a91de28SJoe Perches slave); 1689e8f081aaSYevgeny Petrilin } 1690e8f081aaSYevgeny Petrilin 1691e8f081aaSYevgeny Petrilin out: 1692e8f081aaSYevgeny Petrilin kfree(vhcr); 1693e8f081aaSYevgeny Petrilin mlx4_free_cmd_mailbox(dev, inbox); 1694e8f081aaSYevgeny Petrilin mlx4_free_cmd_mailbox(dev, outbox); 1695e8f081aaSYevgeny Petrilin return ret; 1696e8f081aaSYevgeny Petrilin } 1697e8f081aaSYevgeny Petrilin 1698f094668cSJingoo Han static int mlx4_master_immediate_activate_vlan_qos(struct mlx4_priv *priv, 1699b01978caSJack Morgenstein int slave, int port) 1700b01978caSJack Morgenstein { 1701b01978caSJack Morgenstein struct mlx4_vport_oper_state *vp_oper; 1702b01978caSJack Morgenstein struct mlx4_vport_state *vp_admin; 1703b01978caSJack Morgenstein struct mlx4_vf_immed_vlan_work *work; 17040a6eac24SRony Efraim struct mlx4_dev *dev = &(priv->dev); 1705b01978caSJack Morgenstein int err; 1706b01978caSJack Morgenstein int admin_vlan_ix = NO_INDX; 1707b01978caSJack Morgenstein 1708b01978caSJack Morgenstein vp_oper = &priv->mfunc.master.vf_oper[slave].vport[port]; 1709b01978caSJack Morgenstein vp_admin = &priv->mfunc.master.vf_admin[slave].vport[port]; 1710b01978caSJack Morgenstein 1711b01978caSJack Morgenstein if (vp_oper->state.default_vlan == vp_admin->default_vlan && 17120a6eac24SRony Efraim vp_oper->state.default_qos == vp_admin->default_qos && 17130a6eac24SRony Efraim vp_oper->state.link_state == vp_admin->link_state) 1714b01978caSJack Morgenstein return 0; 1715b01978caSJack Morgenstein 17160a6eac24SRony Efraim if (!(priv->mfunc.master.slave_state[slave].active && 1717f0f829bfSRony Efraim dev->caps.flags2 & MLX4_DEV_CAP_FLAG2_UPDATE_QP)) { 17180a6eac24SRony Efraim /* even if the UPDATE_QP command isn't supported, we still want 17190a6eac24SRony Efraim * to set this VF link according to the admin directive 17200a6eac24SRony Efraim */ 17210a6eac24SRony Efraim vp_oper->state.link_state = vp_admin->link_state; 17220a6eac24SRony Efraim return -1; 17230a6eac24SRony Efraim } 17240a6eac24SRony Efraim 17250a6eac24SRony Efraim mlx4_dbg(dev, "updating immediately admin params slave %d port %d\n", 17260a6eac24SRony Efraim slave, port); 17271a91de28SJoe Perches mlx4_dbg(dev, "vlan %d QoS %d link down %d\n", 17281a91de28SJoe Perches vp_admin->default_vlan, vp_admin->default_qos, 17291a91de28SJoe Perches vp_admin->link_state); 17300a6eac24SRony Efraim 1731b01978caSJack Morgenstein work = kzalloc(sizeof(*work), GFP_KERNEL); 1732b01978caSJack Morgenstein if (!work) 1733b01978caSJack Morgenstein return -ENOMEM; 1734b01978caSJack Morgenstein 1735b01978caSJack Morgenstein if (vp_oper->state.default_vlan != vp_admin->default_vlan) { 1736f0f829bfSRony Efraim if (MLX4_VGT != vp_admin->default_vlan) { 1737b01978caSJack Morgenstein err = __mlx4_register_vlan(&priv->dev, port, 1738b01978caSJack Morgenstein vp_admin->default_vlan, 1739b01978caSJack Morgenstein &admin_vlan_ix); 1740b01978caSJack Morgenstein if (err) { 17419caf83c3SDan Carpenter kfree(work); 17421a91de28SJoe Perches mlx4_warn(&priv->dev, 1743b01978caSJack Morgenstein "No vlan resources slave %d, port %d\n", 1744b01978caSJack Morgenstein slave, port); 1745b01978caSJack Morgenstein return err; 1746b01978caSJack Morgenstein } 1747f0f829bfSRony Efraim } else { 1748f0f829bfSRony Efraim admin_vlan_ix = NO_INDX; 1749f0f829bfSRony Efraim } 1750b01978caSJack Morgenstein work->flags |= MLX4_VF_IMMED_VLAN_FLAG_VLAN; 17511a91de28SJoe Perches mlx4_dbg(&priv->dev, 1752b01978caSJack Morgenstein "alloc vlan %d idx %d slave %d port %d\n", 1753b01978caSJack Morgenstein (int)(vp_admin->default_vlan), 1754b01978caSJack Morgenstein admin_vlan_ix, slave, port); 1755b01978caSJack Morgenstein } 1756b01978caSJack Morgenstein 1757b01978caSJack Morgenstein /* save original vlan ix and vlan id */ 1758b01978caSJack Morgenstein work->orig_vlan_id = vp_oper->state.default_vlan; 1759b01978caSJack Morgenstein work->orig_vlan_ix = vp_oper->vlan_idx; 1760b01978caSJack Morgenstein 1761b01978caSJack Morgenstein /* handle new qos */ 1762b01978caSJack Morgenstein if (vp_oper->state.default_qos != vp_admin->default_qos) 1763b01978caSJack Morgenstein work->flags |= MLX4_VF_IMMED_VLAN_FLAG_QOS; 1764b01978caSJack Morgenstein 1765b01978caSJack Morgenstein if (work->flags & MLX4_VF_IMMED_VLAN_FLAG_VLAN) 1766b01978caSJack Morgenstein vp_oper->vlan_idx = admin_vlan_ix; 1767b01978caSJack Morgenstein 1768b01978caSJack Morgenstein vp_oper->state.default_vlan = vp_admin->default_vlan; 1769b01978caSJack Morgenstein vp_oper->state.default_qos = vp_admin->default_qos; 17700a6eac24SRony Efraim vp_oper->state.link_state = vp_admin->link_state; 17710a6eac24SRony Efraim 17720a6eac24SRony Efraim if (vp_admin->link_state == IFLA_VF_LINK_STATE_DISABLE) 17730a6eac24SRony Efraim work->flags |= MLX4_VF_IMMED_VLAN_FLAG_LINK_DISABLE; 1774b01978caSJack Morgenstein 1775b01978caSJack Morgenstein /* iterate over QPs owned by this slave, using UPDATE_QP */ 1776b01978caSJack Morgenstein work->port = port; 1777b01978caSJack Morgenstein work->slave = slave; 1778b01978caSJack Morgenstein work->qos = vp_oper->state.default_qos; 1779b01978caSJack Morgenstein work->vlan_id = vp_oper->state.default_vlan; 1780b01978caSJack Morgenstein work->vlan_ix = vp_oper->vlan_idx; 1781b01978caSJack Morgenstein work->priv = priv; 1782b01978caSJack Morgenstein INIT_WORK(&work->work, mlx4_vf_immed_vlan_work_handler); 1783b01978caSJack Morgenstein queue_work(priv->mfunc.master.comm_wq, &work->work); 1784b01978caSJack Morgenstein 1785b01978caSJack Morgenstein return 0; 1786b01978caSJack Morgenstein } 1787b01978caSJack Morgenstein 1788b01978caSJack Morgenstein 17890eb62b93SRony Efraim static int mlx4_master_activate_admin_state(struct mlx4_priv *priv, int slave) 17900eb62b93SRony Efraim { 17913f7fb021SRony Efraim int port, err; 17923f7fb021SRony Efraim struct mlx4_vport_state *vp_admin; 17933f7fb021SRony Efraim struct mlx4_vport_oper_state *vp_oper; 1794449fc488SMatan Barak struct mlx4_active_ports actv_ports = mlx4_get_active_ports( 1795449fc488SMatan Barak &priv->dev, slave); 1796449fc488SMatan Barak int min_port = find_first_bit(actv_ports.ports, 1797449fc488SMatan Barak priv->dev.caps.num_ports) + 1; 1798449fc488SMatan Barak int max_port = min_port - 1 + 1799449fc488SMatan Barak bitmap_weight(actv_ports.ports, priv->dev.caps.num_ports); 18003f7fb021SRony Efraim 1801449fc488SMatan Barak for (port = min_port; port <= max_port; port++) { 1802449fc488SMatan Barak if (!test_bit(port - 1, actv_ports.ports)) 1803449fc488SMatan Barak continue; 180499ec41d0SJack Morgenstein priv->mfunc.master.vf_oper[slave].smi_enabled[port] = 180599ec41d0SJack Morgenstein priv->mfunc.master.vf_admin[slave].enable_smi[port]; 18063f7fb021SRony Efraim vp_oper = &priv->mfunc.master.vf_oper[slave].vport[port]; 18073f7fb021SRony Efraim vp_admin = &priv->mfunc.master.vf_admin[slave].vport[port]; 18083f7fb021SRony Efraim vp_oper->state = *vp_admin; 18093f7fb021SRony Efraim if (MLX4_VGT != vp_admin->default_vlan) { 18103f7fb021SRony Efraim err = __mlx4_register_vlan(&priv->dev, port, 18113f7fb021SRony Efraim vp_admin->default_vlan, &(vp_oper->vlan_idx)); 18123f7fb021SRony Efraim if (err) { 18133f7fb021SRony Efraim vp_oper->vlan_idx = NO_INDX; 18141a91de28SJoe Perches mlx4_warn(&priv->dev, 18151a84db56SMasanari Iida "No vlan resources slave %d, port %d\n", 18163f7fb021SRony Efraim slave, port); 18173f7fb021SRony Efraim return err; 18183f7fb021SRony Efraim } 18191a91de28SJoe Perches mlx4_dbg(&priv->dev, "alloc vlan %d idx %d slave %d port %d\n", 18203f7fb021SRony Efraim (int)(vp_oper->state.default_vlan), 18213f7fb021SRony Efraim vp_oper->vlan_idx, slave, port); 18223f7fb021SRony Efraim } 1823e6b6a231SRony Efraim if (vp_admin->spoofchk) { 1824e6b6a231SRony Efraim vp_oper->mac_idx = __mlx4_register_mac(&priv->dev, 1825e6b6a231SRony Efraim port, 1826e6b6a231SRony Efraim vp_admin->mac); 1827e6b6a231SRony Efraim if (0 > vp_oper->mac_idx) { 1828e6b6a231SRony Efraim err = vp_oper->mac_idx; 1829e6b6a231SRony Efraim vp_oper->mac_idx = NO_INDX; 18301a91de28SJoe Perches mlx4_warn(&priv->dev, 18311a84db56SMasanari Iida "No mac resources slave %d, port %d\n", 1832e6b6a231SRony Efraim slave, port); 1833e6b6a231SRony Efraim return err; 1834e6b6a231SRony Efraim } 18351a91de28SJoe Perches mlx4_dbg(&priv->dev, "alloc mac %llx idx %d slave %d port %d\n", 1836e6b6a231SRony Efraim vp_oper->state.mac, vp_oper->mac_idx, slave, port); 1837e6b6a231SRony Efraim } 18380eb62b93SRony Efraim } 18390eb62b93SRony Efraim return 0; 18400eb62b93SRony Efraim } 18410eb62b93SRony Efraim 18423f7fb021SRony Efraim static void mlx4_master_deactivate_admin_state(struct mlx4_priv *priv, int slave) 18433f7fb021SRony Efraim { 18443f7fb021SRony Efraim int port; 18453f7fb021SRony Efraim struct mlx4_vport_oper_state *vp_oper; 1846449fc488SMatan Barak struct mlx4_active_ports actv_ports = mlx4_get_active_ports( 1847449fc488SMatan Barak &priv->dev, slave); 1848449fc488SMatan Barak int min_port = find_first_bit(actv_ports.ports, 1849449fc488SMatan Barak priv->dev.caps.num_ports) + 1; 1850449fc488SMatan Barak int max_port = min_port - 1 + 1851449fc488SMatan Barak bitmap_weight(actv_ports.ports, priv->dev.caps.num_ports); 18523f7fb021SRony Efraim 1853449fc488SMatan Barak 1854449fc488SMatan Barak for (port = min_port; port <= max_port; port++) { 1855449fc488SMatan Barak if (!test_bit(port - 1, actv_ports.ports)) 1856449fc488SMatan Barak continue; 185799ec41d0SJack Morgenstein priv->mfunc.master.vf_oper[slave].smi_enabled[port] = 185899ec41d0SJack Morgenstein MLX4_VF_SMI_DISABLED; 18593f7fb021SRony Efraim vp_oper = &priv->mfunc.master.vf_oper[slave].vport[port]; 18603f7fb021SRony Efraim if (NO_INDX != vp_oper->vlan_idx) { 18613f7fb021SRony Efraim __mlx4_unregister_vlan(&priv->dev, 18622009d005SJack Morgenstein port, vp_oper->state.default_vlan); 18633f7fb021SRony Efraim vp_oper->vlan_idx = NO_INDX; 18643f7fb021SRony Efraim } 1865e6b6a231SRony Efraim if (NO_INDX != vp_oper->mac_idx) { 1866c32b7dfbSJack Morgenstein __mlx4_unregister_mac(&priv->dev, port, vp_oper->state.mac); 1867e6b6a231SRony Efraim vp_oper->mac_idx = NO_INDX; 1868e6b6a231SRony Efraim } 18693f7fb021SRony Efraim } 18703f7fb021SRony Efraim return; 18713f7fb021SRony Efraim } 18723f7fb021SRony Efraim 1873e8f081aaSYevgeny Petrilin static void mlx4_master_do_cmd(struct mlx4_dev *dev, int slave, u8 cmd, 1874e8f081aaSYevgeny Petrilin u16 param, u8 toggle) 1875e8f081aaSYevgeny Petrilin { 1876e8f081aaSYevgeny Petrilin struct mlx4_priv *priv = mlx4_priv(dev); 1877e8f081aaSYevgeny Petrilin struct mlx4_slave_state *slave_state = priv->mfunc.master.slave_state; 1878e8f081aaSYevgeny Petrilin u32 reply; 1879e8f081aaSYevgeny Petrilin u8 is_going_down = 0; 1880803143fbSMarcel Apfelbaum int i; 1881311f813aSJack Morgenstein unsigned long flags; 1882e8f081aaSYevgeny Petrilin 1883e8f081aaSYevgeny Petrilin slave_state[slave].comm_toggle ^= 1; 1884e8f081aaSYevgeny Petrilin reply = (u32) slave_state[slave].comm_toggle << 31; 1885e8f081aaSYevgeny Petrilin if (toggle != slave_state[slave].comm_toggle) { 18861a91de28SJoe Perches mlx4_warn(dev, "Incorrect toggle %d from slave %d. *** MASTER STATE COMPROMISED ***\n", 18871a91de28SJoe Perches toggle, slave); 1888e8f081aaSYevgeny Petrilin goto reset_slave; 1889e8f081aaSYevgeny Petrilin } 1890e8f081aaSYevgeny Petrilin if (cmd == MLX4_COMM_CMD_RESET) { 1891e8f081aaSYevgeny Petrilin mlx4_warn(dev, "Received reset from slave:%d\n", slave); 1892e8f081aaSYevgeny Petrilin slave_state[slave].active = false; 18932c957ff2SJack Morgenstein slave_state[slave].old_vlan_api = false; 18943f7fb021SRony Efraim mlx4_master_deactivate_admin_state(priv, slave); 1895803143fbSMarcel Apfelbaum for (i = 0; i < MLX4_EVENT_TYPES_NUM; ++i) { 1896803143fbSMarcel Apfelbaum slave_state[slave].event_eq[i].eqn = -1; 1897803143fbSMarcel Apfelbaum slave_state[slave].event_eq[i].token = 0; 1898803143fbSMarcel Apfelbaum } 1899e8f081aaSYevgeny Petrilin /*check if we are in the middle of FLR process, 1900e8f081aaSYevgeny Petrilin if so return "retry" status to the slave*/ 1901162344edSOr Gerlitz if (MLX4_COMM_CMD_FLR == slave_state[slave].last_cmd) 1902e8f081aaSYevgeny Petrilin goto inform_slave_state; 1903e8f081aaSYevgeny Petrilin 1904fc06573dSJack Morgenstein mlx4_dispatch_event(dev, MLX4_DEV_EVENT_SLAVE_SHUTDOWN, slave); 1905fc06573dSJack Morgenstein 1906e8f081aaSYevgeny Petrilin /* write the version in the event field */ 1907e8f081aaSYevgeny Petrilin reply |= mlx4_comm_get_version(); 1908e8f081aaSYevgeny Petrilin 1909e8f081aaSYevgeny Petrilin goto reset_slave; 1910e8f081aaSYevgeny Petrilin } 1911e8f081aaSYevgeny Petrilin /*command from slave in the middle of FLR*/ 1912e8f081aaSYevgeny Petrilin if (cmd != MLX4_COMM_CMD_RESET && 1913e8f081aaSYevgeny Petrilin MLX4_COMM_CMD_FLR == slave_state[slave].last_cmd) { 19141a91de28SJoe Perches mlx4_warn(dev, "slave:%d is Trying to run cmd(0x%x) in the middle of FLR\n", 19151a91de28SJoe Perches slave, cmd); 1916e8f081aaSYevgeny Petrilin return; 1917e8f081aaSYevgeny Petrilin } 1918e8f081aaSYevgeny Petrilin 1919e8f081aaSYevgeny Petrilin switch (cmd) { 1920e8f081aaSYevgeny Petrilin case MLX4_COMM_CMD_VHCR0: 1921e8f081aaSYevgeny Petrilin if (slave_state[slave].last_cmd != MLX4_COMM_CMD_RESET) 1922e8f081aaSYevgeny Petrilin goto reset_slave; 1923e8f081aaSYevgeny Petrilin slave_state[slave].vhcr_dma = ((u64) param) << 48; 1924e8f081aaSYevgeny Petrilin priv->mfunc.master.slave_state[slave].cookie = 0; 1925e8f081aaSYevgeny Petrilin mutex_init(&priv->mfunc.master.gen_eqe_mutex[slave]); 1926e8f081aaSYevgeny Petrilin break; 1927e8f081aaSYevgeny Petrilin case MLX4_COMM_CMD_VHCR1: 1928e8f081aaSYevgeny Petrilin if (slave_state[slave].last_cmd != MLX4_COMM_CMD_VHCR0) 1929e8f081aaSYevgeny Petrilin goto reset_slave; 1930e8f081aaSYevgeny Petrilin slave_state[slave].vhcr_dma |= ((u64) param) << 32; 1931e8f081aaSYevgeny Petrilin break; 1932e8f081aaSYevgeny Petrilin case MLX4_COMM_CMD_VHCR2: 1933e8f081aaSYevgeny Petrilin if (slave_state[slave].last_cmd != MLX4_COMM_CMD_VHCR1) 1934e8f081aaSYevgeny Petrilin goto reset_slave; 1935e8f081aaSYevgeny Petrilin slave_state[slave].vhcr_dma |= ((u64) param) << 16; 1936e8f081aaSYevgeny Petrilin break; 1937e8f081aaSYevgeny Petrilin case MLX4_COMM_CMD_VHCR_EN: 1938e8f081aaSYevgeny Petrilin if (slave_state[slave].last_cmd != MLX4_COMM_CMD_VHCR2) 1939e8f081aaSYevgeny Petrilin goto reset_slave; 1940e8f081aaSYevgeny Petrilin slave_state[slave].vhcr_dma |= param; 19413f7fb021SRony Efraim if (mlx4_master_activate_admin_state(priv, slave)) 19423f7fb021SRony Efraim goto reset_slave; 1943e8f081aaSYevgeny Petrilin slave_state[slave].active = true; 1944fc06573dSJack Morgenstein mlx4_dispatch_event(dev, MLX4_DEV_EVENT_SLAVE_INIT, slave); 1945e8f081aaSYevgeny Petrilin break; 1946e8f081aaSYevgeny Petrilin case MLX4_COMM_CMD_VHCR_POST: 1947e8f081aaSYevgeny Petrilin if ((slave_state[slave].last_cmd != MLX4_COMM_CMD_VHCR_EN) && 1948e8f081aaSYevgeny Petrilin (slave_state[slave].last_cmd != MLX4_COMM_CMD_VHCR_POST)) 1949e8f081aaSYevgeny Petrilin goto reset_slave; 1950f3d4c89eSRoland Dreier 1951f3d4c89eSRoland Dreier mutex_lock(&priv->cmd.slave_cmd_mutex); 1952e8f081aaSYevgeny Petrilin if (mlx4_master_process_vhcr(dev, slave, NULL)) { 19531a91de28SJoe Perches mlx4_err(dev, "Failed processing vhcr for slave:%d, resetting slave\n", 19541a91de28SJoe Perches slave); 1955f3d4c89eSRoland Dreier mutex_unlock(&priv->cmd.slave_cmd_mutex); 1956e8f081aaSYevgeny Petrilin goto reset_slave; 1957e8f081aaSYevgeny Petrilin } 1958f3d4c89eSRoland Dreier mutex_unlock(&priv->cmd.slave_cmd_mutex); 1959e8f081aaSYevgeny Petrilin break; 1960e8f081aaSYevgeny Petrilin default: 1961e8f081aaSYevgeny Petrilin mlx4_warn(dev, "Bad comm cmd:%d from slave:%d\n", cmd, slave); 1962e8f081aaSYevgeny Petrilin goto reset_slave; 1963e8f081aaSYevgeny Petrilin } 1964311f813aSJack Morgenstein spin_lock_irqsave(&priv->mfunc.master.slave_state_lock, flags); 1965e8f081aaSYevgeny Petrilin if (!slave_state[slave].is_slave_going_down) 1966e8f081aaSYevgeny Petrilin slave_state[slave].last_cmd = cmd; 1967e8f081aaSYevgeny Petrilin else 1968e8f081aaSYevgeny Petrilin is_going_down = 1; 1969311f813aSJack Morgenstein spin_unlock_irqrestore(&priv->mfunc.master.slave_state_lock, flags); 1970e8f081aaSYevgeny Petrilin if (is_going_down) { 19711a91de28SJoe Perches mlx4_warn(dev, "Slave is going down aborting command(%d) executing from slave:%d\n", 1972e8f081aaSYevgeny Petrilin cmd, slave); 1973e8f081aaSYevgeny Petrilin return; 1974e8f081aaSYevgeny Petrilin } 1975e8f081aaSYevgeny Petrilin __raw_writel((__force u32) cpu_to_be32(reply), 1976e8f081aaSYevgeny Petrilin &priv->mfunc.comm[slave].slave_read); 1977e8f081aaSYevgeny Petrilin mmiowb(); 1978e8f081aaSYevgeny Petrilin 1979e8f081aaSYevgeny Petrilin return; 1980e8f081aaSYevgeny Petrilin 1981e8f081aaSYevgeny Petrilin reset_slave: 1982c82e9aa0SEli Cohen /* cleanup any slave resources */ 1983c82e9aa0SEli Cohen mlx4_delete_all_resources_for_slave(dev, slave); 1984311f813aSJack Morgenstein spin_lock_irqsave(&priv->mfunc.master.slave_state_lock, flags); 1985e8f081aaSYevgeny Petrilin if (!slave_state[slave].is_slave_going_down) 1986e8f081aaSYevgeny Petrilin slave_state[slave].last_cmd = MLX4_COMM_CMD_RESET; 1987311f813aSJack Morgenstein spin_unlock_irqrestore(&priv->mfunc.master.slave_state_lock, flags); 1988e8f081aaSYevgeny Petrilin /*with slave in the middle of flr, no need to clean resources again.*/ 1989e8f081aaSYevgeny Petrilin inform_slave_state: 1990e8f081aaSYevgeny Petrilin memset(&slave_state[slave].event_eq, 0, 1991e8f081aaSYevgeny Petrilin sizeof(struct mlx4_slave_event_eq_info)); 1992e8f081aaSYevgeny Petrilin __raw_writel((__force u32) cpu_to_be32(reply), 1993e8f081aaSYevgeny Petrilin &priv->mfunc.comm[slave].slave_read); 1994e8f081aaSYevgeny Petrilin wmb(); 1995e8f081aaSYevgeny Petrilin } 1996e8f081aaSYevgeny Petrilin 1997e8f081aaSYevgeny Petrilin /* master command processing */ 1998e8f081aaSYevgeny Petrilin void mlx4_master_comm_channel(struct work_struct *work) 1999e8f081aaSYevgeny Petrilin { 2000e8f081aaSYevgeny Petrilin struct mlx4_mfunc_master_ctx *master = 2001e8f081aaSYevgeny Petrilin container_of(work, 2002e8f081aaSYevgeny Petrilin struct mlx4_mfunc_master_ctx, 2003e8f081aaSYevgeny Petrilin comm_work); 2004e8f081aaSYevgeny Petrilin struct mlx4_mfunc *mfunc = 2005e8f081aaSYevgeny Petrilin container_of(master, struct mlx4_mfunc, master); 2006e8f081aaSYevgeny Petrilin struct mlx4_priv *priv = 2007e8f081aaSYevgeny Petrilin container_of(mfunc, struct mlx4_priv, mfunc); 2008e8f081aaSYevgeny Petrilin struct mlx4_dev *dev = &priv->dev; 2009e8f081aaSYevgeny Petrilin __be32 *bit_vec; 2010e8f081aaSYevgeny Petrilin u32 comm_cmd; 2011e8f081aaSYevgeny Petrilin u32 vec; 2012e8f081aaSYevgeny Petrilin int i, j, slave; 2013e8f081aaSYevgeny Petrilin int toggle; 2014e8f081aaSYevgeny Petrilin int served = 0; 2015e8f081aaSYevgeny Petrilin int reported = 0; 2016e8f081aaSYevgeny Petrilin u32 slt; 2017e8f081aaSYevgeny Petrilin 2018e8f081aaSYevgeny Petrilin bit_vec = master->comm_arm_bit_vector; 2019e8f081aaSYevgeny Petrilin for (i = 0; i < COMM_CHANNEL_BIT_ARRAY_SIZE; i++) { 2020e8f081aaSYevgeny Petrilin vec = be32_to_cpu(bit_vec[i]); 2021e8f081aaSYevgeny Petrilin for (j = 0; j < 32; j++) { 2022e8f081aaSYevgeny Petrilin if (!(vec & (1 << j))) 2023e8f081aaSYevgeny Petrilin continue; 2024e8f081aaSYevgeny Petrilin ++reported; 2025e8f081aaSYevgeny Petrilin slave = (i * 32) + j; 2026e8f081aaSYevgeny Petrilin comm_cmd = swab32(readl( 2027e8f081aaSYevgeny Petrilin &mfunc->comm[slave].slave_write)); 2028e8f081aaSYevgeny Petrilin slt = swab32(readl(&mfunc->comm[slave].slave_read)) 2029e8f081aaSYevgeny Petrilin >> 31; 2030e8f081aaSYevgeny Petrilin toggle = comm_cmd >> 31; 2031e8f081aaSYevgeny Petrilin if (toggle != slt) { 2032e8f081aaSYevgeny Petrilin if (master->slave_state[slave].comm_toggle 2033e8f081aaSYevgeny Petrilin != slt) { 2034c20862c8SAmir Vadai pr_info("slave %d out of sync. read toggle %d, state toggle %d. Resynching.\n", 20351a91de28SJoe Perches slave, slt, 2036e8f081aaSYevgeny Petrilin master->slave_state[slave].comm_toggle); 2037e8f081aaSYevgeny Petrilin master->slave_state[slave].comm_toggle = 2038e8f081aaSYevgeny Petrilin slt; 2039e8f081aaSYevgeny Petrilin } 2040e8f081aaSYevgeny Petrilin mlx4_master_do_cmd(dev, slave, 2041e8f081aaSYevgeny Petrilin comm_cmd >> 16 & 0xff, 2042e8f081aaSYevgeny Petrilin comm_cmd & 0xffff, toggle); 2043e8f081aaSYevgeny Petrilin ++served; 2044e8f081aaSYevgeny Petrilin } 2045e8f081aaSYevgeny Petrilin } 2046e8f081aaSYevgeny Petrilin } 2047e8f081aaSYevgeny Petrilin 2048e8f081aaSYevgeny Petrilin if (reported && reported != served) 20491a91de28SJoe Perches mlx4_warn(dev, "Got command event with bitmask from %d slaves but %d were served\n", 2050e8f081aaSYevgeny Petrilin reported, served); 2051e8f081aaSYevgeny Petrilin 2052e8f081aaSYevgeny Petrilin if (mlx4_ARM_COMM_CHANNEL(dev)) 2053e8f081aaSYevgeny Petrilin mlx4_warn(dev, "Failed to arm comm channel events\n"); 2054e8f081aaSYevgeny Petrilin } 2055e8f081aaSYevgeny Petrilin 2056ab9c17a0SJack Morgenstein static int sync_toggles(struct mlx4_dev *dev) 2057ab9c17a0SJack Morgenstein { 2058ab9c17a0SJack Morgenstein struct mlx4_priv *priv = mlx4_priv(dev); 2059ab9c17a0SJack Morgenstein int wr_toggle; 2060ab9c17a0SJack Morgenstein int rd_toggle; 2061ab9c17a0SJack Morgenstein unsigned long end; 2062ab9c17a0SJack Morgenstein 2063ab9c17a0SJack Morgenstein wr_toggle = swab32(readl(&priv->mfunc.comm->slave_write)) >> 31; 2064ab9c17a0SJack Morgenstein end = jiffies + msecs_to_jiffies(5000); 2065ab9c17a0SJack Morgenstein 2066ab9c17a0SJack Morgenstein while (time_before(jiffies, end)) { 2067ab9c17a0SJack Morgenstein rd_toggle = swab32(readl(&priv->mfunc.comm->slave_read)) >> 31; 2068ab9c17a0SJack Morgenstein if (rd_toggle == wr_toggle) { 2069ab9c17a0SJack Morgenstein priv->cmd.comm_toggle = rd_toggle; 2070ab9c17a0SJack Morgenstein return 0; 2071ab9c17a0SJack Morgenstein } 2072ab9c17a0SJack Morgenstein 2073ab9c17a0SJack Morgenstein cond_resched(); 2074ab9c17a0SJack Morgenstein } 2075ab9c17a0SJack Morgenstein 2076ab9c17a0SJack Morgenstein /* 2077ab9c17a0SJack Morgenstein * we could reach here if for example the previous VM using this 2078ab9c17a0SJack Morgenstein * function misbehaved and left the channel with unsynced state. We 2079ab9c17a0SJack Morgenstein * should fix this here and give this VM a chance to use a properly 2080ab9c17a0SJack Morgenstein * synced channel 2081ab9c17a0SJack Morgenstein */ 2082ab9c17a0SJack Morgenstein mlx4_warn(dev, "recovering from previously mis-behaved VM\n"); 2083ab9c17a0SJack Morgenstein __raw_writel((__force u32) 0, &priv->mfunc.comm->slave_read); 2084ab9c17a0SJack Morgenstein __raw_writel((__force u32) 0, &priv->mfunc.comm->slave_write); 2085ab9c17a0SJack Morgenstein priv->cmd.comm_toggle = 0; 2086ab9c17a0SJack Morgenstein 2087ab9c17a0SJack Morgenstein return 0; 2088ab9c17a0SJack Morgenstein } 2089ab9c17a0SJack Morgenstein 2090ab9c17a0SJack Morgenstein int mlx4_multi_func_init(struct mlx4_dev *dev) 2091ab9c17a0SJack Morgenstein { 2092ab9c17a0SJack Morgenstein struct mlx4_priv *priv = mlx4_priv(dev); 2093ab9c17a0SJack Morgenstein struct mlx4_slave_state *s_state; 2094803143fbSMarcel Apfelbaum int i, j, err, port; 2095ab9c17a0SJack Morgenstein 2096ab9c17a0SJack Morgenstein if (mlx4_is_master(dev)) 2097ab9c17a0SJack Morgenstein priv->mfunc.comm = 2098872bf2fbSYishai Hadas ioremap(pci_resource_start(dev->persist->pdev, 2099872bf2fbSYishai Hadas priv->fw.comm_bar) + 2100ab9c17a0SJack Morgenstein priv->fw.comm_base, MLX4_COMM_PAGESIZE); 2101ab9c17a0SJack Morgenstein else 2102ab9c17a0SJack Morgenstein priv->mfunc.comm = 2103872bf2fbSYishai Hadas ioremap(pci_resource_start(dev->persist->pdev, 2) + 2104ab9c17a0SJack Morgenstein MLX4_SLAVE_COMM_BASE, MLX4_COMM_PAGESIZE); 2105ab9c17a0SJack Morgenstein if (!priv->mfunc.comm) { 21061a91de28SJoe Perches mlx4_err(dev, "Couldn't map communication vector\n"); 2107ab9c17a0SJack Morgenstein goto err_vhcr; 2108ab9c17a0SJack Morgenstein } 2109ab9c17a0SJack Morgenstein 2110ab9c17a0SJack Morgenstein if (mlx4_is_master(dev)) { 2111ab9c17a0SJack Morgenstein priv->mfunc.master.slave_state = 2112ab9c17a0SJack Morgenstein kzalloc(dev->num_slaves * 2113ab9c17a0SJack Morgenstein sizeof(struct mlx4_slave_state), GFP_KERNEL); 2114ab9c17a0SJack Morgenstein if (!priv->mfunc.master.slave_state) 2115ab9c17a0SJack Morgenstein goto err_comm; 2116ab9c17a0SJack Morgenstein 21170eb62b93SRony Efraim priv->mfunc.master.vf_admin = 21180eb62b93SRony Efraim kzalloc(dev->num_slaves * 21190eb62b93SRony Efraim sizeof(struct mlx4_vf_admin_state), GFP_KERNEL); 21200eb62b93SRony Efraim if (!priv->mfunc.master.vf_admin) 21210eb62b93SRony Efraim goto err_comm_admin; 21220eb62b93SRony Efraim 21230eb62b93SRony Efraim priv->mfunc.master.vf_oper = 21240eb62b93SRony Efraim kzalloc(dev->num_slaves * 21250eb62b93SRony Efraim sizeof(struct mlx4_vf_oper_state), GFP_KERNEL); 21260eb62b93SRony Efraim if (!priv->mfunc.master.vf_oper) 21270eb62b93SRony Efraim goto err_comm_oper; 21280eb62b93SRony Efraim 2129ab9c17a0SJack Morgenstein for (i = 0; i < dev->num_slaves; ++i) { 2130ab9c17a0SJack Morgenstein s_state = &priv->mfunc.master.slave_state[i]; 2131ab9c17a0SJack Morgenstein s_state->last_cmd = MLX4_COMM_CMD_RESET; 2132803143fbSMarcel Apfelbaum for (j = 0; j < MLX4_EVENT_TYPES_NUM; ++j) 2133803143fbSMarcel Apfelbaum s_state->event_eq[j].eqn = -1; 2134ab9c17a0SJack Morgenstein __raw_writel((__force u32) 0, 2135ab9c17a0SJack Morgenstein &priv->mfunc.comm[i].slave_write); 2136ab9c17a0SJack Morgenstein __raw_writel((__force u32) 0, 2137ab9c17a0SJack Morgenstein &priv->mfunc.comm[i].slave_read); 2138ab9c17a0SJack Morgenstein mmiowb(); 2139ab9c17a0SJack Morgenstein for (port = 1; port <= MLX4_MAX_PORTS; port++) { 2140ab9c17a0SJack Morgenstein s_state->vlan_filter[port] = 2141ab9c17a0SJack Morgenstein kzalloc(sizeof(struct mlx4_vlan_fltr), 2142ab9c17a0SJack Morgenstein GFP_KERNEL); 2143ab9c17a0SJack Morgenstein if (!s_state->vlan_filter[port]) { 2144ab9c17a0SJack Morgenstein if (--port) 2145ab9c17a0SJack Morgenstein kfree(s_state->vlan_filter[port]); 2146ab9c17a0SJack Morgenstein goto err_slaves; 2147ab9c17a0SJack Morgenstein } 2148ab9c17a0SJack Morgenstein INIT_LIST_HEAD(&s_state->mcast_filters[port]); 21490eb62b93SRony Efraim priv->mfunc.master.vf_admin[i].vport[port].default_vlan = MLX4_VGT; 21503f7fb021SRony Efraim priv->mfunc.master.vf_oper[i].vport[port].state.default_vlan = MLX4_VGT; 21510eb62b93SRony Efraim priv->mfunc.master.vf_oper[i].vport[port].vlan_idx = NO_INDX; 21520eb62b93SRony Efraim priv->mfunc.master.vf_oper[i].vport[port].mac_idx = NO_INDX; 2153ab9c17a0SJack Morgenstein } 2154ab9c17a0SJack Morgenstein spin_lock_init(&s_state->lock); 2155ab9c17a0SJack Morgenstein } 2156ab9c17a0SJack Morgenstein 215708ff3235SOr Gerlitz memset(&priv->mfunc.master.cmd_eqe, 0, dev->caps.eqe_size); 2158ab9c17a0SJack Morgenstein priv->mfunc.master.cmd_eqe.type = MLX4_EVENT_TYPE_CMD; 2159ab9c17a0SJack Morgenstein INIT_WORK(&priv->mfunc.master.comm_work, 2160ab9c17a0SJack Morgenstein mlx4_master_comm_channel); 2161ab9c17a0SJack Morgenstein INIT_WORK(&priv->mfunc.master.slave_event_work, 2162ab9c17a0SJack Morgenstein mlx4_gen_slave_eqe); 2163ab9c17a0SJack Morgenstein INIT_WORK(&priv->mfunc.master.slave_flr_event_work, 2164ab9c17a0SJack Morgenstein mlx4_master_handle_slave_flr); 2165ab9c17a0SJack Morgenstein spin_lock_init(&priv->mfunc.master.slave_state_lock); 2166992e8e6eSJack Morgenstein spin_lock_init(&priv->mfunc.master.slave_eq.event_lock); 2167ab9c17a0SJack Morgenstein priv->mfunc.master.comm_wq = 2168ab9c17a0SJack Morgenstein create_singlethread_workqueue("mlx4_comm"); 2169ab9c17a0SJack Morgenstein if (!priv->mfunc.master.comm_wq) 2170ab9c17a0SJack Morgenstein goto err_slaves; 2171ab9c17a0SJack Morgenstein 2172ab9c17a0SJack Morgenstein if (mlx4_init_resource_tracker(dev)) 2173ab9c17a0SJack Morgenstein goto err_thread; 2174ab9c17a0SJack Morgenstein 2175ab9c17a0SJack Morgenstein err = mlx4_ARM_COMM_CHANNEL(dev); 2176ab9c17a0SJack Morgenstein if (err) { 2177ab9c17a0SJack Morgenstein mlx4_err(dev, " Failed to arm comm channel eq: %x\n", 2178ab9c17a0SJack Morgenstein err); 2179ab9c17a0SJack Morgenstein goto err_resource; 2180ab9c17a0SJack Morgenstein } 2181ab9c17a0SJack Morgenstein 2182ab9c17a0SJack Morgenstein } else { 2183ab9c17a0SJack Morgenstein err = sync_toggles(dev); 2184ab9c17a0SJack Morgenstein if (err) { 2185ab9c17a0SJack Morgenstein mlx4_err(dev, "Couldn't sync toggles\n"); 2186ab9c17a0SJack Morgenstein goto err_comm; 2187ab9c17a0SJack Morgenstein } 2188ab9c17a0SJack Morgenstein } 2189ab9c17a0SJack Morgenstein return 0; 2190ab9c17a0SJack Morgenstein 2191ab9c17a0SJack Morgenstein err_resource: 2192b8924951SJack Morgenstein mlx4_free_resource_tracker(dev, RES_TR_FREE_ALL); 2193ab9c17a0SJack Morgenstein err_thread: 2194ab9c17a0SJack Morgenstein flush_workqueue(priv->mfunc.master.comm_wq); 2195ab9c17a0SJack Morgenstein destroy_workqueue(priv->mfunc.master.comm_wq); 2196ab9c17a0SJack Morgenstein err_slaves: 2197ab9c17a0SJack Morgenstein while (--i) { 2198ab9c17a0SJack Morgenstein for (port = 1; port <= MLX4_MAX_PORTS; port++) 2199ab9c17a0SJack Morgenstein kfree(priv->mfunc.master.slave_state[i].vlan_filter[port]); 2200ab9c17a0SJack Morgenstein } 22010eb62b93SRony Efraim kfree(priv->mfunc.master.vf_oper); 22020eb62b93SRony Efraim err_comm_oper: 22030eb62b93SRony Efraim kfree(priv->mfunc.master.vf_admin); 22040eb62b93SRony Efraim err_comm_admin: 2205ab9c17a0SJack Morgenstein kfree(priv->mfunc.master.slave_state); 2206ab9c17a0SJack Morgenstein err_comm: 2207ab9c17a0SJack Morgenstein iounmap(priv->mfunc.comm); 2208ab9c17a0SJack Morgenstein err_vhcr: 2209872bf2fbSYishai Hadas dma_free_coherent(&dev->persist->pdev->dev, PAGE_SIZE, 2210ab9c17a0SJack Morgenstein priv->mfunc.vhcr, 2211ab9c17a0SJack Morgenstein priv->mfunc.vhcr_dma); 2212ab9c17a0SJack Morgenstein priv->mfunc.vhcr = NULL; 2213ab9c17a0SJack Morgenstein return -ENOMEM; 2214ab9c17a0SJack Morgenstein } 2215ab9c17a0SJack Morgenstein 22165a2cc190SJeff Kirsher int mlx4_cmd_init(struct mlx4_dev *dev) 22175a2cc190SJeff Kirsher { 22185a2cc190SJeff Kirsher struct mlx4_priv *priv = mlx4_priv(dev); 2219ffc39f6dSMatan Barak int flags = 0; 22205a2cc190SJeff Kirsher 2221ffc39f6dSMatan Barak if (!priv->cmd.initialized) { 2222f3d4c89eSRoland Dreier mutex_init(&priv->cmd.slave_cmd_mutex); 22235a2cc190SJeff Kirsher sema_init(&priv->cmd.poll_sem, 1); 22245a2cc190SJeff Kirsher priv->cmd.use_events = 0; 22255a2cc190SJeff Kirsher priv->cmd.toggle = 1; 2226ffc39f6dSMatan Barak priv->cmd.initialized = 1; 2227ffc39f6dSMatan Barak flags |= MLX4_CMD_CLEANUP_STRUCT; 2228ffc39f6dSMatan Barak } 22295a2cc190SJeff Kirsher 2230ffc39f6dSMatan Barak if (!mlx4_is_slave(dev) && !priv->cmd.hcr) { 2231872bf2fbSYishai Hadas priv->cmd.hcr = ioremap(pci_resource_start(dev->persist->pdev, 2232872bf2fbSYishai Hadas 0) + MLX4_HCR_BASE, MLX4_HCR_SIZE); 22335a2cc190SJeff Kirsher if (!priv->cmd.hcr) { 22341a91de28SJoe Perches mlx4_err(dev, "Couldn't map command register\n"); 2235ffc39f6dSMatan Barak goto err; 22365a2cc190SJeff Kirsher } 2237ffc39f6dSMatan Barak flags |= MLX4_CMD_CLEANUP_HCR; 2238e8f081aaSYevgeny Petrilin } 22395a2cc190SJeff Kirsher 2240ffc39f6dSMatan Barak if (mlx4_is_mfunc(dev) && !priv->mfunc.vhcr) { 2241872bf2fbSYishai Hadas priv->mfunc.vhcr = dma_alloc_coherent(&dev->persist->pdev->dev, 2242872bf2fbSYishai Hadas PAGE_SIZE, 2243f3d4c89eSRoland Dreier &priv->mfunc.vhcr_dma, 2244f3d4c89eSRoland Dreier GFP_KERNEL); 2245d0320f75SJoe Perches if (!priv->mfunc.vhcr) 2246ffc39f6dSMatan Barak goto err; 2247ffc39f6dSMatan Barak 2248ffc39f6dSMatan Barak flags |= MLX4_CMD_CLEANUP_VHCR; 2249f3d4c89eSRoland Dreier } 2250f3d4c89eSRoland Dreier 2251ffc39f6dSMatan Barak if (!priv->cmd.pool) { 2252872bf2fbSYishai Hadas priv->cmd.pool = pci_pool_create("mlx4_cmd", 2253872bf2fbSYishai Hadas dev->persist->pdev, 22545a2cc190SJeff Kirsher MLX4_MAILBOX_SIZE, 22555a2cc190SJeff Kirsher MLX4_MAILBOX_SIZE, 0); 2256e8f081aaSYevgeny Petrilin if (!priv->cmd.pool) 2257ffc39f6dSMatan Barak goto err; 2258ffc39f6dSMatan Barak 2259ffc39f6dSMatan Barak flags |= MLX4_CMD_CLEANUP_POOL; 2260ffc39f6dSMatan Barak } 22615a2cc190SJeff Kirsher 22625a2cc190SJeff Kirsher return 0; 2263e8f081aaSYevgeny Petrilin 2264ffc39f6dSMatan Barak err: 2265ffc39f6dSMatan Barak mlx4_cmd_cleanup(dev, flags); 2266e8f081aaSYevgeny Petrilin return -ENOMEM; 22675a2cc190SJeff Kirsher } 22685a2cc190SJeff Kirsher 2269ab9c17a0SJack Morgenstein void mlx4_multi_func_cleanup(struct mlx4_dev *dev) 2270ab9c17a0SJack Morgenstein { 2271ab9c17a0SJack Morgenstein struct mlx4_priv *priv = mlx4_priv(dev); 2272ab9c17a0SJack Morgenstein int i, port; 2273ab9c17a0SJack Morgenstein 2274ab9c17a0SJack Morgenstein if (mlx4_is_master(dev)) { 2275ab9c17a0SJack Morgenstein flush_workqueue(priv->mfunc.master.comm_wq); 2276ab9c17a0SJack Morgenstein destroy_workqueue(priv->mfunc.master.comm_wq); 2277ab9c17a0SJack Morgenstein for (i = 0; i < dev->num_slaves; i++) { 2278ab9c17a0SJack Morgenstein for (port = 1; port <= MLX4_MAX_PORTS; port++) 2279ab9c17a0SJack Morgenstein kfree(priv->mfunc.master.slave_state[i].vlan_filter[port]); 2280ab9c17a0SJack Morgenstein } 2281ab9c17a0SJack Morgenstein kfree(priv->mfunc.master.slave_state); 22820eb62b93SRony Efraim kfree(priv->mfunc.master.vf_admin); 22830eb62b93SRony Efraim kfree(priv->mfunc.master.vf_oper); 2284f08ad06cSEugenia Emantayev } 2285f08ad06cSEugenia Emantayev 2286ab9c17a0SJack Morgenstein iounmap(priv->mfunc.comm); 2287ab9c17a0SJack Morgenstein } 2288ab9c17a0SJack Morgenstein 2289ffc39f6dSMatan Barak void mlx4_cmd_cleanup(struct mlx4_dev *dev, int cleanup_mask) 22905a2cc190SJeff Kirsher { 22915a2cc190SJeff Kirsher struct mlx4_priv *priv = mlx4_priv(dev); 22925a2cc190SJeff Kirsher 2293ffc39f6dSMatan Barak if (priv->cmd.pool && (cleanup_mask & MLX4_CMD_CLEANUP_POOL)) { 22945a2cc190SJeff Kirsher pci_pool_destroy(priv->cmd.pool); 2295ffc39f6dSMatan Barak priv->cmd.pool = NULL; 2296ffc39f6dSMatan Barak } 2297e8f081aaSYevgeny Petrilin 2298ffc39f6dSMatan Barak if (!mlx4_is_slave(dev) && priv->cmd.hcr && 2299ffc39f6dSMatan Barak (cleanup_mask & MLX4_CMD_CLEANUP_HCR)) { 23005a2cc190SJeff Kirsher iounmap(priv->cmd.hcr); 2301ffc39f6dSMatan Barak priv->cmd.hcr = NULL; 2302ffc39f6dSMatan Barak } 2303ffc39f6dSMatan Barak if (mlx4_is_mfunc(dev) && priv->mfunc.vhcr && 2304ffc39f6dSMatan Barak (cleanup_mask & MLX4_CMD_CLEANUP_VHCR)) { 2305872bf2fbSYishai Hadas dma_free_coherent(&dev->persist->pdev->dev, PAGE_SIZE, 2306f3d4c89eSRoland Dreier priv->mfunc.vhcr, priv->mfunc.vhcr_dma); 2307f3d4c89eSRoland Dreier priv->mfunc.vhcr = NULL; 23085a2cc190SJeff Kirsher } 2309ffc39f6dSMatan Barak if (priv->cmd.initialized && (cleanup_mask & MLX4_CMD_CLEANUP_STRUCT)) 2310ffc39f6dSMatan Barak priv->cmd.initialized = 0; 2311ffc39f6dSMatan Barak } 23125a2cc190SJeff Kirsher 23135a2cc190SJeff Kirsher /* 23145a2cc190SJeff Kirsher * Switch to using events to issue FW commands (can only be called 23155a2cc190SJeff Kirsher * after event queue for command events has been initialized). 23165a2cc190SJeff Kirsher */ 23175a2cc190SJeff Kirsher int mlx4_cmd_use_events(struct mlx4_dev *dev) 23185a2cc190SJeff Kirsher { 23195a2cc190SJeff Kirsher struct mlx4_priv *priv = mlx4_priv(dev); 23205a2cc190SJeff Kirsher int i; 2321e8f081aaSYevgeny Petrilin int err = 0; 23225a2cc190SJeff Kirsher 23235a2cc190SJeff Kirsher priv->cmd.context = kmalloc(priv->cmd.max_cmds * 23245a2cc190SJeff Kirsher sizeof (struct mlx4_cmd_context), 23255a2cc190SJeff Kirsher GFP_KERNEL); 23265a2cc190SJeff Kirsher if (!priv->cmd.context) 23275a2cc190SJeff Kirsher return -ENOMEM; 23285a2cc190SJeff Kirsher 23295a2cc190SJeff Kirsher for (i = 0; i < priv->cmd.max_cmds; ++i) { 23305a2cc190SJeff Kirsher priv->cmd.context[i].token = i; 23315a2cc190SJeff Kirsher priv->cmd.context[i].next = i + 1; 2332*f5aef5aaSYishai Hadas /* To support fatal error flow, initialize all 2333*f5aef5aaSYishai Hadas * cmd contexts to allow simulating completions 2334*f5aef5aaSYishai Hadas * with complete() at any time. 2335*f5aef5aaSYishai Hadas */ 2336*f5aef5aaSYishai Hadas init_completion(&priv->cmd.context[i].done); 23375a2cc190SJeff Kirsher } 23385a2cc190SJeff Kirsher 23395a2cc190SJeff Kirsher priv->cmd.context[priv->cmd.max_cmds - 1].next = -1; 23405a2cc190SJeff Kirsher priv->cmd.free_head = 0; 23415a2cc190SJeff Kirsher 23425a2cc190SJeff Kirsher sema_init(&priv->cmd.event_sem, priv->cmd.max_cmds); 23435a2cc190SJeff Kirsher spin_lock_init(&priv->cmd.context_lock); 23445a2cc190SJeff Kirsher 23455a2cc190SJeff Kirsher for (priv->cmd.token_mask = 1; 23465a2cc190SJeff Kirsher priv->cmd.token_mask < priv->cmd.max_cmds; 23475a2cc190SJeff Kirsher priv->cmd.token_mask <<= 1) 23485a2cc190SJeff Kirsher ; /* nothing */ 23495a2cc190SJeff Kirsher --priv->cmd.token_mask; 23505a2cc190SJeff Kirsher 2351e8f081aaSYevgeny Petrilin down(&priv->cmd.poll_sem); 23525a2cc190SJeff Kirsher priv->cmd.use_events = 1; 23535a2cc190SJeff Kirsher 2354e8f081aaSYevgeny Petrilin return err; 23555a2cc190SJeff Kirsher } 23565a2cc190SJeff Kirsher 23575a2cc190SJeff Kirsher /* 23585a2cc190SJeff Kirsher * Switch back to polling (used when shutting down the device) 23595a2cc190SJeff Kirsher */ 23605a2cc190SJeff Kirsher void mlx4_cmd_use_polling(struct mlx4_dev *dev) 23615a2cc190SJeff Kirsher { 23625a2cc190SJeff Kirsher struct mlx4_priv *priv = mlx4_priv(dev); 23635a2cc190SJeff Kirsher int i; 23645a2cc190SJeff Kirsher 23655a2cc190SJeff Kirsher priv->cmd.use_events = 0; 23665a2cc190SJeff Kirsher 23675a2cc190SJeff Kirsher for (i = 0; i < priv->cmd.max_cmds; ++i) 23685a2cc190SJeff Kirsher down(&priv->cmd.event_sem); 23695a2cc190SJeff Kirsher 23705a2cc190SJeff Kirsher kfree(priv->cmd.context); 23715a2cc190SJeff Kirsher 23725a2cc190SJeff Kirsher up(&priv->cmd.poll_sem); 23735a2cc190SJeff Kirsher } 23745a2cc190SJeff Kirsher 23755a2cc190SJeff Kirsher struct mlx4_cmd_mailbox *mlx4_alloc_cmd_mailbox(struct mlx4_dev *dev) 23765a2cc190SJeff Kirsher { 23775a2cc190SJeff Kirsher struct mlx4_cmd_mailbox *mailbox; 23785a2cc190SJeff Kirsher 23795a2cc190SJeff Kirsher mailbox = kmalloc(sizeof *mailbox, GFP_KERNEL); 23805a2cc190SJeff Kirsher if (!mailbox) 23815a2cc190SJeff Kirsher return ERR_PTR(-ENOMEM); 23825a2cc190SJeff Kirsher 23835a2cc190SJeff Kirsher mailbox->buf = pci_pool_alloc(mlx4_priv(dev)->cmd.pool, GFP_KERNEL, 23845a2cc190SJeff Kirsher &mailbox->dma); 23855a2cc190SJeff Kirsher if (!mailbox->buf) { 23865a2cc190SJeff Kirsher kfree(mailbox); 23875a2cc190SJeff Kirsher return ERR_PTR(-ENOMEM); 23885a2cc190SJeff Kirsher } 23895a2cc190SJeff Kirsher 2390571b8b92SJack Morgenstein memset(mailbox->buf, 0, MLX4_MAILBOX_SIZE); 2391571b8b92SJack Morgenstein 23925a2cc190SJeff Kirsher return mailbox; 23935a2cc190SJeff Kirsher } 23945a2cc190SJeff Kirsher EXPORT_SYMBOL_GPL(mlx4_alloc_cmd_mailbox); 23955a2cc190SJeff Kirsher 2396e8f081aaSYevgeny Petrilin void mlx4_free_cmd_mailbox(struct mlx4_dev *dev, 2397e8f081aaSYevgeny Petrilin struct mlx4_cmd_mailbox *mailbox) 23985a2cc190SJeff Kirsher { 23995a2cc190SJeff Kirsher if (!mailbox) 24005a2cc190SJeff Kirsher return; 24015a2cc190SJeff Kirsher 24025a2cc190SJeff Kirsher pci_pool_free(mlx4_priv(dev)->cmd.pool, mailbox->buf, mailbox->dma); 24035a2cc190SJeff Kirsher kfree(mailbox); 24045a2cc190SJeff Kirsher } 24055a2cc190SJeff Kirsher EXPORT_SYMBOL_GPL(mlx4_free_cmd_mailbox); 2406e8f081aaSYevgeny Petrilin 2407e8f081aaSYevgeny Petrilin u32 mlx4_comm_get_version(void) 2408e8f081aaSYevgeny Petrilin { 2409e8f081aaSYevgeny Petrilin return ((u32) CMD_CHAN_IF_REV << 8) | (u32) CMD_CHAN_VER; 2410e8f081aaSYevgeny Petrilin } 24118f7ba3caSRony Efraim 24128f7ba3caSRony Efraim static int mlx4_get_slave_indx(struct mlx4_dev *dev, int vf) 24138f7ba3caSRony Efraim { 2414872bf2fbSYishai Hadas if ((vf < 0) || (vf >= dev->persist->num_vfs)) { 2415872bf2fbSYishai Hadas mlx4_err(dev, "Bad vf number:%d (number of activated vf: %d)\n", 2416872bf2fbSYishai Hadas vf, dev->persist->num_vfs); 24178f7ba3caSRony Efraim return -EINVAL; 24188f7ba3caSRony Efraim } 24198f7ba3caSRony Efraim 24208f7ba3caSRony Efraim return vf+1; 24218f7ba3caSRony Efraim } 24228f7ba3caSRony Efraim 2423f74462acSMatan Barak int mlx4_get_vf_indx(struct mlx4_dev *dev, int slave) 2424f74462acSMatan Barak { 2425872bf2fbSYishai Hadas if (slave < 1 || slave > dev->persist->num_vfs) { 2426f74462acSMatan Barak mlx4_err(dev, 2427f74462acSMatan Barak "Bad slave number:%d (number of activated slaves: %lu)\n", 2428f74462acSMatan Barak slave, dev->num_slaves); 2429f74462acSMatan Barak return -EINVAL; 2430f74462acSMatan Barak } 2431f74462acSMatan Barak return slave - 1; 2432f74462acSMatan Barak } 2433f74462acSMatan Barak 2434*f5aef5aaSYishai Hadas void mlx4_cmd_wake_completions(struct mlx4_dev *dev) 2435*f5aef5aaSYishai Hadas { 2436*f5aef5aaSYishai Hadas struct mlx4_priv *priv = mlx4_priv(dev); 2437*f5aef5aaSYishai Hadas struct mlx4_cmd_context *context; 2438*f5aef5aaSYishai Hadas int i; 2439*f5aef5aaSYishai Hadas 2440*f5aef5aaSYishai Hadas spin_lock(&priv->cmd.context_lock); 2441*f5aef5aaSYishai Hadas if (priv->cmd.context) { 2442*f5aef5aaSYishai Hadas for (i = 0; i < priv->cmd.max_cmds; ++i) { 2443*f5aef5aaSYishai Hadas context = &priv->cmd.context[i]; 2444*f5aef5aaSYishai Hadas context->fw_status = CMD_STAT_INTERNAL_ERR; 2445*f5aef5aaSYishai Hadas context->result = 2446*f5aef5aaSYishai Hadas mlx4_status_to_errno(CMD_STAT_INTERNAL_ERR); 2447*f5aef5aaSYishai Hadas complete(&context->done); 2448*f5aef5aaSYishai Hadas } 2449*f5aef5aaSYishai Hadas } 2450*f5aef5aaSYishai Hadas spin_unlock(&priv->cmd.context_lock); 2451*f5aef5aaSYishai Hadas } 2452*f5aef5aaSYishai Hadas 2453f74462acSMatan Barak struct mlx4_active_ports mlx4_get_active_ports(struct mlx4_dev *dev, int slave) 2454f74462acSMatan Barak { 2455f74462acSMatan Barak struct mlx4_active_ports actv_ports; 2456f74462acSMatan Barak int vf; 2457f74462acSMatan Barak 2458f74462acSMatan Barak bitmap_zero(actv_ports.ports, MLX4_MAX_PORTS); 2459f74462acSMatan Barak 2460f74462acSMatan Barak if (slave == 0) { 2461f74462acSMatan Barak bitmap_fill(actv_ports.ports, dev->caps.num_ports); 2462f74462acSMatan Barak return actv_ports; 2463f74462acSMatan Barak } 2464f74462acSMatan Barak 2465f74462acSMatan Barak vf = mlx4_get_vf_indx(dev, slave); 2466f74462acSMatan Barak if (vf < 0) 2467f74462acSMatan Barak return actv_ports; 2468f74462acSMatan Barak 2469f74462acSMatan Barak bitmap_set(actv_ports.ports, dev->dev_vfs[vf].min_port - 1, 2470f74462acSMatan Barak min((int)dev->dev_vfs[mlx4_get_vf_indx(dev, slave)].n_ports, 2471f74462acSMatan Barak dev->caps.num_ports)); 2472f74462acSMatan Barak 2473f74462acSMatan Barak return actv_ports; 2474f74462acSMatan Barak } 2475f74462acSMatan Barak EXPORT_SYMBOL_GPL(mlx4_get_active_ports); 2476f74462acSMatan Barak 2477f74462acSMatan Barak int mlx4_slave_convert_port(struct mlx4_dev *dev, int slave, int port) 2478f74462acSMatan Barak { 2479f74462acSMatan Barak unsigned n; 2480f74462acSMatan Barak struct mlx4_active_ports actv_ports = mlx4_get_active_ports(dev, slave); 2481f74462acSMatan Barak unsigned m = bitmap_weight(actv_ports.ports, dev->caps.num_ports); 2482f74462acSMatan Barak 2483f74462acSMatan Barak if (port <= 0 || port > m) 2484f74462acSMatan Barak return -EINVAL; 2485f74462acSMatan Barak 2486f74462acSMatan Barak n = find_first_bit(actv_ports.ports, dev->caps.num_ports); 2487f74462acSMatan Barak if (port <= n) 2488f74462acSMatan Barak port = n + 1; 2489f74462acSMatan Barak 2490f74462acSMatan Barak return port; 2491f74462acSMatan Barak } 2492f74462acSMatan Barak EXPORT_SYMBOL_GPL(mlx4_slave_convert_port); 2493f74462acSMatan Barak 2494f74462acSMatan Barak int mlx4_phys_to_slave_port(struct mlx4_dev *dev, int slave, int port) 2495f74462acSMatan Barak { 2496f74462acSMatan Barak struct mlx4_active_ports actv_ports = mlx4_get_active_ports(dev, slave); 2497f74462acSMatan Barak if (test_bit(port - 1, actv_ports.ports)) 2498f74462acSMatan Barak return port - 2499f74462acSMatan Barak find_first_bit(actv_ports.ports, dev->caps.num_ports); 2500f74462acSMatan Barak 2501f74462acSMatan Barak return -1; 2502f74462acSMatan Barak } 2503f74462acSMatan Barak EXPORT_SYMBOL_GPL(mlx4_phys_to_slave_port); 2504f74462acSMatan Barak 2505f74462acSMatan Barak struct mlx4_slaves_pport mlx4_phys_to_slaves_pport(struct mlx4_dev *dev, 2506f74462acSMatan Barak int port) 2507f74462acSMatan Barak { 2508f74462acSMatan Barak unsigned i; 2509f74462acSMatan Barak struct mlx4_slaves_pport slaves_pport; 2510f74462acSMatan Barak 2511f74462acSMatan Barak bitmap_zero(slaves_pport.slaves, MLX4_MFUNC_MAX); 2512f74462acSMatan Barak 2513f74462acSMatan Barak if (port <= 0 || port > dev->caps.num_ports) 2514f74462acSMatan Barak return slaves_pport; 2515f74462acSMatan Barak 2516872bf2fbSYishai Hadas for (i = 0; i < dev->persist->num_vfs + 1; i++) { 2517f74462acSMatan Barak struct mlx4_active_ports actv_ports = 2518f74462acSMatan Barak mlx4_get_active_ports(dev, i); 2519f74462acSMatan Barak if (test_bit(port - 1, actv_ports.ports)) 2520f74462acSMatan Barak set_bit(i, slaves_pport.slaves); 2521f74462acSMatan Barak } 2522f74462acSMatan Barak 2523f74462acSMatan Barak return slaves_pport; 2524f74462acSMatan Barak } 2525f74462acSMatan Barak EXPORT_SYMBOL_GPL(mlx4_phys_to_slaves_pport); 2526f74462acSMatan Barak 2527f74462acSMatan Barak struct mlx4_slaves_pport mlx4_phys_to_slaves_pport_actv( 2528f74462acSMatan Barak struct mlx4_dev *dev, 2529f74462acSMatan Barak const struct mlx4_active_ports *crit_ports) 2530f74462acSMatan Barak { 2531f74462acSMatan Barak unsigned i; 2532f74462acSMatan Barak struct mlx4_slaves_pport slaves_pport; 2533f74462acSMatan Barak 2534f74462acSMatan Barak bitmap_zero(slaves_pport.slaves, MLX4_MFUNC_MAX); 2535f74462acSMatan Barak 2536872bf2fbSYishai Hadas for (i = 0; i < dev->persist->num_vfs + 1; i++) { 2537f74462acSMatan Barak struct mlx4_active_ports actv_ports = 2538f74462acSMatan Barak mlx4_get_active_ports(dev, i); 2539f74462acSMatan Barak if (bitmap_equal(crit_ports->ports, actv_ports.ports, 2540f74462acSMatan Barak dev->caps.num_ports)) 2541f74462acSMatan Barak set_bit(i, slaves_pport.slaves); 2542f74462acSMatan Barak } 2543f74462acSMatan Barak 2544f74462acSMatan Barak return slaves_pport; 2545f74462acSMatan Barak } 2546f74462acSMatan Barak EXPORT_SYMBOL_GPL(mlx4_phys_to_slaves_pport_actv); 2547f74462acSMatan Barak 2548a91c772fSMatan Barak static int mlx4_slaves_closest_port(struct mlx4_dev *dev, int slave, int port) 2549a91c772fSMatan Barak { 2550a91c772fSMatan Barak struct mlx4_active_ports actv_ports = mlx4_get_active_ports(dev, slave); 2551a91c772fSMatan Barak int min_port = find_first_bit(actv_ports.ports, dev->caps.num_ports) 2552a91c772fSMatan Barak + 1; 2553a91c772fSMatan Barak int max_port = min_port + 2554a91c772fSMatan Barak bitmap_weight(actv_ports.ports, dev->caps.num_ports); 2555a91c772fSMatan Barak 2556a91c772fSMatan Barak if (port < min_port) 2557a91c772fSMatan Barak port = min_port; 2558a91c772fSMatan Barak else if (port >= max_port) 2559a91c772fSMatan Barak port = max_port - 1; 2560a91c772fSMatan Barak 2561a91c772fSMatan Barak return port; 2562a91c772fSMatan Barak } 2563a91c772fSMatan Barak 25648f7ba3caSRony Efraim int mlx4_set_vf_mac(struct mlx4_dev *dev, int port, int vf, u64 mac) 25658f7ba3caSRony Efraim { 25668f7ba3caSRony Efraim struct mlx4_priv *priv = mlx4_priv(dev); 25678f7ba3caSRony Efraim struct mlx4_vport_state *s_info; 25688f7ba3caSRony Efraim int slave; 25698f7ba3caSRony Efraim 25708f7ba3caSRony Efraim if (!mlx4_is_master(dev)) 25718f7ba3caSRony Efraim return -EPROTONOSUPPORT; 25728f7ba3caSRony Efraim 25738f7ba3caSRony Efraim slave = mlx4_get_slave_indx(dev, vf); 25748f7ba3caSRony Efraim if (slave < 0) 25758f7ba3caSRony Efraim return -EINVAL; 25768f7ba3caSRony Efraim 2577a91c772fSMatan Barak port = mlx4_slaves_closest_port(dev, slave, port); 25788f7ba3caSRony Efraim s_info = &priv->mfunc.master.vf_admin[slave].vport[port]; 25798f7ba3caSRony Efraim s_info->mac = mac; 25808f7ba3caSRony Efraim mlx4_info(dev, "default mac on vf %d port %d to %llX will take afect only after vf restart\n", 25818f7ba3caSRony Efraim vf, port, s_info->mac); 25828f7ba3caSRony Efraim return 0; 25838f7ba3caSRony Efraim } 25848f7ba3caSRony Efraim EXPORT_SYMBOL_GPL(mlx4_set_vf_mac); 25853f7fb021SRony Efraim 2586b01978caSJack Morgenstein 25873f7fb021SRony Efraim int mlx4_set_vf_vlan(struct mlx4_dev *dev, int port, int vf, u16 vlan, u8 qos) 25883f7fb021SRony Efraim { 25893f7fb021SRony Efraim struct mlx4_priv *priv = mlx4_priv(dev); 2590b01978caSJack Morgenstein struct mlx4_vport_state *vf_admin; 25913f7fb021SRony Efraim int slave; 25923f7fb021SRony Efraim 25933f7fb021SRony Efraim if ((!mlx4_is_master(dev)) || 25943f7fb021SRony Efraim !(dev->caps.flags2 & MLX4_DEV_CAP_FLAG2_VLAN_CONTROL)) 25953f7fb021SRony Efraim return -EPROTONOSUPPORT; 25963f7fb021SRony Efraim 25973f7fb021SRony Efraim if ((vlan > 4095) || (qos > 7)) 25983f7fb021SRony Efraim return -EINVAL; 25993f7fb021SRony Efraim 26003f7fb021SRony Efraim slave = mlx4_get_slave_indx(dev, vf); 26013f7fb021SRony Efraim if (slave < 0) 26023f7fb021SRony Efraim return -EINVAL; 26033f7fb021SRony Efraim 2604a91c772fSMatan Barak port = mlx4_slaves_closest_port(dev, slave, port); 2605b01978caSJack Morgenstein vf_admin = &priv->mfunc.master.vf_admin[slave].vport[port]; 2606b01978caSJack Morgenstein 26073f7fb021SRony Efraim if ((0 == vlan) && (0 == qos)) 2608b01978caSJack Morgenstein vf_admin->default_vlan = MLX4_VGT; 26093f7fb021SRony Efraim else 2610b01978caSJack Morgenstein vf_admin->default_vlan = vlan; 2611b01978caSJack Morgenstein vf_admin->default_qos = qos; 2612b01978caSJack Morgenstein 26130a6eac24SRony Efraim if (mlx4_master_immediate_activate_vlan_qos(priv, slave, port)) 26140a6eac24SRony Efraim mlx4_info(dev, 26150a6eac24SRony Efraim "updating vf %d port %d config will take effect on next VF restart\n", 2616b01978caSJack Morgenstein vf, port); 26173f7fb021SRony Efraim return 0; 26183f7fb021SRony Efraim } 26193f7fb021SRony Efraim EXPORT_SYMBOL_GPL(mlx4_set_vf_vlan); 2620e6b6a231SRony Efraim 26215ea8bbfcSJack Morgenstein /* mlx4_get_slave_default_vlan - 26225ea8bbfcSJack Morgenstein * return true if VST ( default vlan) 26235ea8bbfcSJack Morgenstein * if VST, will return vlan & qos (if not NULL) 26245ea8bbfcSJack Morgenstein */ 26255ea8bbfcSJack Morgenstein bool mlx4_get_slave_default_vlan(struct mlx4_dev *dev, int port, int slave, 26265ea8bbfcSJack Morgenstein u16 *vlan, u8 *qos) 26275ea8bbfcSJack Morgenstein { 26285ea8bbfcSJack Morgenstein struct mlx4_vport_oper_state *vp_oper; 26295ea8bbfcSJack Morgenstein struct mlx4_priv *priv; 26305ea8bbfcSJack Morgenstein 26315ea8bbfcSJack Morgenstein priv = mlx4_priv(dev); 2632a91c772fSMatan Barak port = mlx4_slaves_closest_port(dev, slave, port); 26335ea8bbfcSJack Morgenstein vp_oper = &priv->mfunc.master.vf_oper[slave].vport[port]; 26345ea8bbfcSJack Morgenstein 26355ea8bbfcSJack Morgenstein if (MLX4_VGT != vp_oper->state.default_vlan) { 26365ea8bbfcSJack Morgenstein if (vlan) 26375ea8bbfcSJack Morgenstein *vlan = vp_oper->state.default_vlan; 26385ea8bbfcSJack Morgenstein if (qos) 26395ea8bbfcSJack Morgenstein *qos = vp_oper->state.default_qos; 26405ea8bbfcSJack Morgenstein return true; 26415ea8bbfcSJack Morgenstein } 26425ea8bbfcSJack Morgenstein return false; 26435ea8bbfcSJack Morgenstein } 26445ea8bbfcSJack Morgenstein EXPORT_SYMBOL_GPL(mlx4_get_slave_default_vlan); 26455ea8bbfcSJack Morgenstein 2646e6b6a231SRony Efraim int mlx4_set_vf_spoofchk(struct mlx4_dev *dev, int port, int vf, bool setting) 2647e6b6a231SRony Efraim { 2648e6b6a231SRony Efraim struct mlx4_priv *priv = mlx4_priv(dev); 2649e6b6a231SRony Efraim struct mlx4_vport_state *s_info; 2650e6b6a231SRony Efraim int slave; 2651e6b6a231SRony Efraim 2652e6b6a231SRony Efraim if ((!mlx4_is_master(dev)) || 2653e6b6a231SRony Efraim !(dev->caps.flags2 & MLX4_DEV_CAP_FLAG2_FSM)) 2654e6b6a231SRony Efraim return -EPROTONOSUPPORT; 2655e6b6a231SRony Efraim 2656e6b6a231SRony Efraim slave = mlx4_get_slave_indx(dev, vf); 2657e6b6a231SRony Efraim if (slave < 0) 2658e6b6a231SRony Efraim return -EINVAL; 2659e6b6a231SRony Efraim 2660a91c772fSMatan Barak port = mlx4_slaves_closest_port(dev, slave, port); 2661e6b6a231SRony Efraim s_info = &priv->mfunc.master.vf_admin[slave].vport[port]; 2662e6b6a231SRony Efraim s_info->spoofchk = setting; 2663e6b6a231SRony Efraim 2664e6b6a231SRony Efraim return 0; 2665e6b6a231SRony Efraim } 2666e6b6a231SRony Efraim EXPORT_SYMBOL_GPL(mlx4_set_vf_spoofchk); 26672cccb9e4SRony Efraim 26682cccb9e4SRony Efraim int mlx4_get_vf_config(struct mlx4_dev *dev, int port, int vf, struct ifla_vf_info *ivf) 26692cccb9e4SRony Efraim { 26702cccb9e4SRony Efraim struct mlx4_priv *priv = mlx4_priv(dev); 26712cccb9e4SRony Efraim struct mlx4_vport_state *s_info; 26722cccb9e4SRony Efraim int slave; 26732cccb9e4SRony Efraim 26742cccb9e4SRony Efraim if (!mlx4_is_master(dev)) 26752cccb9e4SRony Efraim return -EPROTONOSUPPORT; 26762cccb9e4SRony Efraim 26772cccb9e4SRony Efraim slave = mlx4_get_slave_indx(dev, vf); 26782cccb9e4SRony Efraim if (slave < 0) 26792cccb9e4SRony Efraim return -EINVAL; 26802cccb9e4SRony Efraim 26812cccb9e4SRony Efraim s_info = &priv->mfunc.master.vf_admin[slave].vport[port]; 26822cccb9e4SRony Efraim ivf->vf = vf; 26832cccb9e4SRony Efraim 26842cccb9e4SRony Efraim /* need to convert it to a func */ 26852cccb9e4SRony Efraim ivf->mac[0] = ((s_info->mac >> (5*8)) & 0xff); 26862cccb9e4SRony Efraim ivf->mac[1] = ((s_info->mac >> (4*8)) & 0xff); 26872cccb9e4SRony Efraim ivf->mac[2] = ((s_info->mac >> (3*8)) & 0xff); 26882cccb9e4SRony Efraim ivf->mac[3] = ((s_info->mac >> (2*8)) & 0xff); 26892cccb9e4SRony Efraim ivf->mac[4] = ((s_info->mac >> (1*8)) & 0xff); 26902cccb9e4SRony Efraim ivf->mac[5] = ((s_info->mac) & 0xff); 26912cccb9e4SRony Efraim 26922cccb9e4SRony Efraim ivf->vlan = s_info->default_vlan; 26932cccb9e4SRony Efraim ivf->qos = s_info->default_qos; 2694ed616689SSucheta Chakraborty ivf->max_tx_rate = s_info->tx_rate; 2695ed616689SSucheta Chakraborty ivf->min_tx_rate = 0; 26962cccb9e4SRony Efraim ivf->spoofchk = s_info->spoofchk; 2697948e306dSRony Efraim ivf->linkstate = s_info->link_state; 26982cccb9e4SRony Efraim 26992cccb9e4SRony Efraim return 0; 27002cccb9e4SRony Efraim } 27012cccb9e4SRony Efraim EXPORT_SYMBOL_GPL(mlx4_get_vf_config); 2702948e306dSRony Efraim 2703948e306dSRony Efraim int mlx4_set_vf_link_state(struct mlx4_dev *dev, int port, int vf, int link_state) 2704948e306dSRony Efraim { 2705948e306dSRony Efraim struct mlx4_priv *priv = mlx4_priv(dev); 2706948e306dSRony Efraim struct mlx4_vport_state *s_info; 2707948e306dSRony Efraim int slave; 2708948e306dSRony Efraim u8 link_stat_event; 2709948e306dSRony Efraim 2710948e306dSRony Efraim slave = mlx4_get_slave_indx(dev, vf); 2711948e306dSRony Efraim if (slave < 0) 2712948e306dSRony Efraim return -EINVAL; 2713948e306dSRony Efraim 2714a91c772fSMatan Barak port = mlx4_slaves_closest_port(dev, slave, port); 2715948e306dSRony Efraim switch (link_state) { 2716948e306dSRony Efraim case IFLA_VF_LINK_STATE_AUTO: 2717948e306dSRony Efraim /* get current link state */ 2718948e306dSRony Efraim if (!priv->sense.do_sense_port[port]) 2719948e306dSRony Efraim link_stat_event = MLX4_PORT_CHANGE_SUBTYPE_ACTIVE; 2720948e306dSRony Efraim else 2721948e306dSRony Efraim link_stat_event = MLX4_PORT_CHANGE_SUBTYPE_DOWN; 2722948e306dSRony Efraim break; 2723948e306dSRony Efraim 2724948e306dSRony Efraim case IFLA_VF_LINK_STATE_ENABLE: 2725948e306dSRony Efraim link_stat_event = MLX4_PORT_CHANGE_SUBTYPE_ACTIVE; 2726948e306dSRony Efraim break; 2727948e306dSRony Efraim 2728948e306dSRony Efraim case IFLA_VF_LINK_STATE_DISABLE: 2729948e306dSRony Efraim link_stat_event = MLX4_PORT_CHANGE_SUBTYPE_DOWN; 2730948e306dSRony Efraim break; 2731948e306dSRony Efraim 2732948e306dSRony Efraim default: 2733948e306dSRony Efraim mlx4_warn(dev, "unknown value for link_state %02x on slave %d port %d\n", 2734948e306dSRony Efraim link_state, slave, port); 2735948e306dSRony Efraim return -EINVAL; 2736948e306dSRony Efraim }; 2737948e306dSRony Efraim s_info = &priv->mfunc.master.vf_admin[slave].vport[port]; 2738948e306dSRony Efraim s_info->link_state = link_state; 2739948e306dSRony Efraim 2740948e306dSRony Efraim /* send event */ 2741948e306dSRony Efraim mlx4_gen_port_state_change_eqe(dev, slave, port, link_stat_event); 27420a6eac24SRony Efraim 27430a6eac24SRony Efraim if (mlx4_master_immediate_activate_vlan_qos(priv, slave, port)) 27440a6eac24SRony Efraim mlx4_dbg(dev, 27450a6eac24SRony Efraim "updating vf %d port %d no link state HW enforcment\n", 27460a6eac24SRony Efraim vf, port); 2747948e306dSRony Efraim return 0; 2748948e306dSRony Efraim } 2749948e306dSRony Efraim EXPORT_SYMBOL_GPL(mlx4_set_vf_link_state); 275097982f5aSJack Morgenstein 275197982f5aSJack Morgenstein int mlx4_vf_smi_enabled(struct mlx4_dev *dev, int slave, int port) 275297982f5aSJack Morgenstein { 275399ec41d0SJack Morgenstein struct mlx4_priv *priv = mlx4_priv(dev); 275499ec41d0SJack Morgenstein 275599ec41d0SJack Morgenstein if (slave < 1 || slave >= dev->num_slaves || 275699ec41d0SJack Morgenstein port < 1 || port > MLX4_MAX_PORTS) 275797982f5aSJack Morgenstein return 0; 275899ec41d0SJack Morgenstein 275999ec41d0SJack Morgenstein return priv->mfunc.master.vf_oper[slave].smi_enabled[port] == 276099ec41d0SJack Morgenstein MLX4_VF_SMI_ENABLED; 276197982f5aSJack Morgenstein } 276297982f5aSJack Morgenstein EXPORT_SYMBOL_GPL(mlx4_vf_smi_enabled); 276365fed8a8SJack Morgenstein 276465fed8a8SJack Morgenstein int mlx4_vf_get_enable_smi_admin(struct mlx4_dev *dev, int slave, int port) 276565fed8a8SJack Morgenstein { 276665fed8a8SJack Morgenstein struct mlx4_priv *priv = mlx4_priv(dev); 276765fed8a8SJack Morgenstein 276865fed8a8SJack Morgenstein if (slave == mlx4_master_func_num(dev)) 276965fed8a8SJack Morgenstein return 1; 277065fed8a8SJack Morgenstein 277165fed8a8SJack Morgenstein if (slave < 1 || slave >= dev->num_slaves || 277265fed8a8SJack Morgenstein port < 1 || port > MLX4_MAX_PORTS) 277365fed8a8SJack Morgenstein return 0; 277465fed8a8SJack Morgenstein 277565fed8a8SJack Morgenstein return priv->mfunc.master.vf_admin[slave].enable_smi[port] == 277665fed8a8SJack Morgenstein MLX4_VF_SMI_ENABLED; 277765fed8a8SJack Morgenstein } 277865fed8a8SJack Morgenstein EXPORT_SYMBOL_GPL(mlx4_vf_get_enable_smi_admin); 277965fed8a8SJack Morgenstein 278065fed8a8SJack Morgenstein int mlx4_vf_set_enable_smi_admin(struct mlx4_dev *dev, int slave, int port, 278165fed8a8SJack Morgenstein int enabled) 278265fed8a8SJack Morgenstein { 278365fed8a8SJack Morgenstein struct mlx4_priv *priv = mlx4_priv(dev); 278465fed8a8SJack Morgenstein 278565fed8a8SJack Morgenstein if (slave == mlx4_master_func_num(dev)) 278665fed8a8SJack Morgenstein return 0; 278765fed8a8SJack Morgenstein 278865fed8a8SJack Morgenstein if (slave < 1 || slave >= dev->num_slaves || 278965fed8a8SJack Morgenstein port < 1 || port > MLX4_MAX_PORTS || 279065fed8a8SJack Morgenstein enabled < 0 || enabled > 1) 279165fed8a8SJack Morgenstein return -EINVAL; 279265fed8a8SJack Morgenstein 279365fed8a8SJack Morgenstein priv->mfunc.master.vf_admin[slave].enable_smi[port] = enabled; 279465fed8a8SJack Morgenstein return 0; 279565fed8a8SJack Morgenstein } 279665fed8a8SJack Morgenstein EXPORT_SYMBOL_GPL(mlx4_vf_set_enable_smi_admin); 2797