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> 42e8f081aaSYevgeny Petrilin #include <linux/semaphore.h> 435a2cc190SJeff Kirsher 445a2cc190SJeff Kirsher #include <asm/io.h> 455a2cc190SJeff Kirsher 465a2cc190SJeff Kirsher #include "mlx4.h" 47e8f081aaSYevgeny Petrilin #include "fw.h" 485a2cc190SJeff Kirsher 495a2cc190SJeff Kirsher #define CMD_POLL_TOKEN 0xffff 50e8f081aaSYevgeny Petrilin #define INBOX_MASK 0xffffffffffffff00ULL 51e8f081aaSYevgeny Petrilin 52e8f081aaSYevgeny Petrilin #define CMD_CHAN_VER 1 53e8f081aaSYevgeny Petrilin #define CMD_CHAN_IF_REV 1 545a2cc190SJeff Kirsher 555a2cc190SJeff Kirsher enum { 565a2cc190SJeff Kirsher /* command completed successfully: */ 575a2cc190SJeff Kirsher CMD_STAT_OK = 0x00, 585a2cc190SJeff Kirsher /* Internal error (such as a bus error) occurred while processing command: */ 595a2cc190SJeff Kirsher CMD_STAT_INTERNAL_ERR = 0x01, 605a2cc190SJeff Kirsher /* Operation/command not supported or opcode modifier not supported: */ 615a2cc190SJeff Kirsher CMD_STAT_BAD_OP = 0x02, 625a2cc190SJeff Kirsher /* Parameter not supported or parameter out of range: */ 635a2cc190SJeff Kirsher CMD_STAT_BAD_PARAM = 0x03, 645a2cc190SJeff Kirsher /* System not enabled or bad system state: */ 655a2cc190SJeff Kirsher CMD_STAT_BAD_SYS_STATE = 0x04, 665a2cc190SJeff Kirsher /* Attempt to access reserved or unallocaterd resource: */ 675a2cc190SJeff Kirsher CMD_STAT_BAD_RESOURCE = 0x05, 685a2cc190SJeff Kirsher /* Requested resource is currently executing a command, or is otherwise busy: */ 695a2cc190SJeff Kirsher CMD_STAT_RESOURCE_BUSY = 0x06, 705a2cc190SJeff Kirsher /* Required capability exceeds device limits: */ 715a2cc190SJeff Kirsher CMD_STAT_EXCEED_LIM = 0x08, 725a2cc190SJeff Kirsher /* Resource is not in the appropriate state or ownership: */ 735a2cc190SJeff Kirsher CMD_STAT_BAD_RES_STATE = 0x09, 745a2cc190SJeff Kirsher /* Index out of range: */ 755a2cc190SJeff Kirsher CMD_STAT_BAD_INDEX = 0x0a, 765a2cc190SJeff Kirsher /* FW image corrupted: */ 775a2cc190SJeff Kirsher CMD_STAT_BAD_NVMEM = 0x0b, 785a2cc190SJeff Kirsher /* Error in ICM mapping (e.g. not enough auxiliary ICM pages to execute command): */ 795a2cc190SJeff Kirsher CMD_STAT_ICM_ERROR = 0x0c, 805a2cc190SJeff Kirsher /* Attempt to modify a QP/EE which is not in the presumed state: */ 815a2cc190SJeff Kirsher CMD_STAT_BAD_QP_STATE = 0x10, 825a2cc190SJeff Kirsher /* Bad segment parameters (Address/Size): */ 835a2cc190SJeff Kirsher CMD_STAT_BAD_SEG_PARAM = 0x20, 845a2cc190SJeff Kirsher /* Memory Region has Memory Windows bound to: */ 855a2cc190SJeff Kirsher CMD_STAT_REG_BOUND = 0x21, 865a2cc190SJeff Kirsher /* HCA local attached memory not present: */ 875a2cc190SJeff Kirsher CMD_STAT_LAM_NOT_PRE = 0x22, 885a2cc190SJeff Kirsher /* Bad management packet (silently discarded): */ 895a2cc190SJeff Kirsher CMD_STAT_BAD_PKT = 0x30, 905a2cc190SJeff Kirsher /* More outstanding CQEs in CQ than new CQ size: */ 915a2cc190SJeff Kirsher CMD_STAT_BAD_SIZE = 0x40, 925a2cc190SJeff Kirsher /* Multi Function device support required: */ 935a2cc190SJeff Kirsher CMD_STAT_MULTI_FUNC_REQ = 0x50, 945a2cc190SJeff Kirsher }; 955a2cc190SJeff Kirsher 965a2cc190SJeff Kirsher enum { 975a2cc190SJeff Kirsher HCR_IN_PARAM_OFFSET = 0x00, 985a2cc190SJeff Kirsher HCR_IN_MODIFIER_OFFSET = 0x08, 995a2cc190SJeff Kirsher HCR_OUT_PARAM_OFFSET = 0x0c, 1005a2cc190SJeff Kirsher HCR_TOKEN_OFFSET = 0x14, 1015a2cc190SJeff Kirsher HCR_STATUS_OFFSET = 0x18, 1025a2cc190SJeff Kirsher 1035a2cc190SJeff Kirsher HCR_OPMOD_SHIFT = 12, 1045a2cc190SJeff Kirsher HCR_T_BIT = 21, 1055a2cc190SJeff Kirsher HCR_E_BIT = 22, 1065a2cc190SJeff Kirsher HCR_GO_BIT = 23 1075a2cc190SJeff Kirsher }; 1085a2cc190SJeff Kirsher 1095a2cc190SJeff Kirsher enum { 1105a2cc190SJeff Kirsher GO_BIT_TIMEOUT_MSECS = 10000 1115a2cc190SJeff Kirsher }; 1125a2cc190SJeff Kirsher 1135a2cc190SJeff Kirsher struct mlx4_cmd_context { 1145a2cc190SJeff Kirsher struct completion done; 1155a2cc190SJeff Kirsher int result; 1165a2cc190SJeff Kirsher int next; 1175a2cc190SJeff Kirsher u64 out_param; 1185a2cc190SJeff Kirsher u16 token; 119e8f081aaSYevgeny Petrilin u8 fw_status; 1205a2cc190SJeff Kirsher }; 1215a2cc190SJeff Kirsher 122e8f081aaSYevgeny Petrilin static int mlx4_master_process_vhcr(struct mlx4_dev *dev, int slave, 123e8f081aaSYevgeny Petrilin struct mlx4_vhcr_cmd *in_vhcr); 124e8f081aaSYevgeny Petrilin 1255a2cc190SJeff Kirsher static int mlx4_status_to_errno(u8 status) 1265a2cc190SJeff Kirsher { 1275a2cc190SJeff Kirsher static const int trans_table[] = { 1285a2cc190SJeff Kirsher [CMD_STAT_INTERNAL_ERR] = -EIO, 1295a2cc190SJeff Kirsher [CMD_STAT_BAD_OP] = -EPERM, 1305a2cc190SJeff Kirsher [CMD_STAT_BAD_PARAM] = -EINVAL, 1315a2cc190SJeff Kirsher [CMD_STAT_BAD_SYS_STATE] = -ENXIO, 1325a2cc190SJeff Kirsher [CMD_STAT_BAD_RESOURCE] = -EBADF, 1335a2cc190SJeff Kirsher [CMD_STAT_RESOURCE_BUSY] = -EBUSY, 1345a2cc190SJeff Kirsher [CMD_STAT_EXCEED_LIM] = -ENOMEM, 1355a2cc190SJeff Kirsher [CMD_STAT_BAD_RES_STATE] = -EBADF, 1365a2cc190SJeff Kirsher [CMD_STAT_BAD_INDEX] = -EBADF, 1375a2cc190SJeff Kirsher [CMD_STAT_BAD_NVMEM] = -EFAULT, 1385a2cc190SJeff Kirsher [CMD_STAT_ICM_ERROR] = -ENFILE, 1395a2cc190SJeff Kirsher [CMD_STAT_BAD_QP_STATE] = -EINVAL, 1405a2cc190SJeff Kirsher [CMD_STAT_BAD_SEG_PARAM] = -EFAULT, 1415a2cc190SJeff Kirsher [CMD_STAT_REG_BOUND] = -EBUSY, 1425a2cc190SJeff Kirsher [CMD_STAT_LAM_NOT_PRE] = -EAGAIN, 1435a2cc190SJeff Kirsher [CMD_STAT_BAD_PKT] = -EINVAL, 1445a2cc190SJeff Kirsher [CMD_STAT_BAD_SIZE] = -ENOMEM, 1455a2cc190SJeff Kirsher [CMD_STAT_MULTI_FUNC_REQ] = -EACCES, 1465a2cc190SJeff Kirsher }; 1475a2cc190SJeff Kirsher 1485a2cc190SJeff Kirsher if (status >= ARRAY_SIZE(trans_table) || 1495a2cc190SJeff Kirsher (status != CMD_STAT_OK && trans_table[status] == 0)) 1505a2cc190SJeff Kirsher return -EIO; 1515a2cc190SJeff Kirsher 1525a2cc190SJeff Kirsher return trans_table[status]; 1535a2cc190SJeff Kirsher } 1545a2cc190SJeff Kirsher 15572be84f1SYevgeny Petrilin static u8 mlx4_errno_to_status(int errno) 15672be84f1SYevgeny Petrilin { 15772be84f1SYevgeny Petrilin switch (errno) { 15872be84f1SYevgeny Petrilin case -EPERM: 15972be84f1SYevgeny Petrilin return CMD_STAT_BAD_OP; 16072be84f1SYevgeny Petrilin case -EINVAL: 16172be84f1SYevgeny Petrilin return CMD_STAT_BAD_PARAM; 16272be84f1SYevgeny Petrilin case -ENXIO: 16372be84f1SYevgeny Petrilin return CMD_STAT_BAD_SYS_STATE; 16472be84f1SYevgeny Petrilin case -EBUSY: 16572be84f1SYevgeny Petrilin return CMD_STAT_RESOURCE_BUSY; 16672be84f1SYevgeny Petrilin case -ENOMEM: 16772be84f1SYevgeny Petrilin return CMD_STAT_EXCEED_LIM; 16872be84f1SYevgeny Petrilin case -ENFILE: 16972be84f1SYevgeny Petrilin return CMD_STAT_ICM_ERROR; 17072be84f1SYevgeny Petrilin default: 17172be84f1SYevgeny Petrilin return CMD_STAT_INTERNAL_ERR; 17272be84f1SYevgeny Petrilin } 17372be84f1SYevgeny Petrilin } 17472be84f1SYevgeny Petrilin 175e8f081aaSYevgeny Petrilin static int comm_pending(struct mlx4_dev *dev) 176e8f081aaSYevgeny Petrilin { 177e8f081aaSYevgeny Petrilin struct mlx4_priv *priv = mlx4_priv(dev); 178e8f081aaSYevgeny Petrilin u32 status = readl(&priv->mfunc.comm->slave_read); 179e8f081aaSYevgeny Petrilin 180e8f081aaSYevgeny Petrilin return (swab32(status) >> 31) != priv->cmd.comm_toggle; 181e8f081aaSYevgeny Petrilin } 182e8f081aaSYevgeny Petrilin 183e8f081aaSYevgeny Petrilin static void mlx4_comm_cmd_post(struct mlx4_dev *dev, u8 cmd, u16 param) 184e8f081aaSYevgeny Petrilin { 185e8f081aaSYevgeny Petrilin struct mlx4_priv *priv = mlx4_priv(dev); 186e8f081aaSYevgeny Petrilin u32 val; 187e8f081aaSYevgeny Petrilin 188e8f081aaSYevgeny Petrilin priv->cmd.comm_toggle ^= 1; 189e8f081aaSYevgeny Petrilin val = param | (cmd << 16) | (priv->cmd.comm_toggle << 31); 190e8f081aaSYevgeny Petrilin __raw_writel((__force u32) cpu_to_be32(val), 191e8f081aaSYevgeny Petrilin &priv->mfunc.comm->slave_write); 192e8f081aaSYevgeny Petrilin mmiowb(); 193e8f081aaSYevgeny Petrilin } 194e8f081aaSYevgeny Petrilin 195e8f081aaSYevgeny Petrilin static int mlx4_comm_cmd_poll(struct mlx4_dev *dev, u8 cmd, u16 param, 196e8f081aaSYevgeny Petrilin unsigned long timeout) 197e8f081aaSYevgeny Petrilin { 198e8f081aaSYevgeny Petrilin struct mlx4_priv *priv = mlx4_priv(dev); 199e8f081aaSYevgeny Petrilin unsigned long end; 200e8f081aaSYevgeny Petrilin int err = 0; 201e8f081aaSYevgeny Petrilin int ret_from_pending = 0; 202e8f081aaSYevgeny Petrilin 203e8f081aaSYevgeny Petrilin /* First, verify that the master reports correct status */ 204e8f081aaSYevgeny Petrilin if (comm_pending(dev)) { 205e8f081aaSYevgeny Petrilin mlx4_warn(dev, "Communication channel is not idle." 206e8f081aaSYevgeny Petrilin "my toggle is %d (cmd:0x%x)\n", 207e8f081aaSYevgeny Petrilin priv->cmd.comm_toggle, cmd); 208e8f081aaSYevgeny Petrilin return -EAGAIN; 209e8f081aaSYevgeny Petrilin } 210e8f081aaSYevgeny Petrilin 211e8f081aaSYevgeny Petrilin /* Write command */ 212e8f081aaSYevgeny Petrilin down(&priv->cmd.poll_sem); 213e8f081aaSYevgeny Petrilin mlx4_comm_cmd_post(dev, cmd, param); 214e8f081aaSYevgeny Petrilin 215e8f081aaSYevgeny Petrilin end = msecs_to_jiffies(timeout) + jiffies; 216e8f081aaSYevgeny Petrilin while (comm_pending(dev) && time_before(jiffies, end)) 217e8f081aaSYevgeny Petrilin cond_resched(); 218e8f081aaSYevgeny Petrilin ret_from_pending = comm_pending(dev); 219e8f081aaSYevgeny Petrilin if (ret_from_pending) { 220e8f081aaSYevgeny Petrilin /* check if the slave is trying to boot in the middle of 221e8f081aaSYevgeny Petrilin * FLR process. The only non-zero result in the RESET command 222e8f081aaSYevgeny Petrilin * is MLX4_DELAY_RESET_SLAVE*/ 223e8f081aaSYevgeny Petrilin if ((MLX4_COMM_CMD_RESET == cmd)) { 224e8f081aaSYevgeny Petrilin mlx4_warn(dev, "Got slave FLRed from Communication" 225e8f081aaSYevgeny Petrilin " channel (ret:0x%x)\n", ret_from_pending); 226e8f081aaSYevgeny Petrilin err = MLX4_DELAY_RESET_SLAVE; 227e8f081aaSYevgeny Petrilin } else { 228e8f081aaSYevgeny Petrilin mlx4_warn(dev, "Communication channel timed out\n"); 229e8f081aaSYevgeny Petrilin err = -ETIMEDOUT; 230e8f081aaSYevgeny Petrilin } 231e8f081aaSYevgeny Petrilin } 232e8f081aaSYevgeny Petrilin 233e8f081aaSYevgeny Petrilin up(&priv->cmd.poll_sem); 234e8f081aaSYevgeny Petrilin return err; 235e8f081aaSYevgeny Petrilin } 236e8f081aaSYevgeny Petrilin 237e8f081aaSYevgeny Petrilin static int mlx4_comm_cmd_wait(struct mlx4_dev *dev, u8 op, 238e8f081aaSYevgeny Petrilin u16 param, unsigned long timeout) 239e8f081aaSYevgeny Petrilin { 240e8f081aaSYevgeny Petrilin struct mlx4_cmd *cmd = &mlx4_priv(dev)->cmd; 241e8f081aaSYevgeny Petrilin struct mlx4_cmd_context *context; 24258a3de05SEugenia Emantayev unsigned long end; 243e8f081aaSYevgeny Petrilin int err = 0; 244e8f081aaSYevgeny Petrilin 245e8f081aaSYevgeny Petrilin down(&cmd->event_sem); 246e8f081aaSYevgeny Petrilin 247e8f081aaSYevgeny Petrilin spin_lock(&cmd->context_lock); 248e8f081aaSYevgeny Petrilin BUG_ON(cmd->free_head < 0); 249e8f081aaSYevgeny Petrilin context = &cmd->context[cmd->free_head]; 250e8f081aaSYevgeny Petrilin context->token += cmd->token_mask + 1; 251e8f081aaSYevgeny Petrilin cmd->free_head = context->next; 252e8f081aaSYevgeny Petrilin spin_unlock(&cmd->context_lock); 253e8f081aaSYevgeny Petrilin 254e8f081aaSYevgeny Petrilin init_completion(&context->done); 255e8f081aaSYevgeny Petrilin 256e8f081aaSYevgeny Petrilin mlx4_comm_cmd_post(dev, op, param); 257e8f081aaSYevgeny Petrilin 258e8f081aaSYevgeny Petrilin if (!wait_for_completion_timeout(&context->done, 259e8f081aaSYevgeny Petrilin msecs_to_jiffies(timeout))) { 260e8f081aaSYevgeny Petrilin err = -EBUSY; 261e8f081aaSYevgeny Petrilin goto out; 262e8f081aaSYevgeny Petrilin } 263e8f081aaSYevgeny Petrilin 264e8f081aaSYevgeny Petrilin err = context->result; 265e8f081aaSYevgeny Petrilin if (err && context->fw_status != CMD_STAT_MULTI_FUNC_REQ) { 266e8f081aaSYevgeny Petrilin mlx4_err(dev, "command 0x%x failed: fw status = 0x%x\n", 267e8f081aaSYevgeny Petrilin op, context->fw_status); 268e8f081aaSYevgeny Petrilin goto out; 269e8f081aaSYevgeny Petrilin } 270e8f081aaSYevgeny Petrilin 271e8f081aaSYevgeny Petrilin out: 27258a3de05SEugenia Emantayev /* wait for comm channel ready 27358a3de05SEugenia Emantayev * this is necessary for prevention the race 27458a3de05SEugenia Emantayev * when switching between event to polling mode 27558a3de05SEugenia Emantayev */ 27658a3de05SEugenia Emantayev end = msecs_to_jiffies(timeout) + jiffies; 27758a3de05SEugenia Emantayev while (comm_pending(dev) && time_before(jiffies, end)) 27858a3de05SEugenia Emantayev cond_resched(); 27958a3de05SEugenia Emantayev 280e8f081aaSYevgeny Petrilin spin_lock(&cmd->context_lock); 281e8f081aaSYevgeny Petrilin context->next = cmd->free_head; 282e8f081aaSYevgeny Petrilin cmd->free_head = context - cmd->context; 283e8f081aaSYevgeny Petrilin spin_unlock(&cmd->context_lock); 284e8f081aaSYevgeny Petrilin 285e8f081aaSYevgeny Petrilin up(&cmd->event_sem); 286e8f081aaSYevgeny Petrilin return err; 287e8f081aaSYevgeny Petrilin } 288e8f081aaSYevgeny Petrilin 289ab9c17a0SJack Morgenstein int mlx4_comm_cmd(struct mlx4_dev *dev, u8 cmd, u16 param, 290e8f081aaSYevgeny Petrilin unsigned long timeout) 291e8f081aaSYevgeny Petrilin { 292e8f081aaSYevgeny Petrilin if (mlx4_priv(dev)->cmd.use_events) 293e8f081aaSYevgeny Petrilin return mlx4_comm_cmd_wait(dev, cmd, param, timeout); 294e8f081aaSYevgeny Petrilin return mlx4_comm_cmd_poll(dev, cmd, param, timeout); 295e8f081aaSYevgeny Petrilin } 296e8f081aaSYevgeny Petrilin 2975a2cc190SJeff Kirsher static int cmd_pending(struct mlx4_dev *dev) 2985a2cc190SJeff Kirsher { 2995a2cc190SJeff Kirsher u32 status = readl(mlx4_priv(dev)->cmd.hcr + HCR_STATUS_OFFSET); 3005a2cc190SJeff Kirsher 3015a2cc190SJeff Kirsher return (status & swab32(1 << HCR_GO_BIT)) || 3025a2cc190SJeff Kirsher (mlx4_priv(dev)->cmd.toggle == 3035a2cc190SJeff Kirsher !!(status & swab32(1 << HCR_T_BIT))); 3045a2cc190SJeff Kirsher } 3055a2cc190SJeff Kirsher 3065a2cc190SJeff Kirsher static int mlx4_cmd_post(struct mlx4_dev *dev, u64 in_param, u64 out_param, 3075a2cc190SJeff Kirsher u32 in_modifier, u8 op_modifier, u16 op, u16 token, 3085a2cc190SJeff Kirsher int event) 3095a2cc190SJeff Kirsher { 3105a2cc190SJeff Kirsher struct mlx4_cmd *cmd = &mlx4_priv(dev)->cmd; 3115a2cc190SJeff Kirsher u32 __iomem *hcr = cmd->hcr; 3125a2cc190SJeff Kirsher int ret = -EAGAIN; 3135a2cc190SJeff Kirsher unsigned long end; 3145a2cc190SJeff Kirsher 3155a2cc190SJeff Kirsher mutex_lock(&cmd->hcr_mutex); 3165a2cc190SJeff Kirsher 3175a2cc190SJeff Kirsher end = jiffies; 3185a2cc190SJeff Kirsher if (event) 3195a2cc190SJeff Kirsher end += msecs_to_jiffies(GO_BIT_TIMEOUT_MSECS); 3205a2cc190SJeff Kirsher 3215a2cc190SJeff Kirsher while (cmd_pending(dev)) { 322e8f081aaSYevgeny Petrilin if (time_after_eq(jiffies, end)) { 323e8f081aaSYevgeny Petrilin mlx4_err(dev, "%s:cmd_pending failed\n", __func__); 3245a2cc190SJeff Kirsher goto out; 325e8f081aaSYevgeny Petrilin } 3265a2cc190SJeff Kirsher cond_resched(); 3275a2cc190SJeff Kirsher } 3285a2cc190SJeff Kirsher 3295a2cc190SJeff Kirsher /* 3305a2cc190SJeff Kirsher * We use writel (instead of something like memcpy_toio) 3315a2cc190SJeff Kirsher * because writes of less than 32 bits to the HCR don't work 3325a2cc190SJeff Kirsher * (and some architectures such as ia64 implement memcpy_toio 3335a2cc190SJeff Kirsher * in terms of writeb). 3345a2cc190SJeff Kirsher */ 3355a2cc190SJeff Kirsher __raw_writel((__force u32) cpu_to_be32(in_param >> 32), hcr + 0); 3365a2cc190SJeff Kirsher __raw_writel((__force u32) cpu_to_be32(in_param & 0xfffffffful), hcr + 1); 3375a2cc190SJeff Kirsher __raw_writel((__force u32) cpu_to_be32(in_modifier), hcr + 2); 3385a2cc190SJeff Kirsher __raw_writel((__force u32) cpu_to_be32(out_param >> 32), hcr + 3); 3395a2cc190SJeff Kirsher __raw_writel((__force u32) cpu_to_be32(out_param & 0xfffffffful), hcr + 4); 3405a2cc190SJeff Kirsher __raw_writel((__force u32) cpu_to_be32(token << 16), hcr + 5); 3415a2cc190SJeff Kirsher 3425a2cc190SJeff Kirsher /* __raw_writel may not order writes. */ 3435a2cc190SJeff Kirsher wmb(); 3445a2cc190SJeff Kirsher 3455a2cc190SJeff Kirsher __raw_writel((__force u32) cpu_to_be32((1 << HCR_GO_BIT) | 3465a2cc190SJeff Kirsher (cmd->toggle << HCR_T_BIT) | 3475a2cc190SJeff Kirsher (event ? (1 << HCR_E_BIT) : 0) | 3485a2cc190SJeff Kirsher (op_modifier << HCR_OPMOD_SHIFT) | 3495a2cc190SJeff Kirsher op), hcr + 6); 3505a2cc190SJeff Kirsher 3515a2cc190SJeff Kirsher /* 3525a2cc190SJeff Kirsher * Make sure that our HCR writes don't get mixed in with 3535a2cc190SJeff Kirsher * writes from another CPU starting a FW command. 3545a2cc190SJeff Kirsher */ 3555a2cc190SJeff Kirsher mmiowb(); 3565a2cc190SJeff Kirsher 3575a2cc190SJeff Kirsher cmd->toggle = cmd->toggle ^ 1; 3585a2cc190SJeff Kirsher 3595a2cc190SJeff Kirsher ret = 0; 3605a2cc190SJeff Kirsher 3615a2cc190SJeff Kirsher out: 3625a2cc190SJeff Kirsher mutex_unlock(&cmd->hcr_mutex); 3635a2cc190SJeff Kirsher return ret; 3645a2cc190SJeff Kirsher } 3655a2cc190SJeff Kirsher 366e8f081aaSYevgeny Petrilin static int mlx4_slave_cmd(struct mlx4_dev *dev, u64 in_param, u64 *out_param, 367e8f081aaSYevgeny Petrilin int out_is_imm, u32 in_modifier, u8 op_modifier, 368e8f081aaSYevgeny Petrilin u16 op, unsigned long timeout) 369e8f081aaSYevgeny Petrilin { 370e8f081aaSYevgeny Petrilin struct mlx4_priv *priv = mlx4_priv(dev); 371e8f081aaSYevgeny Petrilin struct mlx4_vhcr_cmd *vhcr = priv->mfunc.vhcr; 372e8f081aaSYevgeny Petrilin int ret; 373e8f081aaSYevgeny Petrilin 374e8f081aaSYevgeny Petrilin down(&priv->cmd.slave_sem); 375e8f081aaSYevgeny Petrilin vhcr->in_param = cpu_to_be64(in_param); 376e8f081aaSYevgeny Petrilin vhcr->out_param = out_param ? cpu_to_be64(*out_param) : 0; 377e8f081aaSYevgeny Petrilin vhcr->in_modifier = cpu_to_be32(in_modifier); 378e8f081aaSYevgeny Petrilin vhcr->opcode = cpu_to_be16((((u16) op_modifier) << 12) | (op & 0xfff)); 379e8f081aaSYevgeny Petrilin vhcr->token = cpu_to_be16(CMD_POLL_TOKEN); 380e8f081aaSYevgeny Petrilin vhcr->status = 0; 381e8f081aaSYevgeny Petrilin vhcr->flags = !!(priv->cmd.use_events) << 6; 382e8f081aaSYevgeny Petrilin if (mlx4_is_master(dev)) { 383e8f081aaSYevgeny Petrilin ret = mlx4_master_process_vhcr(dev, dev->caps.function, vhcr); 384e8f081aaSYevgeny Petrilin if (!ret) { 385e8f081aaSYevgeny Petrilin if (out_is_imm) { 386e8f081aaSYevgeny Petrilin if (out_param) 387e8f081aaSYevgeny Petrilin *out_param = 388e8f081aaSYevgeny Petrilin be64_to_cpu(vhcr->out_param); 389e8f081aaSYevgeny Petrilin else { 390e8f081aaSYevgeny Petrilin mlx4_err(dev, "response expected while" 391e8f081aaSYevgeny Petrilin "output mailbox is NULL for " 392e8f081aaSYevgeny Petrilin "command 0x%x\n", op); 39372be84f1SYevgeny Petrilin vhcr->status = CMD_STAT_BAD_PARAM; 394e8f081aaSYevgeny Petrilin } 395e8f081aaSYevgeny Petrilin } 39672be84f1SYevgeny Petrilin ret = mlx4_status_to_errno(vhcr->status); 397e8f081aaSYevgeny Petrilin } 398e8f081aaSYevgeny Petrilin } else { 399e8f081aaSYevgeny Petrilin ret = mlx4_comm_cmd(dev, MLX4_COMM_CMD_VHCR_POST, 0, 400e8f081aaSYevgeny Petrilin MLX4_COMM_TIME + timeout); 401e8f081aaSYevgeny Petrilin if (!ret) { 402e8f081aaSYevgeny Petrilin if (out_is_imm) { 403e8f081aaSYevgeny Petrilin if (out_param) 404e8f081aaSYevgeny Petrilin *out_param = 405e8f081aaSYevgeny Petrilin be64_to_cpu(vhcr->out_param); 406e8f081aaSYevgeny Petrilin else { 407e8f081aaSYevgeny Petrilin mlx4_err(dev, "response expected while" 408e8f081aaSYevgeny Petrilin "output mailbox is NULL for " 409e8f081aaSYevgeny Petrilin "command 0x%x\n", op); 41072be84f1SYevgeny Petrilin vhcr->status = CMD_STAT_BAD_PARAM; 411e8f081aaSYevgeny Petrilin } 412e8f081aaSYevgeny Petrilin } 41372be84f1SYevgeny Petrilin ret = mlx4_status_to_errno(vhcr->status); 414e8f081aaSYevgeny Petrilin } else 415e8f081aaSYevgeny Petrilin mlx4_err(dev, "failed execution of VHCR_POST command" 416e8f081aaSYevgeny Petrilin "opcode 0x%x\n", op); 417e8f081aaSYevgeny Petrilin } 418e8f081aaSYevgeny Petrilin up(&priv->cmd.slave_sem); 419e8f081aaSYevgeny Petrilin return ret; 420e8f081aaSYevgeny Petrilin } 421e8f081aaSYevgeny Petrilin 4225a2cc190SJeff Kirsher static int mlx4_cmd_poll(struct mlx4_dev *dev, u64 in_param, u64 *out_param, 4235a2cc190SJeff Kirsher int out_is_imm, u32 in_modifier, u8 op_modifier, 4245a2cc190SJeff Kirsher u16 op, unsigned long timeout) 4255a2cc190SJeff Kirsher { 4265a2cc190SJeff Kirsher struct mlx4_priv *priv = mlx4_priv(dev); 4275a2cc190SJeff Kirsher void __iomem *hcr = priv->cmd.hcr; 4285a2cc190SJeff Kirsher int err = 0; 4295a2cc190SJeff Kirsher unsigned long end; 430e8f081aaSYevgeny Petrilin u32 stat; 4315a2cc190SJeff Kirsher 4325a2cc190SJeff Kirsher down(&priv->cmd.poll_sem); 4335a2cc190SJeff Kirsher 4345a2cc190SJeff Kirsher err = mlx4_cmd_post(dev, in_param, out_param ? *out_param : 0, 4355a2cc190SJeff Kirsher in_modifier, op_modifier, op, CMD_POLL_TOKEN, 0); 4365a2cc190SJeff Kirsher if (err) 4375a2cc190SJeff Kirsher goto out; 4385a2cc190SJeff Kirsher 4395a2cc190SJeff Kirsher end = msecs_to_jiffies(timeout) + jiffies; 4405a2cc190SJeff Kirsher while (cmd_pending(dev) && time_before(jiffies, end)) 4415a2cc190SJeff Kirsher cond_resched(); 4425a2cc190SJeff Kirsher 4435a2cc190SJeff Kirsher if (cmd_pending(dev)) { 4445a2cc190SJeff Kirsher err = -ETIMEDOUT; 4455a2cc190SJeff Kirsher goto out; 4465a2cc190SJeff Kirsher } 4475a2cc190SJeff Kirsher 4485a2cc190SJeff Kirsher if (out_is_imm) 4495a2cc190SJeff Kirsher *out_param = 4505a2cc190SJeff Kirsher (u64) be32_to_cpu((__force __be32) 4515a2cc190SJeff Kirsher __raw_readl(hcr + HCR_OUT_PARAM_OFFSET)) << 32 | 4525a2cc190SJeff Kirsher (u64) be32_to_cpu((__force __be32) 4535a2cc190SJeff Kirsher __raw_readl(hcr + HCR_OUT_PARAM_OFFSET + 4)); 454e8f081aaSYevgeny Petrilin stat = be32_to_cpu((__force __be32) 455e8f081aaSYevgeny Petrilin __raw_readl(hcr + HCR_STATUS_OFFSET)) >> 24; 456e8f081aaSYevgeny Petrilin err = mlx4_status_to_errno(stat); 457e8f081aaSYevgeny Petrilin if (err) 458e8f081aaSYevgeny Petrilin mlx4_err(dev, "command 0x%x failed: fw status = 0x%x\n", 459e8f081aaSYevgeny Petrilin op, stat); 4605a2cc190SJeff Kirsher 4615a2cc190SJeff Kirsher out: 4625a2cc190SJeff Kirsher up(&priv->cmd.poll_sem); 4635a2cc190SJeff Kirsher return err; 4645a2cc190SJeff Kirsher } 4655a2cc190SJeff Kirsher 4665a2cc190SJeff Kirsher void mlx4_cmd_event(struct mlx4_dev *dev, u16 token, u8 status, u64 out_param) 4675a2cc190SJeff Kirsher { 4685a2cc190SJeff Kirsher struct mlx4_priv *priv = mlx4_priv(dev); 4695a2cc190SJeff Kirsher struct mlx4_cmd_context *context = 4705a2cc190SJeff Kirsher &priv->cmd.context[token & priv->cmd.token_mask]; 4715a2cc190SJeff Kirsher 4725a2cc190SJeff Kirsher /* previously timed out command completing at long last */ 4735a2cc190SJeff Kirsher if (token != context->token) 4745a2cc190SJeff Kirsher return; 4755a2cc190SJeff Kirsher 476e8f081aaSYevgeny Petrilin context->fw_status = status; 4775a2cc190SJeff Kirsher context->result = mlx4_status_to_errno(status); 4785a2cc190SJeff Kirsher context->out_param = out_param; 4795a2cc190SJeff Kirsher 4805a2cc190SJeff Kirsher complete(&context->done); 4815a2cc190SJeff Kirsher } 4825a2cc190SJeff Kirsher 4835a2cc190SJeff Kirsher static int mlx4_cmd_wait(struct mlx4_dev *dev, u64 in_param, u64 *out_param, 4845a2cc190SJeff Kirsher int out_is_imm, u32 in_modifier, u8 op_modifier, 4855a2cc190SJeff Kirsher u16 op, unsigned long timeout) 4865a2cc190SJeff Kirsher { 4875a2cc190SJeff Kirsher struct mlx4_cmd *cmd = &mlx4_priv(dev)->cmd; 4885a2cc190SJeff Kirsher struct mlx4_cmd_context *context; 4895a2cc190SJeff Kirsher int err = 0; 4905a2cc190SJeff Kirsher 4915a2cc190SJeff Kirsher down(&cmd->event_sem); 4925a2cc190SJeff Kirsher 4935a2cc190SJeff Kirsher spin_lock(&cmd->context_lock); 4945a2cc190SJeff Kirsher BUG_ON(cmd->free_head < 0); 4955a2cc190SJeff Kirsher context = &cmd->context[cmd->free_head]; 4965a2cc190SJeff Kirsher context->token += cmd->token_mask + 1; 4975a2cc190SJeff Kirsher cmd->free_head = context->next; 4985a2cc190SJeff Kirsher spin_unlock(&cmd->context_lock); 4995a2cc190SJeff Kirsher 5005a2cc190SJeff Kirsher init_completion(&context->done); 5015a2cc190SJeff Kirsher 5025a2cc190SJeff Kirsher mlx4_cmd_post(dev, in_param, out_param ? *out_param : 0, 5035a2cc190SJeff Kirsher in_modifier, op_modifier, op, context->token, 1); 5045a2cc190SJeff Kirsher 505e8f081aaSYevgeny Petrilin if (!wait_for_completion_timeout(&context->done, 506e8f081aaSYevgeny Petrilin msecs_to_jiffies(timeout))) { 5075a2cc190SJeff Kirsher err = -EBUSY; 5085a2cc190SJeff Kirsher goto out; 5095a2cc190SJeff Kirsher } 5105a2cc190SJeff Kirsher 5115a2cc190SJeff Kirsher err = context->result; 512e8f081aaSYevgeny Petrilin if (err) { 513e8f081aaSYevgeny Petrilin mlx4_err(dev, "command 0x%x failed: fw status = 0x%x\n", 514e8f081aaSYevgeny Petrilin op, context->fw_status); 5155a2cc190SJeff Kirsher goto out; 516e8f081aaSYevgeny Petrilin } 5175a2cc190SJeff Kirsher 5185a2cc190SJeff Kirsher if (out_is_imm) 5195a2cc190SJeff Kirsher *out_param = context->out_param; 5205a2cc190SJeff Kirsher 5215a2cc190SJeff Kirsher out: 5225a2cc190SJeff Kirsher spin_lock(&cmd->context_lock); 5235a2cc190SJeff Kirsher context->next = cmd->free_head; 5245a2cc190SJeff Kirsher cmd->free_head = context - cmd->context; 5255a2cc190SJeff Kirsher spin_unlock(&cmd->context_lock); 5265a2cc190SJeff Kirsher 5275a2cc190SJeff Kirsher up(&cmd->event_sem); 5285a2cc190SJeff Kirsher return err; 5295a2cc190SJeff Kirsher } 5305a2cc190SJeff Kirsher 5315a2cc190SJeff Kirsher int __mlx4_cmd(struct mlx4_dev *dev, u64 in_param, u64 *out_param, 5325a2cc190SJeff Kirsher int out_is_imm, u32 in_modifier, u8 op_modifier, 533f9baff50SJack Morgenstein u16 op, unsigned long timeout, int native) 5345a2cc190SJeff Kirsher { 535e8f081aaSYevgeny Petrilin if (!mlx4_is_mfunc(dev) || (native && mlx4_is_master(dev))) { 5365a2cc190SJeff Kirsher if (mlx4_priv(dev)->cmd.use_events) 537e8f081aaSYevgeny Petrilin return mlx4_cmd_wait(dev, in_param, out_param, 538e8f081aaSYevgeny Petrilin out_is_imm, in_modifier, 539e8f081aaSYevgeny Petrilin op_modifier, op, timeout); 5405a2cc190SJeff Kirsher else 541e8f081aaSYevgeny Petrilin return mlx4_cmd_poll(dev, in_param, out_param, 542e8f081aaSYevgeny Petrilin out_is_imm, in_modifier, 543e8f081aaSYevgeny Petrilin op_modifier, op, timeout); 544e8f081aaSYevgeny Petrilin } 545e8f081aaSYevgeny Petrilin return mlx4_slave_cmd(dev, in_param, out_param, out_is_imm, 5465a2cc190SJeff Kirsher in_modifier, op_modifier, op, timeout); 5475a2cc190SJeff Kirsher } 5485a2cc190SJeff Kirsher EXPORT_SYMBOL_GPL(__mlx4_cmd); 5495a2cc190SJeff Kirsher 550e8f081aaSYevgeny Petrilin 551e8f081aaSYevgeny Petrilin static int mlx4_ARM_COMM_CHANNEL(struct mlx4_dev *dev) 552e8f081aaSYevgeny Petrilin { 553e8f081aaSYevgeny Petrilin return mlx4_cmd(dev, 0, 0, 0, MLX4_CMD_ARM_COMM_CHANNEL, 554e8f081aaSYevgeny Petrilin MLX4_CMD_TIME_CLASS_B, MLX4_CMD_NATIVE); 555e8f081aaSYevgeny Petrilin } 556e8f081aaSYevgeny Petrilin 557e8f081aaSYevgeny Petrilin static int mlx4_ACCESS_MEM(struct mlx4_dev *dev, u64 master_addr, 558e8f081aaSYevgeny Petrilin int slave, u64 slave_addr, 559e8f081aaSYevgeny Petrilin int size, int is_read) 560e8f081aaSYevgeny Petrilin { 561e8f081aaSYevgeny Petrilin u64 in_param; 562e8f081aaSYevgeny Petrilin u64 out_param; 563e8f081aaSYevgeny Petrilin 564e8f081aaSYevgeny Petrilin if ((slave_addr & 0xfff) | (master_addr & 0xfff) | 565e8f081aaSYevgeny Petrilin (slave & ~0x7f) | (size & 0xff)) { 566e8f081aaSYevgeny Petrilin mlx4_err(dev, "Bad access mem params - slave_addr:0x%llx " 567e8f081aaSYevgeny Petrilin "master_addr:0x%llx slave_id:%d size:%d\n", 568e8f081aaSYevgeny Petrilin slave_addr, master_addr, slave, size); 569e8f081aaSYevgeny Petrilin return -EINVAL; 570e8f081aaSYevgeny Petrilin } 571e8f081aaSYevgeny Petrilin 572e8f081aaSYevgeny Petrilin if (is_read) { 573e8f081aaSYevgeny Petrilin in_param = (u64) slave | slave_addr; 574e8f081aaSYevgeny Petrilin out_param = (u64) dev->caps.function | master_addr; 575e8f081aaSYevgeny Petrilin } else { 576e8f081aaSYevgeny Petrilin in_param = (u64) dev->caps.function | master_addr; 577e8f081aaSYevgeny Petrilin out_param = (u64) slave | slave_addr; 578e8f081aaSYevgeny Petrilin } 579e8f081aaSYevgeny Petrilin 580e8f081aaSYevgeny Petrilin return mlx4_cmd_imm(dev, in_param, &out_param, size, 0, 581e8f081aaSYevgeny Petrilin MLX4_CMD_ACCESS_MEM, 582e8f081aaSYevgeny Petrilin MLX4_CMD_TIME_CLASS_A, MLX4_CMD_NATIVE); 583e8f081aaSYevgeny Petrilin } 584e8f081aaSYevgeny Petrilin 585e8f081aaSYevgeny Petrilin int mlx4_DMA_wrapper(struct mlx4_dev *dev, int slave, 586e8f081aaSYevgeny Petrilin struct mlx4_vhcr *vhcr, 587e8f081aaSYevgeny Petrilin struct mlx4_cmd_mailbox *inbox, 588e8f081aaSYevgeny Petrilin struct mlx4_cmd_mailbox *outbox, 589e8f081aaSYevgeny Petrilin struct mlx4_cmd_info *cmd) 590e8f081aaSYevgeny Petrilin { 591e8f081aaSYevgeny Petrilin u64 in_param; 592e8f081aaSYevgeny Petrilin u64 out_param; 593e8f081aaSYevgeny Petrilin int err; 594e8f081aaSYevgeny Petrilin 595e8f081aaSYevgeny Petrilin in_param = cmd->has_inbox ? (u64) inbox->dma : vhcr->in_param; 596e8f081aaSYevgeny Petrilin out_param = cmd->has_outbox ? (u64) outbox->dma : vhcr->out_param; 597e8f081aaSYevgeny Petrilin if (cmd->encode_slave_id) { 598e8f081aaSYevgeny Petrilin in_param &= 0xffffffffffffff00ll; 599e8f081aaSYevgeny Petrilin in_param |= slave; 600e8f081aaSYevgeny Petrilin } 601e8f081aaSYevgeny Petrilin 602e8f081aaSYevgeny Petrilin err = __mlx4_cmd(dev, in_param, &out_param, cmd->out_is_imm, 603e8f081aaSYevgeny Petrilin vhcr->in_modifier, vhcr->op_modifier, vhcr->op, 604e8f081aaSYevgeny Petrilin MLX4_CMD_TIME_CLASS_A, MLX4_CMD_NATIVE); 605e8f081aaSYevgeny Petrilin 606e8f081aaSYevgeny Petrilin if (cmd->out_is_imm) 607e8f081aaSYevgeny Petrilin vhcr->out_param = out_param; 608e8f081aaSYevgeny Petrilin 609e8f081aaSYevgeny Petrilin return err; 610e8f081aaSYevgeny Petrilin } 611e8f081aaSYevgeny Petrilin 612e8f081aaSYevgeny Petrilin static struct mlx4_cmd_info cmd_info[] = { 613e8f081aaSYevgeny Petrilin { 614e8f081aaSYevgeny Petrilin .opcode = MLX4_CMD_QUERY_FW, 615e8f081aaSYevgeny Petrilin .has_inbox = false, 616e8f081aaSYevgeny Petrilin .has_outbox = true, 617e8f081aaSYevgeny Petrilin .out_is_imm = false, 618e8f081aaSYevgeny Petrilin .encode_slave_id = false, 619e8f081aaSYevgeny Petrilin .verify = NULL, 620e8f081aaSYevgeny Petrilin .wrapper = NULL 621e8f081aaSYevgeny Petrilin }, 622e8f081aaSYevgeny Petrilin { 623e8f081aaSYevgeny Petrilin .opcode = MLX4_CMD_QUERY_HCA, 624e8f081aaSYevgeny Petrilin .has_inbox = false, 625e8f081aaSYevgeny Petrilin .has_outbox = true, 626e8f081aaSYevgeny Petrilin .out_is_imm = false, 627e8f081aaSYevgeny Petrilin .encode_slave_id = false, 628e8f081aaSYevgeny Petrilin .verify = NULL, 629e8f081aaSYevgeny Petrilin .wrapper = NULL 630e8f081aaSYevgeny Petrilin }, 631e8f081aaSYevgeny Petrilin { 632e8f081aaSYevgeny Petrilin .opcode = MLX4_CMD_QUERY_DEV_CAP, 633e8f081aaSYevgeny Petrilin .has_inbox = false, 634e8f081aaSYevgeny Petrilin .has_outbox = true, 635e8f081aaSYevgeny Petrilin .out_is_imm = false, 636e8f081aaSYevgeny Petrilin .encode_slave_id = false, 637e8f081aaSYevgeny Petrilin .verify = NULL, 638e8f081aaSYevgeny Petrilin .wrapper = NULL 639e8f081aaSYevgeny Petrilin }, 640c82e9aa0SEli Cohen { 641c82e9aa0SEli Cohen .opcode = MLX4_CMD_QUERY_FUNC_CAP, 642c82e9aa0SEli Cohen .has_inbox = false, 643c82e9aa0SEli Cohen .has_outbox = true, 644c82e9aa0SEli Cohen .out_is_imm = false, 645c82e9aa0SEli Cohen .encode_slave_id = false, 646c82e9aa0SEli Cohen .verify = NULL, 647c82e9aa0SEli Cohen .wrapper = mlx4_QUERY_FUNC_CAP_wrapper 648c82e9aa0SEli Cohen }, 649c82e9aa0SEli Cohen { 650c82e9aa0SEli Cohen .opcode = MLX4_CMD_QUERY_ADAPTER, 651c82e9aa0SEli Cohen .has_inbox = false, 652c82e9aa0SEli Cohen .has_outbox = true, 653c82e9aa0SEli Cohen .out_is_imm = false, 654c82e9aa0SEli Cohen .encode_slave_id = false, 655c82e9aa0SEli Cohen .verify = NULL, 656c82e9aa0SEli Cohen .wrapper = NULL 657c82e9aa0SEli Cohen }, 658c82e9aa0SEli Cohen { 659c82e9aa0SEli Cohen .opcode = MLX4_CMD_INIT_PORT, 660c82e9aa0SEli Cohen .has_inbox = false, 661c82e9aa0SEli Cohen .has_outbox = false, 662c82e9aa0SEli Cohen .out_is_imm = false, 663c82e9aa0SEli Cohen .encode_slave_id = false, 664c82e9aa0SEli Cohen .verify = NULL, 665c82e9aa0SEli Cohen .wrapper = mlx4_INIT_PORT_wrapper 666c82e9aa0SEli Cohen }, 667c82e9aa0SEli Cohen { 668c82e9aa0SEli Cohen .opcode = MLX4_CMD_CLOSE_PORT, 669c82e9aa0SEli Cohen .has_inbox = false, 670c82e9aa0SEli Cohen .has_outbox = false, 671c82e9aa0SEli Cohen .out_is_imm = false, 672c82e9aa0SEli Cohen .encode_slave_id = false, 673c82e9aa0SEli Cohen .verify = NULL, 674c82e9aa0SEli Cohen .wrapper = mlx4_CLOSE_PORT_wrapper 675c82e9aa0SEli Cohen }, 676c82e9aa0SEli Cohen { 677c82e9aa0SEli Cohen .opcode = MLX4_CMD_QUERY_PORT, 678c82e9aa0SEli Cohen .has_inbox = false, 679c82e9aa0SEli Cohen .has_outbox = true, 680c82e9aa0SEli Cohen .out_is_imm = false, 681c82e9aa0SEli Cohen .encode_slave_id = false, 682c82e9aa0SEli Cohen .verify = NULL, 683c82e9aa0SEli Cohen .wrapper = mlx4_QUERY_PORT_wrapper 684c82e9aa0SEli Cohen }, 685c82e9aa0SEli Cohen { 686ffe455adSEugenia Emantayev .opcode = MLX4_CMD_SET_PORT, 687ffe455adSEugenia Emantayev .has_inbox = true, 688ffe455adSEugenia Emantayev .has_outbox = false, 689ffe455adSEugenia Emantayev .out_is_imm = false, 690ffe455adSEugenia Emantayev .encode_slave_id = false, 691ffe455adSEugenia Emantayev .verify = NULL, 692ffe455adSEugenia Emantayev .wrapper = mlx4_SET_PORT_wrapper 693ffe455adSEugenia Emantayev }, 694ffe455adSEugenia Emantayev { 695c82e9aa0SEli Cohen .opcode = MLX4_CMD_MAP_EQ, 696c82e9aa0SEli Cohen .has_inbox = false, 697c82e9aa0SEli Cohen .has_outbox = false, 698c82e9aa0SEli Cohen .out_is_imm = false, 699c82e9aa0SEli Cohen .encode_slave_id = false, 700c82e9aa0SEli Cohen .verify = NULL, 701c82e9aa0SEli Cohen .wrapper = mlx4_MAP_EQ_wrapper 702c82e9aa0SEli Cohen }, 703c82e9aa0SEli Cohen { 704c82e9aa0SEli Cohen .opcode = MLX4_CMD_SW2HW_EQ, 705c82e9aa0SEli Cohen .has_inbox = true, 706c82e9aa0SEli Cohen .has_outbox = false, 707c82e9aa0SEli Cohen .out_is_imm = false, 708c82e9aa0SEli Cohen .encode_slave_id = true, 709c82e9aa0SEli Cohen .verify = NULL, 710c82e9aa0SEli Cohen .wrapper = mlx4_SW2HW_EQ_wrapper 711c82e9aa0SEli Cohen }, 712c82e9aa0SEli Cohen { 713c82e9aa0SEli Cohen .opcode = MLX4_CMD_HW_HEALTH_CHECK, 714c82e9aa0SEli Cohen .has_inbox = false, 715c82e9aa0SEli Cohen .has_outbox = false, 716c82e9aa0SEli Cohen .out_is_imm = false, 717c82e9aa0SEli Cohen .encode_slave_id = false, 718c82e9aa0SEli Cohen .verify = NULL, 719c82e9aa0SEli Cohen .wrapper = NULL 720c82e9aa0SEli Cohen }, 721c82e9aa0SEli Cohen { 722c82e9aa0SEli Cohen .opcode = MLX4_CMD_NOP, 723c82e9aa0SEli Cohen .has_inbox = false, 724c82e9aa0SEli Cohen .has_outbox = false, 725c82e9aa0SEli Cohen .out_is_imm = false, 726c82e9aa0SEli Cohen .encode_slave_id = false, 727c82e9aa0SEli Cohen .verify = NULL, 728c82e9aa0SEli Cohen .wrapper = NULL 729c82e9aa0SEli Cohen }, 730c82e9aa0SEli Cohen { 731c82e9aa0SEli Cohen .opcode = MLX4_CMD_ALLOC_RES, 732c82e9aa0SEli Cohen .has_inbox = false, 733c82e9aa0SEli Cohen .has_outbox = false, 734c82e9aa0SEli Cohen .out_is_imm = true, 735c82e9aa0SEli Cohen .encode_slave_id = false, 736c82e9aa0SEli Cohen .verify = NULL, 737c82e9aa0SEli Cohen .wrapper = mlx4_ALLOC_RES_wrapper 738c82e9aa0SEli Cohen }, 739c82e9aa0SEli Cohen { 740c82e9aa0SEli Cohen .opcode = MLX4_CMD_FREE_RES, 741c82e9aa0SEli Cohen .has_inbox = false, 742c82e9aa0SEli Cohen .has_outbox = false, 743c82e9aa0SEli Cohen .out_is_imm = false, 744c82e9aa0SEli Cohen .encode_slave_id = false, 745c82e9aa0SEli Cohen .verify = NULL, 746c82e9aa0SEli Cohen .wrapper = mlx4_FREE_RES_wrapper 747c82e9aa0SEli Cohen }, 748c82e9aa0SEli Cohen { 749c82e9aa0SEli Cohen .opcode = MLX4_CMD_SW2HW_MPT, 750c82e9aa0SEli Cohen .has_inbox = true, 751c82e9aa0SEli Cohen .has_outbox = false, 752c82e9aa0SEli Cohen .out_is_imm = false, 753c82e9aa0SEli Cohen .encode_slave_id = true, 754c82e9aa0SEli Cohen .verify = NULL, 755c82e9aa0SEli Cohen .wrapper = mlx4_SW2HW_MPT_wrapper 756c82e9aa0SEli Cohen }, 757c82e9aa0SEli Cohen { 758c82e9aa0SEli Cohen .opcode = MLX4_CMD_QUERY_MPT, 759c82e9aa0SEli Cohen .has_inbox = false, 760c82e9aa0SEli Cohen .has_outbox = true, 761c82e9aa0SEli Cohen .out_is_imm = false, 762c82e9aa0SEli Cohen .encode_slave_id = false, 763c82e9aa0SEli Cohen .verify = NULL, 764c82e9aa0SEli Cohen .wrapper = mlx4_QUERY_MPT_wrapper 765c82e9aa0SEli Cohen }, 766c82e9aa0SEli Cohen { 767c82e9aa0SEli Cohen .opcode = MLX4_CMD_HW2SW_MPT, 768c82e9aa0SEli Cohen .has_inbox = false, 769c82e9aa0SEli Cohen .has_outbox = false, 770c82e9aa0SEli Cohen .out_is_imm = false, 771c82e9aa0SEli Cohen .encode_slave_id = false, 772c82e9aa0SEli Cohen .verify = NULL, 773c82e9aa0SEli Cohen .wrapper = mlx4_HW2SW_MPT_wrapper 774c82e9aa0SEli Cohen }, 775c82e9aa0SEli Cohen { 776c82e9aa0SEli Cohen .opcode = MLX4_CMD_READ_MTT, 777c82e9aa0SEli Cohen .has_inbox = false, 778c82e9aa0SEli Cohen .has_outbox = true, 779c82e9aa0SEli Cohen .out_is_imm = false, 780c82e9aa0SEli Cohen .encode_slave_id = false, 781c82e9aa0SEli Cohen .verify = NULL, 782c82e9aa0SEli Cohen .wrapper = NULL 783c82e9aa0SEli Cohen }, 784c82e9aa0SEli Cohen { 785c82e9aa0SEli Cohen .opcode = MLX4_CMD_WRITE_MTT, 786c82e9aa0SEli Cohen .has_inbox = true, 787c82e9aa0SEli Cohen .has_outbox = false, 788c82e9aa0SEli Cohen .out_is_imm = false, 789c82e9aa0SEli Cohen .encode_slave_id = false, 790c82e9aa0SEli Cohen .verify = NULL, 791c82e9aa0SEli Cohen .wrapper = mlx4_WRITE_MTT_wrapper 792c82e9aa0SEli Cohen }, 793c82e9aa0SEli Cohen { 794c82e9aa0SEli Cohen .opcode = MLX4_CMD_SYNC_TPT, 795c82e9aa0SEli Cohen .has_inbox = true, 796c82e9aa0SEli Cohen .has_outbox = false, 797c82e9aa0SEli Cohen .out_is_imm = false, 798c82e9aa0SEli Cohen .encode_slave_id = false, 799c82e9aa0SEli Cohen .verify = NULL, 800c82e9aa0SEli Cohen .wrapper = NULL 801c82e9aa0SEli Cohen }, 802c82e9aa0SEli Cohen { 803c82e9aa0SEli Cohen .opcode = MLX4_CMD_HW2SW_EQ, 804c82e9aa0SEli Cohen .has_inbox = false, 805c82e9aa0SEli Cohen .has_outbox = true, 806c82e9aa0SEli Cohen .out_is_imm = false, 807c82e9aa0SEli Cohen .encode_slave_id = true, 808c82e9aa0SEli Cohen .verify = NULL, 809c82e9aa0SEli Cohen .wrapper = mlx4_HW2SW_EQ_wrapper 810c82e9aa0SEli Cohen }, 811c82e9aa0SEli Cohen { 812c82e9aa0SEli Cohen .opcode = MLX4_CMD_QUERY_EQ, 813c82e9aa0SEli Cohen .has_inbox = false, 814c82e9aa0SEli Cohen .has_outbox = true, 815c82e9aa0SEli Cohen .out_is_imm = false, 816c82e9aa0SEli Cohen .encode_slave_id = true, 817c82e9aa0SEli Cohen .verify = NULL, 818c82e9aa0SEli Cohen .wrapper = mlx4_QUERY_EQ_wrapper 819c82e9aa0SEli Cohen }, 820c82e9aa0SEli Cohen { 821c82e9aa0SEli Cohen .opcode = MLX4_CMD_SW2HW_CQ, 822c82e9aa0SEli Cohen .has_inbox = true, 823c82e9aa0SEli Cohen .has_outbox = false, 824c82e9aa0SEli Cohen .out_is_imm = false, 825c82e9aa0SEli Cohen .encode_slave_id = true, 826c82e9aa0SEli Cohen .verify = NULL, 827c82e9aa0SEli Cohen .wrapper = mlx4_SW2HW_CQ_wrapper 828c82e9aa0SEli Cohen }, 829c82e9aa0SEli Cohen { 830c82e9aa0SEli Cohen .opcode = MLX4_CMD_HW2SW_CQ, 831c82e9aa0SEli Cohen .has_inbox = false, 832c82e9aa0SEli Cohen .has_outbox = false, 833c82e9aa0SEli Cohen .out_is_imm = false, 834c82e9aa0SEli Cohen .encode_slave_id = false, 835c82e9aa0SEli Cohen .verify = NULL, 836c82e9aa0SEli Cohen .wrapper = mlx4_HW2SW_CQ_wrapper 837c82e9aa0SEli Cohen }, 838c82e9aa0SEli Cohen { 839c82e9aa0SEli Cohen .opcode = MLX4_CMD_QUERY_CQ, 840c82e9aa0SEli Cohen .has_inbox = false, 841c82e9aa0SEli Cohen .has_outbox = true, 842c82e9aa0SEli Cohen .out_is_imm = false, 843c82e9aa0SEli Cohen .encode_slave_id = false, 844c82e9aa0SEli Cohen .verify = NULL, 845c82e9aa0SEli Cohen .wrapper = mlx4_QUERY_CQ_wrapper 846c82e9aa0SEli Cohen }, 847c82e9aa0SEli Cohen { 848c82e9aa0SEli Cohen .opcode = MLX4_CMD_MODIFY_CQ, 849c82e9aa0SEli Cohen .has_inbox = true, 850c82e9aa0SEli Cohen .has_outbox = false, 851c82e9aa0SEli Cohen .out_is_imm = true, 852c82e9aa0SEli Cohen .encode_slave_id = false, 853c82e9aa0SEli Cohen .verify = NULL, 854c82e9aa0SEli Cohen .wrapper = mlx4_MODIFY_CQ_wrapper 855c82e9aa0SEli Cohen }, 856c82e9aa0SEli Cohen { 857c82e9aa0SEli Cohen .opcode = MLX4_CMD_SW2HW_SRQ, 858c82e9aa0SEli Cohen .has_inbox = true, 859c82e9aa0SEli Cohen .has_outbox = false, 860c82e9aa0SEli Cohen .out_is_imm = false, 861c82e9aa0SEli Cohen .encode_slave_id = true, 862c82e9aa0SEli Cohen .verify = NULL, 863c82e9aa0SEli Cohen .wrapper = mlx4_SW2HW_SRQ_wrapper 864c82e9aa0SEli Cohen }, 865c82e9aa0SEli Cohen { 866c82e9aa0SEli Cohen .opcode = MLX4_CMD_HW2SW_SRQ, 867c82e9aa0SEli Cohen .has_inbox = false, 868c82e9aa0SEli Cohen .has_outbox = false, 869c82e9aa0SEli Cohen .out_is_imm = false, 870c82e9aa0SEli Cohen .encode_slave_id = false, 871c82e9aa0SEli Cohen .verify = NULL, 872c82e9aa0SEli Cohen .wrapper = mlx4_HW2SW_SRQ_wrapper 873c82e9aa0SEli Cohen }, 874c82e9aa0SEli Cohen { 875c82e9aa0SEli Cohen .opcode = MLX4_CMD_QUERY_SRQ, 876c82e9aa0SEli Cohen .has_inbox = false, 877c82e9aa0SEli Cohen .has_outbox = true, 878c82e9aa0SEli Cohen .out_is_imm = false, 879c82e9aa0SEli Cohen .encode_slave_id = false, 880c82e9aa0SEli Cohen .verify = NULL, 881c82e9aa0SEli Cohen .wrapper = mlx4_QUERY_SRQ_wrapper 882c82e9aa0SEli Cohen }, 883c82e9aa0SEli Cohen { 884c82e9aa0SEli Cohen .opcode = MLX4_CMD_ARM_SRQ, 885c82e9aa0SEli Cohen .has_inbox = false, 886c82e9aa0SEli Cohen .has_outbox = false, 887c82e9aa0SEli Cohen .out_is_imm = false, 888c82e9aa0SEli Cohen .encode_slave_id = false, 889c82e9aa0SEli Cohen .verify = NULL, 890c82e9aa0SEli Cohen .wrapper = mlx4_ARM_SRQ_wrapper 891c82e9aa0SEli Cohen }, 892c82e9aa0SEli Cohen { 893c82e9aa0SEli Cohen .opcode = MLX4_CMD_RST2INIT_QP, 894c82e9aa0SEli Cohen .has_inbox = true, 895c82e9aa0SEli Cohen .has_outbox = false, 896c82e9aa0SEli Cohen .out_is_imm = false, 897c82e9aa0SEli Cohen .encode_slave_id = true, 898c82e9aa0SEli Cohen .verify = NULL, 899c82e9aa0SEli Cohen .wrapper = mlx4_RST2INIT_QP_wrapper 900c82e9aa0SEli Cohen }, 901c82e9aa0SEli Cohen { 902c82e9aa0SEli Cohen .opcode = MLX4_CMD_INIT2INIT_QP, 903c82e9aa0SEli Cohen .has_inbox = true, 904c82e9aa0SEli Cohen .has_outbox = false, 905c82e9aa0SEli Cohen .out_is_imm = false, 906c82e9aa0SEli Cohen .encode_slave_id = false, 907c82e9aa0SEli Cohen .verify = NULL, 908c82e9aa0SEli Cohen .wrapper = mlx4_GEN_QP_wrapper 909c82e9aa0SEli Cohen }, 910c82e9aa0SEli Cohen { 911c82e9aa0SEli Cohen .opcode = MLX4_CMD_INIT2RTR_QP, 912c82e9aa0SEli Cohen .has_inbox = true, 913c82e9aa0SEli Cohen .has_outbox = false, 914c82e9aa0SEli Cohen .out_is_imm = false, 915c82e9aa0SEli Cohen .encode_slave_id = false, 916c82e9aa0SEli Cohen .verify = NULL, 917c82e9aa0SEli Cohen .wrapper = mlx4_INIT2RTR_QP_wrapper 918c82e9aa0SEli Cohen }, 919c82e9aa0SEli Cohen { 920c82e9aa0SEli Cohen .opcode = MLX4_CMD_RTR2RTS_QP, 921c82e9aa0SEli Cohen .has_inbox = true, 922c82e9aa0SEli Cohen .has_outbox = false, 923c82e9aa0SEli Cohen .out_is_imm = false, 924c82e9aa0SEli Cohen .encode_slave_id = false, 925c82e9aa0SEli Cohen .verify = NULL, 926c82e9aa0SEli Cohen .wrapper = mlx4_GEN_QP_wrapper 927c82e9aa0SEli Cohen }, 928c82e9aa0SEli Cohen { 929c82e9aa0SEli Cohen .opcode = MLX4_CMD_RTS2RTS_QP, 930c82e9aa0SEli Cohen .has_inbox = true, 931c82e9aa0SEli Cohen .has_outbox = false, 932c82e9aa0SEli Cohen .out_is_imm = false, 933c82e9aa0SEli Cohen .encode_slave_id = false, 934c82e9aa0SEli Cohen .verify = NULL, 935c82e9aa0SEli Cohen .wrapper = mlx4_GEN_QP_wrapper 936c82e9aa0SEli Cohen }, 937c82e9aa0SEli Cohen { 938c82e9aa0SEli Cohen .opcode = MLX4_CMD_SQERR2RTS_QP, 939c82e9aa0SEli Cohen .has_inbox = true, 940c82e9aa0SEli Cohen .has_outbox = false, 941c82e9aa0SEli Cohen .out_is_imm = false, 942c82e9aa0SEli Cohen .encode_slave_id = false, 943c82e9aa0SEli Cohen .verify = NULL, 944c82e9aa0SEli Cohen .wrapper = mlx4_GEN_QP_wrapper 945c82e9aa0SEli Cohen }, 946c82e9aa0SEli Cohen { 947c82e9aa0SEli Cohen .opcode = MLX4_CMD_2ERR_QP, 948c82e9aa0SEli Cohen .has_inbox = false, 949c82e9aa0SEli Cohen .has_outbox = false, 950c82e9aa0SEli Cohen .out_is_imm = false, 951c82e9aa0SEli Cohen .encode_slave_id = false, 952c82e9aa0SEli Cohen .verify = NULL, 953c82e9aa0SEli Cohen .wrapper = mlx4_GEN_QP_wrapper 954c82e9aa0SEli Cohen }, 955c82e9aa0SEli Cohen { 956c82e9aa0SEli Cohen .opcode = MLX4_CMD_RTS2SQD_QP, 957c82e9aa0SEli Cohen .has_inbox = false, 958c82e9aa0SEli Cohen .has_outbox = false, 959c82e9aa0SEli Cohen .out_is_imm = false, 960c82e9aa0SEli Cohen .encode_slave_id = false, 961c82e9aa0SEli Cohen .verify = NULL, 962c82e9aa0SEli Cohen .wrapper = mlx4_GEN_QP_wrapper 963c82e9aa0SEli Cohen }, 964c82e9aa0SEli Cohen { 965c82e9aa0SEli Cohen .opcode = MLX4_CMD_SQD2SQD_QP, 966c82e9aa0SEli Cohen .has_inbox = true, 967c82e9aa0SEli Cohen .has_outbox = false, 968c82e9aa0SEli Cohen .out_is_imm = false, 969c82e9aa0SEli Cohen .encode_slave_id = false, 970c82e9aa0SEli Cohen .verify = NULL, 971c82e9aa0SEli Cohen .wrapper = mlx4_GEN_QP_wrapper 972c82e9aa0SEli Cohen }, 973c82e9aa0SEli Cohen { 974c82e9aa0SEli Cohen .opcode = MLX4_CMD_SQD2RTS_QP, 975c82e9aa0SEli Cohen .has_inbox = true, 976c82e9aa0SEli Cohen .has_outbox = false, 977c82e9aa0SEli Cohen .out_is_imm = false, 978c82e9aa0SEli Cohen .encode_slave_id = false, 979c82e9aa0SEli Cohen .verify = NULL, 980c82e9aa0SEli Cohen .wrapper = mlx4_GEN_QP_wrapper 981c82e9aa0SEli Cohen }, 982c82e9aa0SEli Cohen { 983c82e9aa0SEli Cohen .opcode = MLX4_CMD_2RST_QP, 984c82e9aa0SEli Cohen .has_inbox = false, 985c82e9aa0SEli Cohen .has_outbox = false, 986c82e9aa0SEli Cohen .out_is_imm = false, 987c82e9aa0SEli Cohen .encode_slave_id = false, 988c82e9aa0SEli Cohen .verify = NULL, 989c82e9aa0SEli Cohen .wrapper = mlx4_2RST_QP_wrapper 990c82e9aa0SEli Cohen }, 991c82e9aa0SEli Cohen { 992c82e9aa0SEli Cohen .opcode = MLX4_CMD_QUERY_QP, 993c82e9aa0SEli Cohen .has_inbox = false, 994c82e9aa0SEli Cohen .has_outbox = true, 995c82e9aa0SEli Cohen .out_is_imm = false, 996c82e9aa0SEli Cohen .encode_slave_id = false, 997c82e9aa0SEli Cohen .verify = NULL, 998c82e9aa0SEli Cohen .wrapper = mlx4_GEN_QP_wrapper 999c82e9aa0SEli Cohen }, 1000c82e9aa0SEli Cohen { 1001c82e9aa0SEli Cohen .opcode = MLX4_CMD_SUSPEND_QP, 1002c82e9aa0SEli Cohen .has_inbox = false, 1003c82e9aa0SEli Cohen .has_outbox = false, 1004c82e9aa0SEli Cohen .out_is_imm = false, 1005c82e9aa0SEli Cohen .encode_slave_id = false, 1006c82e9aa0SEli Cohen .verify = NULL, 1007c82e9aa0SEli Cohen .wrapper = mlx4_GEN_QP_wrapper 1008c82e9aa0SEli Cohen }, 1009c82e9aa0SEli Cohen { 1010c82e9aa0SEli Cohen .opcode = MLX4_CMD_UNSUSPEND_QP, 1011c82e9aa0SEli Cohen .has_inbox = false, 1012c82e9aa0SEli Cohen .has_outbox = false, 1013c82e9aa0SEli Cohen .out_is_imm = false, 1014c82e9aa0SEli Cohen .encode_slave_id = false, 1015c82e9aa0SEli Cohen .verify = NULL, 1016c82e9aa0SEli Cohen .wrapper = mlx4_GEN_QP_wrapper 1017c82e9aa0SEli Cohen }, 1018c82e9aa0SEli Cohen { 1019c82e9aa0SEli Cohen .opcode = MLX4_CMD_QUERY_IF_STAT, 1020c82e9aa0SEli Cohen .has_inbox = false, 1021c82e9aa0SEli Cohen .has_outbox = true, 1022c82e9aa0SEli Cohen .out_is_imm = false, 1023c82e9aa0SEli Cohen .encode_slave_id = false, 1024c82e9aa0SEli Cohen .verify = NULL, 1025c82e9aa0SEli Cohen .wrapper = mlx4_QUERY_IF_STAT_wrapper 1026c82e9aa0SEli Cohen }, 1027c82e9aa0SEli Cohen /* Native multicast commands are not available for guests */ 1028c82e9aa0SEli Cohen { 1029c82e9aa0SEli Cohen .opcode = MLX4_CMD_QP_ATTACH, 1030c82e9aa0SEli Cohen .has_inbox = true, 1031c82e9aa0SEli Cohen .has_outbox = false, 1032c82e9aa0SEli Cohen .out_is_imm = false, 1033c82e9aa0SEli Cohen .encode_slave_id = false, 1034c82e9aa0SEli Cohen .verify = NULL, 1035c82e9aa0SEli Cohen .wrapper = mlx4_QP_ATTACH_wrapper 1036c82e9aa0SEli Cohen }, 1037c82e9aa0SEli Cohen { 10380ec2c0f8SEugenia Emantayev .opcode = MLX4_CMD_PROMISC, 10390ec2c0f8SEugenia Emantayev .has_inbox = false, 10400ec2c0f8SEugenia Emantayev .has_outbox = false, 10410ec2c0f8SEugenia Emantayev .out_is_imm = false, 10420ec2c0f8SEugenia Emantayev .encode_slave_id = false, 10430ec2c0f8SEugenia Emantayev .verify = NULL, 10440ec2c0f8SEugenia Emantayev .wrapper = mlx4_PROMISC_wrapper 10450ec2c0f8SEugenia Emantayev }, 1046ffe455adSEugenia Emantayev /* Ethernet specific commands */ 1047ffe455adSEugenia Emantayev { 1048ffe455adSEugenia Emantayev .opcode = MLX4_CMD_SET_VLAN_FLTR, 1049ffe455adSEugenia Emantayev .has_inbox = true, 1050ffe455adSEugenia Emantayev .has_outbox = false, 1051ffe455adSEugenia Emantayev .out_is_imm = false, 1052ffe455adSEugenia Emantayev .encode_slave_id = false, 1053ffe455adSEugenia Emantayev .verify = NULL, 1054ffe455adSEugenia Emantayev .wrapper = mlx4_SET_VLAN_FLTR_wrapper 1055ffe455adSEugenia Emantayev }, 1056ffe455adSEugenia Emantayev { 1057ffe455adSEugenia Emantayev .opcode = MLX4_CMD_SET_MCAST_FLTR, 1058ffe455adSEugenia Emantayev .has_inbox = false, 1059ffe455adSEugenia Emantayev .has_outbox = false, 1060ffe455adSEugenia Emantayev .out_is_imm = false, 1061ffe455adSEugenia Emantayev .encode_slave_id = false, 1062ffe455adSEugenia Emantayev .verify = NULL, 1063ffe455adSEugenia Emantayev .wrapper = mlx4_SET_MCAST_FLTR_wrapper 1064ffe455adSEugenia Emantayev }, 1065ffe455adSEugenia Emantayev { 1066ffe455adSEugenia Emantayev .opcode = MLX4_CMD_DUMP_ETH_STATS, 1067ffe455adSEugenia Emantayev .has_inbox = false, 1068ffe455adSEugenia Emantayev .has_outbox = true, 1069ffe455adSEugenia Emantayev .out_is_imm = false, 1070ffe455adSEugenia Emantayev .encode_slave_id = false, 1071ffe455adSEugenia Emantayev .verify = NULL, 1072ffe455adSEugenia Emantayev .wrapper = mlx4_DUMP_ETH_STATS_wrapper 1073ffe455adSEugenia Emantayev }, 10740ec2c0f8SEugenia Emantayev { 1075c82e9aa0SEli Cohen .opcode = MLX4_CMD_INFORM_FLR_DONE, 1076c82e9aa0SEli Cohen .has_inbox = false, 1077c82e9aa0SEli Cohen .has_outbox = false, 1078c82e9aa0SEli Cohen .out_is_imm = false, 1079c82e9aa0SEli Cohen .encode_slave_id = false, 1080c82e9aa0SEli Cohen .verify = NULL, 1081c82e9aa0SEli Cohen .wrapper = NULL 1082c82e9aa0SEli Cohen }, 1083e8f081aaSYevgeny Petrilin }; 1084e8f081aaSYevgeny Petrilin 1085e8f081aaSYevgeny Petrilin static int mlx4_master_process_vhcr(struct mlx4_dev *dev, int slave, 1086e8f081aaSYevgeny Petrilin struct mlx4_vhcr_cmd *in_vhcr) 1087e8f081aaSYevgeny Petrilin { 1088e8f081aaSYevgeny Petrilin struct mlx4_priv *priv = mlx4_priv(dev); 1089e8f081aaSYevgeny Petrilin struct mlx4_cmd_info *cmd = NULL; 1090e8f081aaSYevgeny Petrilin struct mlx4_vhcr_cmd *vhcr_cmd = in_vhcr ? in_vhcr : priv->mfunc.vhcr; 1091e8f081aaSYevgeny Petrilin struct mlx4_vhcr *vhcr; 1092e8f081aaSYevgeny Petrilin struct mlx4_cmd_mailbox *inbox = NULL; 1093e8f081aaSYevgeny Petrilin struct mlx4_cmd_mailbox *outbox = NULL; 1094e8f081aaSYevgeny Petrilin u64 in_param; 1095e8f081aaSYevgeny Petrilin u64 out_param; 1096e8f081aaSYevgeny Petrilin int ret = 0; 1097e8f081aaSYevgeny Petrilin int i; 109872be84f1SYevgeny Petrilin int err = 0; 1099e8f081aaSYevgeny Petrilin 1100e8f081aaSYevgeny Petrilin /* Create sw representation of Virtual HCR */ 1101e8f081aaSYevgeny Petrilin vhcr = kzalloc(sizeof(struct mlx4_vhcr), GFP_KERNEL); 1102e8f081aaSYevgeny Petrilin if (!vhcr) 1103e8f081aaSYevgeny Petrilin return -ENOMEM; 1104e8f081aaSYevgeny Petrilin 1105e8f081aaSYevgeny Petrilin /* DMA in the vHCR */ 1106e8f081aaSYevgeny Petrilin if (!in_vhcr) { 1107e8f081aaSYevgeny Petrilin ret = mlx4_ACCESS_MEM(dev, priv->mfunc.vhcr_dma, slave, 1108e8f081aaSYevgeny Petrilin priv->mfunc.master.slave_state[slave].vhcr_dma, 1109e8f081aaSYevgeny Petrilin ALIGN(sizeof(struct mlx4_vhcr_cmd), 1110e8f081aaSYevgeny Petrilin MLX4_ACCESS_MEM_ALIGN), 1); 1111e8f081aaSYevgeny Petrilin if (ret) { 1112e8f081aaSYevgeny Petrilin mlx4_err(dev, "%s:Failed reading vhcr" 1113e8f081aaSYevgeny Petrilin "ret: 0x%x\n", __func__, ret); 1114e8f081aaSYevgeny Petrilin kfree(vhcr); 1115e8f081aaSYevgeny Petrilin return ret; 1116e8f081aaSYevgeny Petrilin } 1117e8f081aaSYevgeny Petrilin } 1118e8f081aaSYevgeny Petrilin 1119e8f081aaSYevgeny Petrilin /* Fill SW VHCR fields */ 1120e8f081aaSYevgeny Petrilin vhcr->in_param = be64_to_cpu(vhcr_cmd->in_param); 1121e8f081aaSYevgeny Petrilin vhcr->out_param = be64_to_cpu(vhcr_cmd->out_param); 1122e8f081aaSYevgeny Petrilin vhcr->in_modifier = be32_to_cpu(vhcr_cmd->in_modifier); 1123e8f081aaSYevgeny Petrilin vhcr->token = be16_to_cpu(vhcr_cmd->token); 1124e8f081aaSYevgeny Petrilin vhcr->op = be16_to_cpu(vhcr_cmd->opcode) & 0xfff; 1125e8f081aaSYevgeny Petrilin vhcr->op_modifier = (u8) (be16_to_cpu(vhcr_cmd->opcode) >> 12); 1126e8f081aaSYevgeny Petrilin vhcr->e_bit = vhcr_cmd->flags & (1 << 6); 1127e8f081aaSYevgeny Petrilin 1128e8f081aaSYevgeny Petrilin /* Lookup command */ 1129e8f081aaSYevgeny Petrilin for (i = 0; i < ARRAY_SIZE(cmd_info); ++i) { 1130e8f081aaSYevgeny Petrilin if (vhcr->op == cmd_info[i].opcode) { 1131e8f081aaSYevgeny Petrilin cmd = &cmd_info[i]; 1132e8f081aaSYevgeny Petrilin break; 1133e8f081aaSYevgeny Petrilin } 1134e8f081aaSYevgeny Petrilin } 1135e8f081aaSYevgeny Petrilin if (!cmd) { 1136e8f081aaSYevgeny Petrilin mlx4_err(dev, "Unknown command:0x%x accepted from slave:%d\n", 1137e8f081aaSYevgeny Petrilin vhcr->op, slave); 113872be84f1SYevgeny Petrilin vhcr_cmd->status = CMD_STAT_BAD_PARAM; 1139e8f081aaSYevgeny Petrilin goto out_status; 1140e8f081aaSYevgeny Petrilin } 1141e8f081aaSYevgeny Petrilin 1142e8f081aaSYevgeny Petrilin /* Read inbox */ 1143e8f081aaSYevgeny Petrilin if (cmd->has_inbox) { 1144e8f081aaSYevgeny Petrilin vhcr->in_param &= INBOX_MASK; 1145e8f081aaSYevgeny Petrilin inbox = mlx4_alloc_cmd_mailbox(dev); 1146e8f081aaSYevgeny Petrilin if (IS_ERR(inbox)) { 114772be84f1SYevgeny Petrilin vhcr_cmd->status = CMD_STAT_BAD_SIZE; 1148e8f081aaSYevgeny Petrilin inbox = NULL; 114972be84f1SYevgeny Petrilin goto out_status; 1150e8f081aaSYevgeny Petrilin } 1151e8f081aaSYevgeny Petrilin 115272be84f1SYevgeny Petrilin if (mlx4_ACCESS_MEM(dev, inbox->dma, slave, 1153e8f081aaSYevgeny Petrilin vhcr->in_param, 115472be84f1SYevgeny Petrilin MLX4_MAILBOX_SIZE, 1)) { 1155e8f081aaSYevgeny Petrilin mlx4_err(dev, "%s: Failed reading inbox (cmd:0x%x)\n", 1156e8f081aaSYevgeny Petrilin __func__, cmd->opcode); 115772be84f1SYevgeny Petrilin vhcr_cmd->status = CMD_STAT_INTERNAL_ERR; 115872be84f1SYevgeny Petrilin goto out_status; 1159e8f081aaSYevgeny Petrilin } 1160e8f081aaSYevgeny Petrilin } 1161e8f081aaSYevgeny Petrilin 1162e8f081aaSYevgeny Petrilin /* Apply permission and bound checks if applicable */ 1163e8f081aaSYevgeny Petrilin if (cmd->verify && cmd->verify(dev, slave, vhcr, inbox)) { 1164e8f081aaSYevgeny Petrilin mlx4_warn(dev, "Command:0x%x from slave: %d failed protection " 1165e8f081aaSYevgeny Petrilin "checks for resource_id:%d\n", vhcr->op, slave, 1166e8f081aaSYevgeny Petrilin vhcr->in_modifier); 116772be84f1SYevgeny Petrilin vhcr_cmd->status = CMD_STAT_BAD_OP; 1168e8f081aaSYevgeny Petrilin goto out_status; 1169e8f081aaSYevgeny Petrilin } 1170e8f081aaSYevgeny Petrilin 1171e8f081aaSYevgeny Petrilin /* Allocate outbox */ 1172e8f081aaSYevgeny Petrilin if (cmd->has_outbox) { 1173e8f081aaSYevgeny Petrilin outbox = mlx4_alloc_cmd_mailbox(dev); 1174e8f081aaSYevgeny Petrilin if (IS_ERR(outbox)) { 117572be84f1SYevgeny Petrilin vhcr_cmd->status = CMD_STAT_BAD_SIZE; 1176e8f081aaSYevgeny Petrilin outbox = NULL; 117772be84f1SYevgeny Petrilin goto out_status; 1178e8f081aaSYevgeny Petrilin } 1179e8f081aaSYevgeny Petrilin } 1180e8f081aaSYevgeny Petrilin 1181e8f081aaSYevgeny Petrilin /* Execute the command! */ 1182e8f081aaSYevgeny Petrilin if (cmd->wrapper) { 118372be84f1SYevgeny Petrilin err = cmd->wrapper(dev, slave, vhcr, inbox, outbox, 1184e8f081aaSYevgeny Petrilin cmd); 1185e8f081aaSYevgeny Petrilin if (cmd->out_is_imm) 1186e8f081aaSYevgeny Petrilin vhcr_cmd->out_param = cpu_to_be64(vhcr->out_param); 1187e8f081aaSYevgeny Petrilin } else { 1188e8f081aaSYevgeny Petrilin in_param = cmd->has_inbox ? (u64) inbox->dma : 1189e8f081aaSYevgeny Petrilin vhcr->in_param; 1190e8f081aaSYevgeny Petrilin out_param = cmd->has_outbox ? (u64) outbox->dma : 1191e8f081aaSYevgeny Petrilin vhcr->out_param; 119272be84f1SYevgeny Petrilin err = __mlx4_cmd(dev, in_param, &out_param, 1193e8f081aaSYevgeny Petrilin cmd->out_is_imm, vhcr->in_modifier, 1194e8f081aaSYevgeny Petrilin vhcr->op_modifier, vhcr->op, 1195e8f081aaSYevgeny Petrilin MLX4_CMD_TIME_CLASS_A, 1196e8f081aaSYevgeny Petrilin MLX4_CMD_NATIVE); 1197e8f081aaSYevgeny Petrilin 1198e8f081aaSYevgeny Petrilin if (cmd->out_is_imm) { 1199e8f081aaSYevgeny Petrilin vhcr->out_param = out_param; 1200e8f081aaSYevgeny Petrilin vhcr_cmd->out_param = cpu_to_be64(vhcr->out_param); 1201e8f081aaSYevgeny Petrilin } 1202e8f081aaSYevgeny Petrilin } 1203e8f081aaSYevgeny Petrilin 120472be84f1SYevgeny Petrilin if (err) { 120572be84f1SYevgeny Petrilin mlx4_warn(dev, "vhcr command:0x%x slave:%d failed with" 120672be84f1SYevgeny Petrilin " error:%d, status %d\n", 120772be84f1SYevgeny Petrilin vhcr->op, slave, vhcr->errno, err); 120872be84f1SYevgeny Petrilin vhcr_cmd->status = mlx4_errno_to_status(err); 120972be84f1SYevgeny Petrilin goto out_status; 121072be84f1SYevgeny Petrilin } 121172be84f1SYevgeny Petrilin 121272be84f1SYevgeny Petrilin 1213e8f081aaSYevgeny Petrilin /* Write outbox if command completed successfully */ 121472be84f1SYevgeny Petrilin if (cmd->has_outbox && !vhcr_cmd->status) { 1215e8f081aaSYevgeny Petrilin ret = mlx4_ACCESS_MEM(dev, outbox->dma, slave, 1216e8f081aaSYevgeny Petrilin vhcr->out_param, 1217e8f081aaSYevgeny Petrilin MLX4_MAILBOX_SIZE, MLX4_CMD_WRAPPED); 1218e8f081aaSYevgeny Petrilin if (ret) { 121972be84f1SYevgeny Petrilin /* If we failed to write back the outbox after the 122072be84f1SYevgeny Petrilin *command was successfully executed, we must fail this 122172be84f1SYevgeny Petrilin * slave, as it is now in undefined state */ 1222e8f081aaSYevgeny Petrilin mlx4_err(dev, "%s:Failed writing outbox\n", __func__); 1223e8f081aaSYevgeny Petrilin goto out; 1224e8f081aaSYevgeny Petrilin } 1225e8f081aaSYevgeny Petrilin } 1226e8f081aaSYevgeny Petrilin 1227e8f081aaSYevgeny Petrilin out_status: 1228e8f081aaSYevgeny Petrilin /* DMA back vhcr result */ 1229e8f081aaSYevgeny Petrilin if (!in_vhcr) { 1230e8f081aaSYevgeny Petrilin ret = mlx4_ACCESS_MEM(dev, priv->mfunc.vhcr_dma, slave, 1231e8f081aaSYevgeny Petrilin priv->mfunc.master.slave_state[slave].vhcr_dma, 1232e8f081aaSYevgeny Petrilin ALIGN(sizeof(struct mlx4_vhcr), 1233e8f081aaSYevgeny Petrilin MLX4_ACCESS_MEM_ALIGN), 1234e8f081aaSYevgeny Petrilin MLX4_CMD_WRAPPED); 1235e8f081aaSYevgeny Petrilin if (ret) 1236e8f081aaSYevgeny Petrilin mlx4_err(dev, "%s:Failed writing vhcr result\n", 1237e8f081aaSYevgeny Petrilin __func__); 1238e8f081aaSYevgeny Petrilin else if (vhcr->e_bit && 1239e8f081aaSYevgeny Petrilin mlx4_GEN_EQE(dev, slave, &priv->mfunc.master.cmd_eqe)) 1240e8f081aaSYevgeny Petrilin mlx4_warn(dev, "Failed to generate command completion " 1241e8f081aaSYevgeny Petrilin "eqe for slave %d\n", slave); 1242e8f081aaSYevgeny Petrilin } 1243e8f081aaSYevgeny Petrilin 1244e8f081aaSYevgeny Petrilin out: 1245e8f081aaSYevgeny Petrilin kfree(vhcr); 1246e8f081aaSYevgeny Petrilin mlx4_free_cmd_mailbox(dev, inbox); 1247e8f081aaSYevgeny Petrilin mlx4_free_cmd_mailbox(dev, outbox); 1248e8f081aaSYevgeny Petrilin return ret; 1249e8f081aaSYevgeny Petrilin } 1250e8f081aaSYevgeny Petrilin 1251e8f081aaSYevgeny Petrilin static void mlx4_master_do_cmd(struct mlx4_dev *dev, int slave, u8 cmd, 1252e8f081aaSYevgeny Petrilin u16 param, u8 toggle) 1253e8f081aaSYevgeny Petrilin { 1254e8f081aaSYevgeny Petrilin struct mlx4_priv *priv = mlx4_priv(dev); 1255e8f081aaSYevgeny Petrilin struct mlx4_slave_state *slave_state = priv->mfunc.master.slave_state; 1256e8f081aaSYevgeny Petrilin u32 reply; 1257e8f081aaSYevgeny Petrilin u8 is_going_down = 0; 1258803143fbSMarcel Apfelbaum int i; 1259e8f081aaSYevgeny Petrilin 1260e8f081aaSYevgeny Petrilin slave_state[slave].comm_toggle ^= 1; 1261e8f081aaSYevgeny Petrilin reply = (u32) slave_state[slave].comm_toggle << 31; 1262e8f081aaSYevgeny Petrilin if (toggle != slave_state[slave].comm_toggle) { 1263e8f081aaSYevgeny Petrilin mlx4_warn(dev, "Incorrect toggle %d from slave %d. *** MASTER" 1264e8f081aaSYevgeny Petrilin "STATE COMPROMISIED ***\n", toggle, slave); 1265e8f081aaSYevgeny Petrilin goto reset_slave; 1266e8f081aaSYevgeny Petrilin } 1267e8f081aaSYevgeny Petrilin if (cmd == MLX4_COMM_CMD_RESET) { 1268e8f081aaSYevgeny Petrilin mlx4_warn(dev, "Received reset from slave:%d\n", slave); 1269e8f081aaSYevgeny Petrilin slave_state[slave].active = false; 1270803143fbSMarcel Apfelbaum for (i = 0; i < MLX4_EVENT_TYPES_NUM; ++i) { 1271803143fbSMarcel Apfelbaum slave_state[slave].event_eq[i].eqn = -1; 1272803143fbSMarcel Apfelbaum slave_state[slave].event_eq[i].token = 0; 1273803143fbSMarcel Apfelbaum } 1274e8f081aaSYevgeny Petrilin /*check if we are in the middle of FLR process, 1275e8f081aaSYevgeny Petrilin if so return "retry" status to the slave*/ 1276162344edSOr Gerlitz if (MLX4_COMM_CMD_FLR == slave_state[slave].last_cmd) 1277e8f081aaSYevgeny Petrilin goto inform_slave_state; 1278e8f081aaSYevgeny Petrilin 1279e8f081aaSYevgeny Petrilin /* write the version in the event field */ 1280e8f081aaSYevgeny Petrilin reply |= mlx4_comm_get_version(); 1281e8f081aaSYevgeny Petrilin 1282e8f081aaSYevgeny Petrilin goto reset_slave; 1283e8f081aaSYevgeny Petrilin } 1284e8f081aaSYevgeny Petrilin /*command from slave in the middle of FLR*/ 1285e8f081aaSYevgeny Petrilin if (cmd != MLX4_COMM_CMD_RESET && 1286e8f081aaSYevgeny Petrilin MLX4_COMM_CMD_FLR == slave_state[slave].last_cmd) { 1287e8f081aaSYevgeny Petrilin mlx4_warn(dev, "slave:%d is Trying to run cmd(0x%x) " 1288e8f081aaSYevgeny Petrilin "in the middle of FLR\n", slave, cmd); 1289e8f081aaSYevgeny Petrilin return; 1290e8f081aaSYevgeny Petrilin } 1291e8f081aaSYevgeny Petrilin 1292e8f081aaSYevgeny Petrilin switch (cmd) { 1293e8f081aaSYevgeny Petrilin case MLX4_COMM_CMD_VHCR0: 1294e8f081aaSYevgeny Petrilin if (slave_state[slave].last_cmd != MLX4_COMM_CMD_RESET) 1295e8f081aaSYevgeny Petrilin goto reset_slave; 1296e8f081aaSYevgeny Petrilin slave_state[slave].vhcr_dma = ((u64) param) << 48; 1297e8f081aaSYevgeny Petrilin priv->mfunc.master.slave_state[slave].cookie = 0; 1298e8f081aaSYevgeny Petrilin mutex_init(&priv->mfunc.master.gen_eqe_mutex[slave]); 1299e8f081aaSYevgeny Petrilin break; 1300e8f081aaSYevgeny Petrilin case MLX4_COMM_CMD_VHCR1: 1301e8f081aaSYevgeny Petrilin if (slave_state[slave].last_cmd != MLX4_COMM_CMD_VHCR0) 1302e8f081aaSYevgeny Petrilin goto reset_slave; 1303e8f081aaSYevgeny Petrilin slave_state[slave].vhcr_dma |= ((u64) param) << 32; 1304e8f081aaSYevgeny Petrilin break; 1305e8f081aaSYevgeny Petrilin case MLX4_COMM_CMD_VHCR2: 1306e8f081aaSYevgeny Petrilin if (slave_state[slave].last_cmd != MLX4_COMM_CMD_VHCR1) 1307e8f081aaSYevgeny Petrilin goto reset_slave; 1308e8f081aaSYevgeny Petrilin slave_state[slave].vhcr_dma |= ((u64) param) << 16; 1309e8f081aaSYevgeny Petrilin break; 1310e8f081aaSYevgeny Petrilin case MLX4_COMM_CMD_VHCR_EN: 1311e8f081aaSYevgeny Petrilin if (slave_state[slave].last_cmd != MLX4_COMM_CMD_VHCR2) 1312e8f081aaSYevgeny Petrilin goto reset_slave; 1313e8f081aaSYevgeny Petrilin slave_state[slave].vhcr_dma |= param; 1314e8f081aaSYevgeny Petrilin slave_state[slave].active = true; 1315e8f081aaSYevgeny Petrilin break; 1316e8f081aaSYevgeny Petrilin case MLX4_COMM_CMD_VHCR_POST: 1317e8f081aaSYevgeny Petrilin if ((slave_state[slave].last_cmd != MLX4_COMM_CMD_VHCR_EN) && 1318e8f081aaSYevgeny Petrilin (slave_state[slave].last_cmd != MLX4_COMM_CMD_VHCR_POST)) 1319e8f081aaSYevgeny Petrilin goto reset_slave; 1320e8f081aaSYevgeny Petrilin down(&priv->cmd.slave_sem); 1321e8f081aaSYevgeny Petrilin if (mlx4_master_process_vhcr(dev, slave, NULL)) { 1322e8f081aaSYevgeny Petrilin mlx4_err(dev, "Failed processing vhcr for slave:%d," 13238d9eb069SMasanari Iida " resetting slave.\n", slave); 1324e8f081aaSYevgeny Petrilin up(&priv->cmd.slave_sem); 1325e8f081aaSYevgeny Petrilin goto reset_slave; 1326e8f081aaSYevgeny Petrilin } 1327e8f081aaSYevgeny Petrilin up(&priv->cmd.slave_sem); 1328e8f081aaSYevgeny Petrilin break; 1329e8f081aaSYevgeny Petrilin default: 1330e8f081aaSYevgeny Petrilin mlx4_warn(dev, "Bad comm cmd:%d from slave:%d\n", cmd, slave); 1331e8f081aaSYevgeny Petrilin goto reset_slave; 1332e8f081aaSYevgeny Petrilin } 1333e8f081aaSYevgeny Petrilin spin_lock(&priv->mfunc.master.slave_state_lock); 1334e8f081aaSYevgeny Petrilin if (!slave_state[slave].is_slave_going_down) 1335e8f081aaSYevgeny Petrilin slave_state[slave].last_cmd = cmd; 1336e8f081aaSYevgeny Petrilin else 1337e8f081aaSYevgeny Petrilin is_going_down = 1; 1338e8f081aaSYevgeny Petrilin spin_unlock(&priv->mfunc.master.slave_state_lock); 1339e8f081aaSYevgeny Petrilin if (is_going_down) { 1340e8f081aaSYevgeny Petrilin mlx4_warn(dev, "Slave is going down aborting command(%d)" 1341e8f081aaSYevgeny Petrilin " executing from slave:%d\n", 1342e8f081aaSYevgeny Petrilin cmd, slave); 1343e8f081aaSYevgeny Petrilin return; 1344e8f081aaSYevgeny Petrilin } 1345e8f081aaSYevgeny Petrilin __raw_writel((__force u32) cpu_to_be32(reply), 1346e8f081aaSYevgeny Petrilin &priv->mfunc.comm[slave].slave_read); 1347e8f081aaSYevgeny Petrilin mmiowb(); 1348e8f081aaSYevgeny Petrilin 1349e8f081aaSYevgeny Petrilin return; 1350e8f081aaSYevgeny Petrilin 1351e8f081aaSYevgeny Petrilin reset_slave: 1352c82e9aa0SEli Cohen /* cleanup any slave resources */ 1353c82e9aa0SEli Cohen mlx4_delete_all_resources_for_slave(dev, slave); 1354e8f081aaSYevgeny Petrilin spin_lock(&priv->mfunc.master.slave_state_lock); 1355e8f081aaSYevgeny Petrilin if (!slave_state[slave].is_slave_going_down) 1356e8f081aaSYevgeny Petrilin slave_state[slave].last_cmd = MLX4_COMM_CMD_RESET; 1357e8f081aaSYevgeny Petrilin spin_unlock(&priv->mfunc.master.slave_state_lock); 1358e8f081aaSYevgeny Petrilin /*with slave in the middle of flr, no need to clean resources again.*/ 1359e8f081aaSYevgeny Petrilin inform_slave_state: 1360e8f081aaSYevgeny Petrilin memset(&slave_state[slave].event_eq, 0, 1361e8f081aaSYevgeny Petrilin sizeof(struct mlx4_slave_event_eq_info)); 1362e8f081aaSYevgeny Petrilin __raw_writel((__force u32) cpu_to_be32(reply), 1363e8f081aaSYevgeny Petrilin &priv->mfunc.comm[slave].slave_read); 1364e8f081aaSYevgeny Petrilin wmb(); 1365e8f081aaSYevgeny Petrilin } 1366e8f081aaSYevgeny Petrilin 1367e8f081aaSYevgeny Petrilin /* master command processing */ 1368e8f081aaSYevgeny Petrilin void mlx4_master_comm_channel(struct work_struct *work) 1369e8f081aaSYevgeny Petrilin { 1370e8f081aaSYevgeny Petrilin struct mlx4_mfunc_master_ctx *master = 1371e8f081aaSYevgeny Petrilin container_of(work, 1372e8f081aaSYevgeny Petrilin struct mlx4_mfunc_master_ctx, 1373e8f081aaSYevgeny Petrilin comm_work); 1374e8f081aaSYevgeny Petrilin struct mlx4_mfunc *mfunc = 1375e8f081aaSYevgeny Petrilin container_of(master, struct mlx4_mfunc, master); 1376e8f081aaSYevgeny Petrilin struct mlx4_priv *priv = 1377e8f081aaSYevgeny Petrilin container_of(mfunc, struct mlx4_priv, mfunc); 1378e8f081aaSYevgeny Petrilin struct mlx4_dev *dev = &priv->dev; 1379e8f081aaSYevgeny Petrilin __be32 *bit_vec; 1380e8f081aaSYevgeny Petrilin u32 comm_cmd; 1381e8f081aaSYevgeny Petrilin u32 vec; 1382e8f081aaSYevgeny Petrilin int i, j, slave; 1383e8f081aaSYevgeny Petrilin int toggle; 1384e8f081aaSYevgeny Petrilin int served = 0; 1385e8f081aaSYevgeny Petrilin int reported = 0; 1386e8f081aaSYevgeny Petrilin u32 slt; 1387e8f081aaSYevgeny Petrilin 1388e8f081aaSYevgeny Petrilin bit_vec = master->comm_arm_bit_vector; 1389e8f081aaSYevgeny Petrilin for (i = 0; i < COMM_CHANNEL_BIT_ARRAY_SIZE; i++) { 1390e8f081aaSYevgeny Petrilin vec = be32_to_cpu(bit_vec[i]); 1391e8f081aaSYevgeny Petrilin for (j = 0; j < 32; j++) { 1392e8f081aaSYevgeny Petrilin if (!(vec & (1 << j))) 1393e8f081aaSYevgeny Petrilin continue; 1394e8f081aaSYevgeny Petrilin ++reported; 1395e8f081aaSYevgeny Petrilin slave = (i * 32) + j; 1396e8f081aaSYevgeny Petrilin comm_cmd = swab32(readl( 1397e8f081aaSYevgeny Petrilin &mfunc->comm[slave].slave_write)); 1398e8f081aaSYevgeny Petrilin slt = swab32(readl(&mfunc->comm[slave].slave_read)) 1399e8f081aaSYevgeny Petrilin >> 31; 1400e8f081aaSYevgeny Petrilin toggle = comm_cmd >> 31; 1401e8f081aaSYevgeny Petrilin if (toggle != slt) { 1402e8f081aaSYevgeny Petrilin if (master->slave_state[slave].comm_toggle 1403e8f081aaSYevgeny Petrilin != slt) { 1404e8f081aaSYevgeny Petrilin printk(KERN_INFO "slave %d out of sync." 1405e8f081aaSYevgeny Petrilin " read toggle %d, state toggle %d. " 1406e8f081aaSYevgeny Petrilin "Resynching.\n", slave, slt, 1407e8f081aaSYevgeny Petrilin master->slave_state[slave].comm_toggle); 1408e8f081aaSYevgeny Petrilin master->slave_state[slave].comm_toggle = 1409e8f081aaSYevgeny Petrilin slt; 1410e8f081aaSYevgeny Petrilin } 1411e8f081aaSYevgeny Petrilin mlx4_master_do_cmd(dev, slave, 1412e8f081aaSYevgeny Petrilin comm_cmd >> 16 & 0xff, 1413e8f081aaSYevgeny Petrilin comm_cmd & 0xffff, toggle); 1414e8f081aaSYevgeny Petrilin ++served; 1415e8f081aaSYevgeny Petrilin } 1416e8f081aaSYevgeny Petrilin } 1417e8f081aaSYevgeny Petrilin } 1418e8f081aaSYevgeny Petrilin 1419e8f081aaSYevgeny Petrilin if (reported && reported != served) 1420e8f081aaSYevgeny Petrilin mlx4_warn(dev, "Got command event with bitmask from %d slaves" 1421e8f081aaSYevgeny Petrilin " but %d were served\n", 1422e8f081aaSYevgeny Petrilin reported, served); 1423e8f081aaSYevgeny Petrilin 1424e8f081aaSYevgeny Petrilin if (mlx4_ARM_COMM_CHANNEL(dev)) 1425e8f081aaSYevgeny Petrilin mlx4_warn(dev, "Failed to arm comm channel events\n"); 1426e8f081aaSYevgeny Petrilin } 1427e8f081aaSYevgeny Petrilin 1428ab9c17a0SJack Morgenstein static int sync_toggles(struct mlx4_dev *dev) 1429ab9c17a0SJack Morgenstein { 1430ab9c17a0SJack Morgenstein struct mlx4_priv *priv = mlx4_priv(dev); 1431ab9c17a0SJack Morgenstein int wr_toggle; 1432ab9c17a0SJack Morgenstein int rd_toggle; 1433ab9c17a0SJack Morgenstein unsigned long end; 1434ab9c17a0SJack Morgenstein 1435ab9c17a0SJack Morgenstein wr_toggle = swab32(readl(&priv->mfunc.comm->slave_write)) >> 31; 1436ab9c17a0SJack Morgenstein end = jiffies + msecs_to_jiffies(5000); 1437ab9c17a0SJack Morgenstein 1438ab9c17a0SJack Morgenstein while (time_before(jiffies, end)) { 1439ab9c17a0SJack Morgenstein rd_toggle = swab32(readl(&priv->mfunc.comm->slave_read)) >> 31; 1440ab9c17a0SJack Morgenstein if (rd_toggle == wr_toggle) { 1441ab9c17a0SJack Morgenstein priv->cmd.comm_toggle = rd_toggle; 1442ab9c17a0SJack Morgenstein return 0; 1443ab9c17a0SJack Morgenstein } 1444ab9c17a0SJack Morgenstein 1445ab9c17a0SJack Morgenstein cond_resched(); 1446ab9c17a0SJack Morgenstein } 1447ab9c17a0SJack Morgenstein 1448ab9c17a0SJack Morgenstein /* 1449ab9c17a0SJack Morgenstein * we could reach here if for example the previous VM using this 1450ab9c17a0SJack Morgenstein * function misbehaved and left the channel with unsynced state. We 1451ab9c17a0SJack Morgenstein * should fix this here and give this VM a chance to use a properly 1452ab9c17a0SJack Morgenstein * synced channel 1453ab9c17a0SJack Morgenstein */ 1454ab9c17a0SJack Morgenstein mlx4_warn(dev, "recovering from previously mis-behaved VM\n"); 1455ab9c17a0SJack Morgenstein __raw_writel((__force u32) 0, &priv->mfunc.comm->slave_read); 1456ab9c17a0SJack Morgenstein __raw_writel((__force u32) 0, &priv->mfunc.comm->slave_write); 1457ab9c17a0SJack Morgenstein priv->cmd.comm_toggle = 0; 1458ab9c17a0SJack Morgenstein 1459ab9c17a0SJack Morgenstein return 0; 1460ab9c17a0SJack Morgenstein } 1461ab9c17a0SJack Morgenstein 1462ab9c17a0SJack Morgenstein int mlx4_multi_func_init(struct mlx4_dev *dev) 1463ab9c17a0SJack Morgenstein { 1464ab9c17a0SJack Morgenstein struct mlx4_priv *priv = mlx4_priv(dev); 1465ab9c17a0SJack Morgenstein struct mlx4_slave_state *s_state; 1466803143fbSMarcel Apfelbaum int i, j, err, port; 1467ab9c17a0SJack Morgenstein 1468ab9c17a0SJack Morgenstein priv->mfunc.vhcr = dma_alloc_coherent(&(dev->pdev->dev), PAGE_SIZE, 1469ab9c17a0SJack Morgenstein &priv->mfunc.vhcr_dma, 1470ab9c17a0SJack Morgenstein GFP_KERNEL); 1471ab9c17a0SJack Morgenstein if (!priv->mfunc.vhcr) { 1472ab9c17a0SJack Morgenstein mlx4_err(dev, "Couldn't allocate vhcr.\n"); 1473ab9c17a0SJack Morgenstein return -ENOMEM; 1474ab9c17a0SJack Morgenstein } 1475ab9c17a0SJack Morgenstein 1476ab9c17a0SJack Morgenstein if (mlx4_is_master(dev)) 1477ab9c17a0SJack Morgenstein priv->mfunc.comm = 1478ab9c17a0SJack Morgenstein ioremap(pci_resource_start(dev->pdev, priv->fw.comm_bar) + 1479ab9c17a0SJack Morgenstein priv->fw.comm_base, MLX4_COMM_PAGESIZE); 1480ab9c17a0SJack Morgenstein else 1481ab9c17a0SJack Morgenstein priv->mfunc.comm = 1482ab9c17a0SJack Morgenstein ioremap(pci_resource_start(dev->pdev, 2) + 1483ab9c17a0SJack Morgenstein MLX4_SLAVE_COMM_BASE, MLX4_COMM_PAGESIZE); 1484ab9c17a0SJack Morgenstein if (!priv->mfunc.comm) { 1485ab9c17a0SJack Morgenstein mlx4_err(dev, "Couldn't map communication vector.\n"); 1486ab9c17a0SJack Morgenstein goto err_vhcr; 1487ab9c17a0SJack Morgenstein } 1488ab9c17a0SJack Morgenstein 1489ab9c17a0SJack Morgenstein if (mlx4_is_master(dev)) { 1490ab9c17a0SJack Morgenstein priv->mfunc.master.slave_state = 1491ab9c17a0SJack Morgenstein kzalloc(dev->num_slaves * 1492ab9c17a0SJack Morgenstein sizeof(struct mlx4_slave_state), GFP_KERNEL); 1493ab9c17a0SJack Morgenstein if (!priv->mfunc.master.slave_state) 1494ab9c17a0SJack Morgenstein goto err_comm; 1495ab9c17a0SJack Morgenstein 1496ab9c17a0SJack Morgenstein for (i = 0; i < dev->num_slaves; ++i) { 1497ab9c17a0SJack Morgenstein s_state = &priv->mfunc.master.slave_state[i]; 1498ab9c17a0SJack Morgenstein s_state->last_cmd = MLX4_COMM_CMD_RESET; 1499803143fbSMarcel Apfelbaum for (j = 0; j < MLX4_EVENT_TYPES_NUM; ++j) 1500803143fbSMarcel Apfelbaum s_state->event_eq[j].eqn = -1; 1501ab9c17a0SJack Morgenstein __raw_writel((__force u32) 0, 1502ab9c17a0SJack Morgenstein &priv->mfunc.comm[i].slave_write); 1503ab9c17a0SJack Morgenstein __raw_writel((__force u32) 0, 1504ab9c17a0SJack Morgenstein &priv->mfunc.comm[i].slave_read); 1505ab9c17a0SJack Morgenstein mmiowb(); 1506ab9c17a0SJack Morgenstein for (port = 1; port <= MLX4_MAX_PORTS; port++) { 1507ab9c17a0SJack Morgenstein s_state->vlan_filter[port] = 1508ab9c17a0SJack Morgenstein kzalloc(sizeof(struct mlx4_vlan_fltr), 1509ab9c17a0SJack Morgenstein GFP_KERNEL); 1510ab9c17a0SJack Morgenstein if (!s_state->vlan_filter[port]) { 1511ab9c17a0SJack Morgenstein if (--port) 1512ab9c17a0SJack Morgenstein kfree(s_state->vlan_filter[port]); 1513ab9c17a0SJack Morgenstein goto err_slaves; 1514ab9c17a0SJack Morgenstein } 1515ab9c17a0SJack Morgenstein INIT_LIST_HEAD(&s_state->mcast_filters[port]); 1516ab9c17a0SJack Morgenstein } 1517ab9c17a0SJack Morgenstein spin_lock_init(&s_state->lock); 1518ab9c17a0SJack Morgenstein } 1519ab9c17a0SJack Morgenstein 1520ab9c17a0SJack Morgenstein memset(&priv->mfunc.master.cmd_eqe, 0, sizeof(struct mlx4_eqe)); 1521ab9c17a0SJack Morgenstein priv->mfunc.master.cmd_eqe.type = MLX4_EVENT_TYPE_CMD; 1522ab9c17a0SJack Morgenstein INIT_WORK(&priv->mfunc.master.comm_work, 1523ab9c17a0SJack Morgenstein mlx4_master_comm_channel); 1524ab9c17a0SJack Morgenstein INIT_WORK(&priv->mfunc.master.slave_event_work, 1525ab9c17a0SJack Morgenstein mlx4_gen_slave_eqe); 1526ab9c17a0SJack Morgenstein INIT_WORK(&priv->mfunc.master.slave_flr_event_work, 1527ab9c17a0SJack Morgenstein mlx4_master_handle_slave_flr); 1528ab9c17a0SJack Morgenstein spin_lock_init(&priv->mfunc.master.slave_state_lock); 1529ab9c17a0SJack Morgenstein priv->mfunc.master.comm_wq = 1530ab9c17a0SJack Morgenstein create_singlethread_workqueue("mlx4_comm"); 1531ab9c17a0SJack Morgenstein if (!priv->mfunc.master.comm_wq) 1532ab9c17a0SJack Morgenstein goto err_slaves; 1533ab9c17a0SJack Morgenstein 1534ab9c17a0SJack Morgenstein if (mlx4_init_resource_tracker(dev)) 1535ab9c17a0SJack Morgenstein goto err_thread; 1536ab9c17a0SJack Morgenstein 1537ab9c17a0SJack Morgenstein sema_init(&priv->cmd.slave_sem, 1); 1538ab9c17a0SJack Morgenstein err = mlx4_ARM_COMM_CHANNEL(dev); 1539ab9c17a0SJack Morgenstein if (err) { 1540ab9c17a0SJack Morgenstein mlx4_err(dev, " Failed to arm comm channel eq: %x\n", 1541ab9c17a0SJack Morgenstein err); 1542ab9c17a0SJack Morgenstein goto err_resource; 1543ab9c17a0SJack Morgenstein } 1544ab9c17a0SJack Morgenstein 1545ab9c17a0SJack Morgenstein } else { 1546ab9c17a0SJack Morgenstein err = sync_toggles(dev); 1547ab9c17a0SJack Morgenstein if (err) { 1548ab9c17a0SJack Morgenstein mlx4_err(dev, "Couldn't sync toggles\n"); 1549ab9c17a0SJack Morgenstein goto err_comm; 1550ab9c17a0SJack Morgenstein } 1551ab9c17a0SJack Morgenstein 1552ab9c17a0SJack Morgenstein sema_init(&priv->cmd.slave_sem, 1); 1553ab9c17a0SJack Morgenstein } 1554ab9c17a0SJack Morgenstein return 0; 1555ab9c17a0SJack Morgenstein 1556ab9c17a0SJack Morgenstein err_resource: 1557*b8924951SJack Morgenstein mlx4_free_resource_tracker(dev, RES_TR_FREE_ALL); 1558ab9c17a0SJack Morgenstein err_thread: 1559ab9c17a0SJack Morgenstein flush_workqueue(priv->mfunc.master.comm_wq); 1560ab9c17a0SJack Morgenstein destroy_workqueue(priv->mfunc.master.comm_wq); 1561ab9c17a0SJack Morgenstein err_slaves: 1562ab9c17a0SJack Morgenstein while (--i) { 1563ab9c17a0SJack Morgenstein for (port = 1; port <= MLX4_MAX_PORTS; port++) 1564ab9c17a0SJack Morgenstein kfree(priv->mfunc.master.slave_state[i].vlan_filter[port]); 1565ab9c17a0SJack Morgenstein } 1566ab9c17a0SJack Morgenstein kfree(priv->mfunc.master.slave_state); 1567ab9c17a0SJack Morgenstein err_comm: 1568ab9c17a0SJack Morgenstein iounmap(priv->mfunc.comm); 1569ab9c17a0SJack Morgenstein err_vhcr: 1570ab9c17a0SJack Morgenstein dma_free_coherent(&(dev->pdev->dev), PAGE_SIZE, 1571ab9c17a0SJack Morgenstein priv->mfunc.vhcr, 1572ab9c17a0SJack Morgenstein priv->mfunc.vhcr_dma); 1573ab9c17a0SJack Morgenstein priv->mfunc.vhcr = NULL; 1574ab9c17a0SJack Morgenstein return -ENOMEM; 1575ab9c17a0SJack Morgenstein } 1576ab9c17a0SJack Morgenstein 15775a2cc190SJeff Kirsher int mlx4_cmd_init(struct mlx4_dev *dev) 15785a2cc190SJeff Kirsher { 15795a2cc190SJeff Kirsher struct mlx4_priv *priv = mlx4_priv(dev); 15805a2cc190SJeff Kirsher 15815a2cc190SJeff Kirsher mutex_init(&priv->cmd.hcr_mutex); 15825a2cc190SJeff Kirsher sema_init(&priv->cmd.poll_sem, 1); 15835a2cc190SJeff Kirsher priv->cmd.use_events = 0; 15845a2cc190SJeff Kirsher priv->cmd.toggle = 1; 15855a2cc190SJeff Kirsher 1586e8f081aaSYevgeny Petrilin priv->cmd.hcr = NULL; 1587e8f081aaSYevgeny Petrilin priv->mfunc.vhcr = NULL; 1588e8f081aaSYevgeny Petrilin 1589e8f081aaSYevgeny Petrilin if (!mlx4_is_slave(dev)) { 1590e8f081aaSYevgeny Petrilin priv->cmd.hcr = ioremap(pci_resource_start(dev->pdev, 0) + 1591e8f081aaSYevgeny Petrilin MLX4_HCR_BASE, MLX4_HCR_SIZE); 15925a2cc190SJeff Kirsher if (!priv->cmd.hcr) { 1593e8f081aaSYevgeny Petrilin mlx4_err(dev, "Couldn't map command register.\n"); 15945a2cc190SJeff Kirsher return -ENOMEM; 15955a2cc190SJeff Kirsher } 1596e8f081aaSYevgeny Petrilin } 15975a2cc190SJeff Kirsher 15985a2cc190SJeff Kirsher priv->cmd.pool = pci_pool_create("mlx4_cmd", dev->pdev, 15995a2cc190SJeff Kirsher MLX4_MAILBOX_SIZE, 16005a2cc190SJeff Kirsher MLX4_MAILBOX_SIZE, 0); 1601e8f081aaSYevgeny Petrilin if (!priv->cmd.pool) 1602e8f081aaSYevgeny Petrilin goto err_hcr; 16035a2cc190SJeff Kirsher 16045a2cc190SJeff Kirsher return 0; 1605e8f081aaSYevgeny Petrilin 1606e8f081aaSYevgeny Petrilin err_hcr: 1607e8f081aaSYevgeny Petrilin if (!mlx4_is_slave(dev)) 1608e8f081aaSYevgeny Petrilin iounmap(priv->cmd.hcr); 1609e8f081aaSYevgeny Petrilin return -ENOMEM; 16105a2cc190SJeff Kirsher } 16115a2cc190SJeff Kirsher 1612ab9c17a0SJack Morgenstein void mlx4_multi_func_cleanup(struct mlx4_dev *dev) 1613ab9c17a0SJack Morgenstein { 1614ab9c17a0SJack Morgenstein struct mlx4_priv *priv = mlx4_priv(dev); 1615ab9c17a0SJack Morgenstein int i, port; 1616ab9c17a0SJack Morgenstein 1617ab9c17a0SJack Morgenstein if (mlx4_is_master(dev)) { 1618ab9c17a0SJack Morgenstein flush_workqueue(priv->mfunc.master.comm_wq); 1619ab9c17a0SJack Morgenstein destroy_workqueue(priv->mfunc.master.comm_wq); 1620ab9c17a0SJack Morgenstein for (i = 0; i < dev->num_slaves; i++) { 1621ab9c17a0SJack Morgenstein for (port = 1; port <= MLX4_MAX_PORTS; port++) 1622ab9c17a0SJack Morgenstein kfree(priv->mfunc.master.slave_state[i].vlan_filter[port]); 1623ab9c17a0SJack Morgenstein } 1624ab9c17a0SJack Morgenstein kfree(priv->mfunc.master.slave_state); 1625f08ad06cSEugenia Emantayev } 1626f08ad06cSEugenia Emantayev 1627ab9c17a0SJack Morgenstein iounmap(priv->mfunc.comm); 1628ab9c17a0SJack Morgenstein dma_free_coherent(&(dev->pdev->dev), PAGE_SIZE, 1629f08ad06cSEugenia Emantayev priv->mfunc.vhcr, priv->mfunc.vhcr_dma); 1630ab9c17a0SJack Morgenstein priv->mfunc.vhcr = NULL; 1631ab9c17a0SJack Morgenstein } 1632ab9c17a0SJack Morgenstein 16335a2cc190SJeff Kirsher void mlx4_cmd_cleanup(struct mlx4_dev *dev) 16345a2cc190SJeff Kirsher { 16355a2cc190SJeff Kirsher struct mlx4_priv *priv = mlx4_priv(dev); 16365a2cc190SJeff Kirsher 16375a2cc190SJeff Kirsher pci_pool_destroy(priv->cmd.pool); 1638e8f081aaSYevgeny Petrilin 1639e8f081aaSYevgeny Petrilin if (!mlx4_is_slave(dev)) 16405a2cc190SJeff Kirsher iounmap(priv->cmd.hcr); 16415a2cc190SJeff Kirsher } 16425a2cc190SJeff Kirsher 16435a2cc190SJeff Kirsher /* 16445a2cc190SJeff Kirsher * Switch to using events to issue FW commands (can only be called 16455a2cc190SJeff Kirsher * after event queue for command events has been initialized). 16465a2cc190SJeff Kirsher */ 16475a2cc190SJeff Kirsher int mlx4_cmd_use_events(struct mlx4_dev *dev) 16485a2cc190SJeff Kirsher { 16495a2cc190SJeff Kirsher struct mlx4_priv *priv = mlx4_priv(dev); 16505a2cc190SJeff Kirsher int i; 1651e8f081aaSYevgeny Petrilin int err = 0; 16525a2cc190SJeff Kirsher 16535a2cc190SJeff Kirsher priv->cmd.context = kmalloc(priv->cmd.max_cmds * 16545a2cc190SJeff Kirsher sizeof (struct mlx4_cmd_context), 16555a2cc190SJeff Kirsher GFP_KERNEL); 16565a2cc190SJeff Kirsher if (!priv->cmd.context) 16575a2cc190SJeff Kirsher return -ENOMEM; 16585a2cc190SJeff Kirsher 16595a2cc190SJeff Kirsher for (i = 0; i < priv->cmd.max_cmds; ++i) { 16605a2cc190SJeff Kirsher priv->cmd.context[i].token = i; 16615a2cc190SJeff Kirsher priv->cmd.context[i].next = i + 1; 16625a2cc190SJeff Kirsher } 16635a2cc190SJeff Kirsher 16645a2cc190SJeff Kirsher priv->cmd.context[priv->cmd.max_cmds - 1].next = -1; 16655a2cc190SJeff Kirsher priv->cmd.free_head = 0; 16665a2cc190SJeff Kirsher 16675a2cc190SJeff Kirsher sema_init(&priv->cmd.event_sem, priv->cmd.max_cmds); 16685a2cc190SJeff Kirsher spin_lock_init(&priv->cmd.context_lock); 16695a2cc190SJeff Kirsher 16705a2cc190SJeff Kirsher for (priv->cmd.token_mask = 1; 16715a2cc190SJeff Kirsher priv->cmd.token_mask < priv->cmd.max_cmds; 16725a2cc190SJeff Kirsher priv->cmd.token_mask <<= 1) 16735a2cc190SJeff Kirsher ; /* nothing */ 16745a2cc190SJeff Kirsher --priv->cmd.token_mask; 16755a2cc190SJeff Kirsher 1676e8f081aaSYevgeny Petrilin down(&priv->cmd.poll_sem); 16775a2cc190SJeff Kirsher priv->cmd.use_events = 1; 16785a2cc190SJeff Kirsher 1679e8f081aaSYevgeny Petrilin return err; 16805a2cc190SJeff Kirsher } 16815a2cc190SJeff Kirsher 16825a2cc190SJeff Kirsher /* 16835a2cc190SJeff Kirsher * Switch back to polling (used when shutting down the device) 16845a2cc190SJeff Kirsher */ 16855a2cc190SJeff Kirsher void mlx4_cmd_use_polling(struct mlx4_dev *dev) 16865a2cc190SJeff Kirsher { 16875a2cc190SJeff Kirsher struct mlx4_priv *priv = mlx4_priv(dev); 16885a2cc190SJeff Kirsher int i; 16895a2cc190SJeff Kirsher 16905a2cc190SJeff Kirsher priv->cmd.use_events = 0; 16915a2cc190SJeff Kirsher 16925a2cc190SJeff Kirsher for (i = 0; i < priv->cmd.max_cmds; ++i) 16935a2cc190SJeff Kirsher down(&priv->cmd.event_sem); 16945a2cc190SJeff Kirsher 16955a2cc190SJeff Kirsher kfree(priv->cmd.context); 16965a2cc190SJeff Kirsher 16975a2cc190SJeff Kirsher up(&priv->cmd.poll_sem); 16985a2cc190SJeff Kirsher } 16995a2cc190SJeff Kirsher 17005a2cc190SJeff Kirsher struct mlx4_cmd_mailbox *mlx4_alloc_cmd_mailbox(struct mlx4_dev *dev) 17015a2cc190SJeff Kirsher { 17025a2cc190SJeff Kirsher struct mlx4_cmd_mailbox *mailbox; 17035a2cc190SJeff Kirsher 17045a2cc190SJeff Kirsher mailbox = kmalloc(sizeof *mailbox, GFP_KERNEL); 17055a2cc190SJeff Kirsher if (!mailbox) 17065a2cc190SJeff Kirsher return ERR_PTR(-ENOMEM); 17075a2cc190SJeff Kirsher 17085a2cc190SJeff Kirsher mailbox->buf = pci_pool_alloc(mlx4_priv(dev)->cmd.pool, GFP_KERNEL, 17095a2cc190SJeff Kirsher &mailbox->dma); 17105a2cc190SJeff Kirsher if (!mailbox->buf) { 17115a2cc190SJeff Kirsher kfree(mailbox); 17125a2cc190SJeff Kirsher return ERR_PTR(-ENOMEM); 17135a2cc190SJeff Kirsher } 17145a2cc190SJeff Kirsher 17155a2cc190SJeff Kirsher return mailbox; 17165a2cc190SJeff Kirsher } 17175a2cc190SJeff Kirsher EXPORT_SYMBOL_GPL(mlx4_alloc_cmd_mailbox); 17185a2cc190SJeff Kirsher 1719e8f081aaSYevgeny Petrilin void mlx4_free_cmd_mailbox(struct mlx4_dev *dev, 1720e8f081aaSYevgeny Petrilin struct mlx4_cmd_mailbox *mailbox) 17215a2cc190SJeff Kirsher { 17225a2cc190SJeff Kirsher if (!mailbox) 17235a2cc190SJeff Kirsher return; 17245a2cc190SJeff Kirsher 17255a2cc190SJeff Kirsher pci_pool_free(mlx4_priv(dev)->cmd.pool, mailbox->buf, mailbox->dma); 17265a2cc190SJeff Kirsher kfree(mailbox); 17275a2cc190SJeff Kirsher } 17285a2cc190SJeff Kirsher EXPORT_SYMBOL_GPL(mlx4_free_cmd_mailbox); 1729e8f081aaSYevgeny Petrilin 1730e8f081aaSYevgeny Petrilin u32 mlx4_comm_get_version(void) 1731e8f081aaSYevgeny Petrilin { 1732e8f081aaSYevgeny Petrilin return ((u32) CMD_CHAN_IF_REV << 8) | (u32) CMD_CHAN_VER; 1733e8f081aaSYevgeny Petrilin } 1734