1/*
2
3 * Copyright (c) 2004, 2005 Topspin Communications.  All rights reserved.
4 * Copyright (c) 2005, 2006, 2007, 2008, 2014 Mellanox Technologies. All rights reserved.
5 * Copyright (c) 2005, 2006, 2007 Cisco Systems, Inc.  All rights reserved.
6 *
7 * This software is available to you under a choice of one of two
8 * licenses.  You may choose to be licensed under the terms of the GNU
9 * General Public License (GPL) Version 2, available from the file
10 * COPYING in the main directory of this source tree, or the
11 * OpenIB.org BSD license below:
12 *
13 *     Redistribution and use in source and binary forms, with or
14 *     without modification, are permitted provided that the following
15 *     conditions are met:
16 *
17 *      - Redistributions of source code must retain the above
18 *        copyright notice, this list of conditions and the following
19 *        disclaimer.
20 *
21 *      - Redistributions in binary form must reproduce the above
22 *        copyright notice, this list of conditions and the following
23 *        disclaimer in the documentation and/or other materials
24 *        provided with the distribution.
25 *
26 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
27 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
28 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
29 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
30 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
31 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
32 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
33 * SOFTWARE.
34
35
36 #include <linux/sched.h>
37 #include <linux/slab.h>
38 #include <linux/module.h>
39 #include <linux/pci.h>
40 #include <linux/errno.h>
41 #include <linux/mlx4/device.h>
42 #include <linux/semaphore.h>
43 #include <rdma/ib_smi.h>
44
45 #include <asm/io.h>
46 #include <linux/ktime.h>
47 */
48#include <debug.h>
49#include "fw.h"
50
51#include <linux/io.h>
52#include <linux/pci.h>
53#include <linux/mlx4/cmd.h>
54#include <linux/completion.h>
55
56#include <asm/byteorder.h>
57
58#include <barrelfish/barrelfish.h>
59#include <barrelfish/deferred.h>
60#include <barrelfish/sys_debug.h>
61
62#define CMD_POLL_TOKEN 0xffff
63/*#define INBOX_MASK	0xffffffffffffff00ULL
64
65 #define CMD_CHAN_VER 1
66 #define CMD_CHAN_IF_REV 1
67 */
68enum {
69	/* command completed successfully: */
70	CMD_STAT_OK = 0x00,
71	/* Internal error (such as a bus error) occurred while processing command: */
72	CMD_STAT_INTERNAL_ERR = 0x01,
73	/* Operation/command not supported or opcode modifier not supported: */
74	CMD_STAT_BAD_OP = 0x02,
75	/* Parameter not supported or parameter out of range: */
76	CMD_STAT_BAD_PARAM = 0x03,
77	/* System not enabled or bad system state: */
78	CMD_STAT_BAD_SYS_STATE = 0x04,
79	/* Attempt to access reserved or unallocaterd resource: */
80	CMD_STAT_BAD_RESOURCE = 0x05,
81	/* Requested resource is currently executing a command, or is otherwise busy: */
82	CMD_STAT_RESOURCE_BUSY = 0x06,
83	/* Required capability exceeds device limits: */
84	CMD_STAT_EXCEED_LIM = 0x08,
85	/* Resource is not in the appropriate state or ownership: */
86	CMD_STAT_BAD_RES_STATE = 0x09,
87	/* Index out of range: */
88	CMD_STAT_BAD_INDEX = 0x0a,
89	/* FW image corrupted: */
90	CMD_STAT_BAD_NVMEM = 0x0b,
91	/* Error in ICM mapping (e.g. not enough auxiliary ICM pages to execute command): */
92	CMD_STAT_ICM_ERROR = 0x0c,
93	/* Attempt to modify a QP/EE which is not in the presumed state: */
94	CMD_STAT_BAD_QP_STATE = 0x10,
95	/* Bad segment parameters (Address/Size): */
96	CMD_STAT_BAD_SEG_PARAM = 0x20,
97	/* Memory Region has Memory Windows bound to: */
98	CMD_STAT_REG_BOUND = 0x21,
99	/* HCA local attached memory not present: */
100	CMD_STAT_LAM_NOT_PRE = 0x22,
101	/* Bad management packet (silently discarded): */
102	CMD_STAT_BAD_PKT = 0x30,
103	/* More outstanding CQEs in CQ than new CQ size: */
104	CMD_STAT_BAD_SIZE = 0x40,
105	/* Multi Function device support required: */
106	CMD_STAT_MULTI_FUNC_REQ = 0x50,
107};
108
109enum {
110	HCR_IN_PARAM_OFFSET = 0x00,
111	HCR_IN_MODIFIER_OFFSET = 0x08,
112	HCR_OUT_PARAM_OFFSET = 0x0c,
113	HCR_TOKEN_OFFSET = 0x14,
114	HCR_STATUS_OFFSET = 0x18,
115
116	HCR_OPMOD_SHIFT = 12,
117	HCR_T_BIT = 21,
118	HCR_E_BIT = 22,
119	HCR_GO_BIT = 23
120};
121/*
122 enum {
123 GO_BIT_TIMEOUT_MSECS	= 10000
124 };
125
126 enum mlx4_vlan_transition {
127 MLX4_VLAN_TRANSITION_VST_VST = 0,
128 MLX4_VLAN_TRANSITION_VST_VGT = 1,
129 MLX4_VLAN_TRANSITION_VGT_VST = 2,
130 MLX4_VLAN_TRANSITION_VGT_VGT = 3,
131 };
132
133 */
134struct mlx4_cmd_context {
135	struct completion done;
136	int result;
137	int next;
138	u64 out_param;
139	u16 token;
140	u8 fw_status;
141};
142/*
143 static int mlx4_master_process_vhcr(struct mlx4_priv *priv, int slave,
144 struct mlx4_vhcr_cmd *in_vhcr);
145 */
146static int mlx4_status_to_errno(u8 status) {
147	static const int trans_table[] =
148			{ [CMD_STAT_INTERNAL_ERR] = -EIO, [CMD_STAT_BAD_OP] = -EPERM,
149					[CMD_STAT_BAD_PARAM] = -EINVAL, [CMD_STAT_BAD_SYS_STATE
150							] = -ENXIO, [CMD_STAT_BAD_RESOURCE] = -EBADF,
151					[CMD_STAT_RESOURCE_BUSY] = -EBUSY, [CMD_STAT_EXCEED_LIM
152							] = -ENOMEM, [CMD_STAT_BAD_RES_STATE] = -EBADF,
153					[CMD_STAT_BAD_INDEX] = -EBADF, [CMD_STAT_BAD_NVMEM
154							] = -EFAULT, [CMD_STAT_ICM_ERROR] = -ENFILE,
155					[CMD_STAT_BAD_QP_STATE] = -EINVAL, [CMD_STAT_BAD_SEG_PARAM
156							] = -EFAULT, [CMD_STAT_REG_BOUND] = -EBUSY,
157					[CMD_STAT_LAM_NOT_PRE] = -EAGAIN, [CMD_STAT_BAD_PKT
158							] = -EINVAL, [CMD_STAT_BAD_SIZE] = -ENOMEM,
159					[CMD_STAT_MULTI_FUNC_REQ] = -EACCES, };
160
161	if (status >= ARRAY_SIZE(trans_table)
162			|| (status != CMD_STAT_OK && trans_table[status] == 0))
163		return -EIO;
164
165	return trans_table[status];
166}
167
168static const char *cmd_to_str(u16 cmd) {
169	switch (cmd) {
170	case MLX4_CMD_SYS_EN:
171		return "SYS_EN";
172	case MLX4_CMD_SYS_DIS:
173		return "SYS_DIS";
174	case MLX4_CMD_MAP_FA:
175		return "MAP_FA";
176	case MLX4_CMD_UNMAP_FA:
177		return "UNMAP_FA";
178	case MLX4_CMD_RUN_FW:
179		return "RUN_FW";
180	case MLX4_CMD_MOD_STAT_CFG:
181		return "MOD_STAT_CFG";
182	case MLX4_CMD_QUERY_DEV_CAP:
183		return "QUERY_DEV_CAP";
184	case MLX4_CMD_QUERY_FW:
185		return "QUERY_FW";
186	case MLX4_CMD_ENABLE_LAM:
187		return "ENABLE_LAM";
188	case MLX4_CMD_DISABLE_LAM:
189		return "DISABLE_LAM";
190	case MLX4_CMD_QUERY_DDR:
191		return "QUERY_DDR";
192	case MLX4_CMD_QUERY_ADAPTER:
193		return "QUERY_ADAPTER";
194	case MLX4_CMD_INIT_HCA:
195		return "INIT_HCA";
196	case MLX4_CMD_CLOSE_HCA:
197		return "CLOSE_HCA";
198	case MLX4_CMD_INIT_PORT:
199		return "INIT_PORT";
200	case MLX4_CMD_CLOSE_PORT:
201		return "CLOSE_PORT";
202	case MLX4_CMD_QUERY_HCA:
203		return "QUERY_HCA";
204	case MLX4_CMD_QUERY_PORT:
205		return "QUERY_PORT";
206	case MLX4_CMD_SENSE_PORT:
207		return "SENSE_PORT";
208	case MLX4_CMD_HW_HEALTH_CHECK:
209		return "HW_HEALTH_CHECK";
210	case MLX4_CMD_SET_PORT:
211		return "SET_PORT";
212	case MLX4_CMD_SET_NODE:
213		return "SET_NODE";
214	case MLX4_CMD_QUERY_FUNC:
215		return "QUERY_FUNC";
216	case MLX4_CMD_MAP_ICM:
217		return "MAP_ICM";
218	case MLX4_CMD_UNMAP_ICM:
219		return "UNMAP_ICM";
220	case MLX4_CMD_MAP_ICM_AUX:
221		return "MAP_ICM_AUX";
222	case MLX4_CMD_UNMAP_ICM_AUX:
223		return "UNMAP_ICM_AUX";
224	case MLX4_CMD_SET_ICM_SIZE:
225		return "SET_ICM_SIZE";
226		/*master notify fw on finish for slave's flr*/
227	case MLX4_CMD_INFORM_FLR_DONE:
228		return "INFORM_FLR_DONE";
229	case MLX4_CMD_GET_OP_REQ:
230		return "GET_OP_REQ";
231
232		/* TPT commands */
233	case MLX4_CMD_SW2HW_MPT:
234		return "SW2HW_MPT";
235	case MLX4_CMD_QUERY_MPT:
236		return "QUERY_MPT";
237	case MLX4_CMD_HW2SW_MPT:
238		return "HW2SW_MPT";
239	case MLX4_CMD_READ_MTT:
240		return "READ_MTT";
241	case MLX4_CMD_WRITE_MTT:
242		return "WRITE_MTT";
243	case MLX4_CMD_SYNC_TPT:
244		return "SYNC_TPT";
245
246		/* EQ commands */
247	case MLX4_CMD_MAP_EQ:
248		return "MAP_EQ";
249	case MLX4_CMD_SW2HW_EQ:
250		return "SW2HW_EQ";
251	case MLX4_CMD_HW2SW_EQ:
252		return "HW2SW_EQ";
253	case MLX4_CMD_QUERY_EQ:
254		return "QUERY_EQ";
255
256		/* CQ commands */
257	case MLX4_CMD_SW2HW_CQ:
258		return "SW2HW_CQ";
259	case MLX4_CMD_HW2SW_CQ:
260		return "HW2SW_CQ";
261	case MLX4_CMD_QUERY_CQ:
262		return "QUERY_CQ:";
263	case MLX4_CMD_MODIFY_CQ:
264		return "MODIFY_CQ:";
265
266		/* SRQ commands */
267	case MLX4_CMD_SW2HW_SRQ:
268		return "SW2HW_SRQ";
269	case MLX4_CMD_HW2SW_SRQ:
270		return "HW2SW_SRQ";
271	case MLX4_CMD_QUERY_SRQ:
272		return "QUERY_SRQ";
273	case MLX4_CMD_ARM_SRQ:
274		return "ARM_SRQ";
275
276		/* QP/EE commands */
277	case MLX4_CMD_RST2INIT_QP:
278		return "RST2INIT_QP";
279	case MLX4_CMD_INIT2RTR_QP:
280		return "INIT2RTR_QP";
281	case MLX4_CMD_RTR2RTS_QP:
282		return "RTR2RTS_QP";
283	case MLX4_CMD_RTS2RTS_QP:
284		return "RTS2RTS_QP";
285	case MLX4_CMD_SQERR2RTS_QP:
286		return "SQERR2RTS_QP";
287	case MLX4_CMD_2ERR_QP:
288		return "2ERR_QP";
289	case MLX4_CMD_RTS2SQD_QP:
290		return "RTS2SQD_QP";
291	case MLX4_CMD_SQD2SQD_QP:
292		return "SQD2SQD_QP";
293	case MLX4_CMD_SQD2RTS_QP:
294		return "SQD2RTS_QP";
295	case MLX4_CMD_2RST_QP:
296		return "2RST_QP";
297	case MLX4_CMD_QUERY_QP:
298		return "QUERY_QP";
299	case MLX4_CMD_INIT2INIT_QP:
300		return "INIT2INIT_QP";
301	case MLX4_CMD_SUSPEND_QP:
302		return "SUSPEND_QP";
303	case MLX4_CMD_UNSUSPEND_QP:
304		return "UNSUSPEND_QP";
305		/* special QP and management commands */
306	case MLX4_CMD_CONF_SPECIAL_QP:
307		return "CONF_SPECIAL_QP";
308	case MLX4_CMD_MAD_IFC:
309		return "MAD_IFC";
310
311		/* multicast commands */
312	case MLX4_CMD_READ_MCG:
313		return "READ_MCG";
314	case MLX4_CMD_WRITE_MCG:
315		return "WRITE_MCG";
316	case MLX4_CMD_MGID_HASH:
317		return "MGID_HASH";
318
319		/* miscellaneous commands */
320	case MLX4_CMD_DIAG_RPRT:
321		return "DIAG_RPRT";
322	case MLX4_CMD_NOP:
323		return "NOP";
324	case MLX4_CMD_ACCESS_MEM:
325		return "ACCESS_MEM";
326	case MLX4_CMD_SET_VEP:
327		return "SET_VEP";
328
329		/* Ethernet specific commands */
330	case MLX4_CMD_SET_VLAN_FLTR:
331		return "SET_VLAN_FLTR";
332	case MLX4_CMD_SET_MCAST_FLTR:
333		return "SET_MCAST_FLTR";
334	case MLX4_CMD_DUMP_ETH_STATS:
335		return "DUMP_ETH_STATS";
336
337		/* Communication channel commands */
338	case MLX4_CMD_ARM_COMM_CHANNEL:
339		return "ARM_COMM_CHANNEL";
340	case MLX4_CMD_GEN_EQE:
341		return "GEN_EQE";
342
343		/* virtual commands */
344	case MLX4_CMD_ALLOC_RES:
345		return "ALLOC_RES";
346	case MLX4_CMD_FREE_RES:
347		return "FREE_RES";
348	case MLX4_CMD_MCAST_ATTACH:
349		return "MCAST_ATTACH";
350	case MLX4_CMD_UCAST_ATTACH:
351		return "UCAST_ATTACH";
352	case MLX4_CMD_PROMISC:
353		return "PROMISC";
354	case MLX4_CMD_QUERY_FUNC_CAP:
355		return "QUERY_FUNC_CAP";
356	case MLX4_CMD_QP_ATTACH:
357		return "QP_ATTACH";
358
359		/* debug commands */
360	case MLX4_CMD_QUERY_DEBUG_MSG:
361		return "QUERY_DEBUG_MSG";
362	case MLX4_CMD_SET_DEBUG_MSG:
363		return "SET_DEBUG_MSG";
364
365		/* statistics commands */
366	case MLX4_CMD_QUERY_IF_STAT:
367		return "QUERY_IF_STAT";
368	case MLX4_CMD_SET_IF_STAT:
369		return "SET_IF_STAT";
370
371		/* register/delete flow steering network rules */
372	case MLX4_QP_FLOW_STEERING_ATTACH:
373		return "QP_FLOW_STEERING_ATTACH";
374	case MLX4_QP_FLOW_STEERING_DETACH:
375		return "QP_FLOW_STEERING_DETACH";
376	case MLX4_FLOW_STEERING_IB_UC_QP_RANGE:
377		return "FLOW_STEERING_IB_UC_QP_RANGE";
378	default:
379		return "OTHER";
380	}
381}
382/*
383 static u8 mlx4_errno_to_status(int errno)
384 {
385 switch (errno) {
386 case -EPERM:
387 return CMD_STAT_BAD_OP;
388 case -EINVAL:
389 return CMD_STAT_BAD_PARAM;
390 case -ENXIO:
391 return CMD_STAT_BAD_SYS_STATE;
392 case -EBUSY:
393 return CMD_STAT_RESOURCE_BUSY;
394 case -ENOMEM:
395 return CMD_STAT_EXCEED_LIM;
396 case -ENFILE:
397 return CMD_STAT_ICM_ERROR;
398 default:
399 return CMD_STAT_INTERNAL_ERR;
400 }
401 }
402
403 static int comm_pending(struct mlx4_priv *priv)
404 {
405 struct mlx4_priv *priv = mlx4_priv(dev);
406 u32 status = readl(&priv->mfunc.comm->slave_read);
407
408 return (swab32(status) >> 31) != priv->cmd.comm_toggle;
409 }
410
411 static void mlx4_comm_cmd_post(struct mlx4_priv *priv, u8 cmd, u16 param)
412 {
413 struct mlx4_priv *priv = mlx4_priv(dev);
414 u32 val;
415
416 priv->cmd.comm_toggle ^= 1;
417 val = param | (cmd << 16) | (priv->cmd.comm_toggle << 31);
418 __raw_writel((__force u32) cpu_to_be32(val),
419 &priv->mfunc.comm->slave_write);
420 mmiowb();
421 }
422
423 static int mlx4_comm_cmd_poll(struct mlx4_priv *priv, u8 cmd, u16 param,
424 unsigned long timeout)
425 {
426 struct mlx4_priv *priv = mlx4_priv(dev);
427 unsigned long end;
428 int err = 0;
429 int ret_from_pending = 0;
430
431 First, verify that the master reports correct status
432 if (comm_pending(dev)) {
433 MLX4_DEBUG( "Communication channel is not idle."
434 "my toggle is %d (cmd:0x%x)\n",
435 priv->cmd.comm_toggle, cmd);
436 return -EAGAIN;
437 }
438
439 Write command
440 down(&priv->cmd.poll_sem);
441 mlx4_comm_cmd_post(dev, cmd, param);
442
443 end = msecs_to_jiffies(timeout) + jiffies;
444 while (comm_pending(dev) && time_before(jiffies, end))
445 cond_resched();
446 ret_from_pending = comm_pending(dev);
447 if (ret_from_pending) {
448 check if the slave is trying to boot in the middle of
449 * FLR process. The only non-zero result in the RESET command
450 * is MLX4_DELAY_RESET_SLAVE
451 if ((MLX4_COMM_CMD_RESET == cmd)) {
452 MLX4_DEBUG( "Got slave FLRed from Communication"
453 " channel (ret:0x%x)\n", ret_from_pending);
454 err = MLX4_DELAY_RESET_SLAVE;
455 } else {
456 MLX4_DEBUG( "Communication channel timed out\n");
457 err = -ETIMEDOUT;
458 }
459 }
460
461 up(&priv->cmd.poll_sem);
462 return err;
463 }
464
465 static int mlx4_comm_cmd_wait(struct mlx4_priv *priv, u8 op,
466 u16 param, unsigned long timeout)
467 {
468 struct mlx4_cmd *cmd = &mlx4_priv(dev)->cmd;
469 struct mlx4_cmd_context *context;
470 unsigned long end;
471 int err = 0;
472
473 down(&cmd->event_sem);
474
475 end = msecs_to_jiffies(timeout) + jiffies;
476 while (comm_pending(dev) && time_before(jiffies, end))
477 cond_resched();
478 if (comm_pending(dev)) {
479 MLX4_DEBUG( "mlx4_comm_cmd_wait: Comm channel "
480 "is not idle. My toggle is %d (op: 0x%x)\n",
481 mlx4_priv(dev)->cmd.comm_toggle, op);
482 up(&cmd->event_sem);
483 return -EAGAIN;
484 }
485
486 spin_lock(&cmd->context_lock);
487 BUG_ON(cmd->free_head < 0);
488 context = &cmd->context[cmd->free_head];
489 context->token += cmd->token_mask + 1;
490 cmd->free_head = context->next;
491 spin_unlock(&cmd->context_lock);
492
493 init_completion(&context->done);
494
495 mlx4_comm_cmd_post(dev, op, param);
496
497 In slave, wait unconditionally for completion
498 wait_for_completion(&context->done);
499
500 err = context->result;
501 if (err && context->fw_status != CMD_STAT_MULTI_FUNC_REQ) {
502 MLX4_DEBUG( "command 0x%x failed: fw status = 0x%x\n",
503 op, context->fw_status);
504 goto out;
505 }
506
507 out:
508 wait for comm channel ready
509 * this is necessary for prevention the race
510 * when switching between event to polling mode
511
512 end = msecs_to_jiffies(timeout) + jiffies;
513 while (comm_pending(dev) && time_before(jiffies, end))
514 cond_resched();
515
516 spin_lock(&cmd->context_lock);
517 context->next = cmd->free_head;
518 cmd->free_head = context - cmd->context;
519 spin_unlock(&cmd->context_lock);
520
521 up(&cmd->event_sem);
522 return err;
523 }
524
525 int mlx4_comm_cmd(struct mlx4_priv *priv, u8 cmd, u16 param,
526 unsigned long timeout)
527 {
528 if (mlx4_priv(dev)->cmd.use_events)
529 return mlx4_comm_cmd_wait(dev, cmd, param, timeout);
530 return mlx4_comm_cmd_poll(dev, cmd, param, timeout);
531 }
532 */
533static int cmd_pending(struct mlx4_priv *priv) {
534	u32 status;
535
536	if (pci_channel_offline())
537		return -EIO;
538
539	status = __raw_readl(priv->cmd.hcr + HCR_STATUS_OFFSET);
540
541	/*MLX4_DEBUG("status: %x\n",status);*/
542
543	return (status & swab32(1 << HCR_GO_BIT))
544			|| (priv->cmd.toggle == !!(status & swab32(1 << HCR_T_BIT)));
545}
546
547static int get_status(struct mlx4_priv *priv, u32 *status, int *go_bit,
548		int *t_bit) {
549	if (pci_channel_offline())
550		return -EIO;
551
552	*status = __raw_readl(priv->cmd.hcr + HCR_STATUS_OFFSET);
553	*t_bit = !!(*status & swab32(1 << HCR_T_BIT));
554	*go_bit = !!(*status & swab32(1 << HCR_GO_BIT));
555
556	return 0;
557}
558
559static int mlx4_cmd_post(struct mlx4_priv *pdev, struct timespec *ts1,
560		u64 in_param, u64 out_param, u32 in_modifier, u8 op_modifier, u16 op,
561		u16 token, int event) {
562	struct mlx4_cmd *cmd = &pdev->cmd;
563	u32 *hcr = cmd->hcr;
564	int ret = -EAGAIN;
565	unsigned long end = 0;
566	/*errval_t err;*/
567	/*int err, go_bit = 0, t_bit = 0;
568	 u32 status = 0;*/
569
570	/*mutex_lock(&cmd->hcr_mutex);*/
571
572	if (pci_channel_offline()) {
573		/*
574		 * Device is going through error recovery
575		 * and cannot accept commands.
576		 */
577		ret = -EIO;
578		goto out;
579	}
580	/*
581	 end = jiffies;
582	 if (event)
583	 end += msecs_to_jiffies(GO_BIT_TIMEOUT_MSECS);
584	 */
585
586	/*TODO: replace "end" with a barrelfish timestamp*/
587	while (cmd_pending(pdev)) {
588		if (pci_channel_offline()) {
589
590			ret = -EIO;
591			goto out;
592		}
593
594		if (end > 10000) {
595			MLX4_DEBUG("%s:cmd_pending failed\n", __func__);
596			goto out;
597		}
598		end++;
599	}
600
601	/*err = sys_debug_flush_cache();
602	 assert(err_is_ok(err));*/
603
604	/*	MLX4_DEBUG("hcr + 0: %d\n", (u32 ) cpu_to_be32(in_param >> 32));
605	 MLX4_DEBUG("hcr + 1: %d\n", (u32 ) cpu_to_be32(in_param & 0xfffffffful));
606	 MLX4_DEBUG("hcr + 2: %d\n", (u32 ) cpu_to_be32(in_modifier));
607	 MLX4_DEBUG("hcr + 3: %d\n", (u32 ) cpu_to_be32(out_param >> 32));
608	 MLX4_DEBUG("hcr + 4: %d\n", (u32 ) cpu_to_be32(out_param & 0xfffffffful));
609	 MLX4_DEBUG("hcr + 5: %d\n", (u32 ) cpu_to_be32(token << 16));
610	 MLX4_DEBUG("hcr + 6: %d\n",
611	 (u32 ) cpu_to_be32(
612	 (1 << HCR_GO_BIT) | (cmd->toggle << HCR_T_BIT)
613	 | (event ? (1 << HCR_E_BIT) : 0)
614	 | (op_modifier << HCR_OPMOD_SHIFT) | op));*/
615
616	/*
617	 * We use writel (instead of something like memcpy_toio)
618	 * because writes of less than 32 bits to the HCR don't work
619	 * (and some architectures such as ia64 implement memcpy_toio
620	 * in terms of writeb).
621	 */
622	__raw_writel((u32) cpu_to_be32(in_param >> 32), hcr + 0);
623	__raw_writel((u32) cpu_to_be32(in_param & 0xfffffffful), hcr + 1);
624	__raw_writel((u32) cpu_to_be32(in_modifier), hcr + 2);
625	__raw_writel((u32) cpu_to_be32(out_param >> 32), hcr + 3);
626	__raw_writel((u32) cpu_to_be32(out_param & 0xfffffffful), hcr + 4);
627	__raw_writel((u32) cpu_to_be32(token << 16), hcr + 5);
628
629	/*	if (ts1)
630	 ktime_get_ts(ts1);*/
631
632	/* __raw_writel may not order writes. */
633	__asm volatile("" ::: "memory");
634
635	__raw_writel(
636			(u32) cpu_to_be32(
637					(1 << HCR_GO_BIT) | (cmd->toggle << HCR_T_BIT)
638							| (event ? (1 << HCR_E_BIT) : 0)
639							| (op_modifier << HCR_OPMOD_SHIFT) | op), hcr + 6);
640
641	/*
642	 * Make sure that our HCR writes don't get mixed in with
643	 * writes from another CPU starting a FW command.
644	 */
645	/*	mmiowb();
646
647	 */
648	cmd->toggle = cmd->toggle ^ 1;
649	ret = 0;
650
651	/*printf("Posted command %s (0x%x): ret=%d, "
652	 "in_param=0x%llx, in_mod=0x%x, op_mod=0x%x, "
653	 "get_status err=, status_reg=, go_bit=, "
654	 "t_bit=, toggle=0x%x\n", cmd_to_str(op), op, ret,
655	 (unsigned long long) in_param, in_modifier, op_modifier, err,
656	 status, go_bit, t_bit,cmd->toggle);*/
657
658	out:
659	/*	if (ret) {
660	 err = get_status(dev, &status, &go_bit, &t_bit);
661	 MLX4_DEBUG( "Could not post command %s (0x%x): ret=%d, "
662	 "in_param=0x%llx, in_mod=0x%x, op_mod=0x%x, "
663	 "get_status err=%d, status_reg=0x%x, go_bit=%d, "
664	 "t_bit=%d, toggle=0x%x\n", cmd_to_str(op), op, ret,
665	 (unsigned long long) in_param, in_modifier, op_modifier, err, status,
666	 go_bit, t_bit, cmd->toggle);
667	 }
668	 mutex_unlock(&cmd->hcr_mutex);*/
669	return ret;
670}
671/*
672 static int mlx4_slave_cmd(struct mlx4_priv *priv, u64 in_param, u64 *out_param,
673 int out_is_imm, u32 in_modifier, u8 op_modifier,
674 u16 op, unsigned long timeout)
675 {
676 struct mlx4_priv *priv = mlx4_priv(dev);
677 struct mlx4_vhcr_cmd *vhcr = priv->mfunc.vhcr;
678 int ret;
679
680 mutex_lock(&priv->cmd.slave_cmd_mutex);
681
682 vhcr->in_param = cpu_to_be64(in_param);
683 vhcr->out_param = out_param ? cpu_to_be64(*out_param) : 0;
684 vhcr->in_modifier = cpu_to_be32(in_modifier);
685 vhcr->opcode = cpu_to_be16((((u16) op_modifier) << 12) | (op & 0xfff));
686 vhcr->token = cpu_to_be16(CMD_POLL_TOKEN);
687 vhcr->status = 0;
688 vhcr->flags = !!(priv->cmd.use_events) << 6;
689
690 if (mlx4_is_master(dev)) {
691 ret = mlx4_master_process_vhcr(dev, dev->caps.function, vhcr);
692 if (!ret) {
693 if (out_is_imm) {
694 if (out_param)
695 *out_param =
696 be64_to_cpu(vhcr->out_param);
697 else {
698 MLX4_DEBUG( "response expected while"
699 "output mailbox is NULL for "
700 "command 0x%x\n", op);
701 vhcr->status = CMD_STAT_BAD_PARAM;
702 }
703 }
704 ret = mlx4_status_to_errno(vhcr->status);
705 }
706 } else {
707 ret = mlx4_comm_cmd(dev, MLX4_COMM_CMD_VHCR_POST, 0,
708 MLX4_COMM_TIME + timeout);
709 if (!ret) {
710 if (out_is_imm) {
711 if (out_param)
712 *out_param =
713 be64_to_cpu(vhcr->out_param);
714 else {
715 MLX4_DEBUG( "response expected while"
716 "output mailbox is NULL for "
717 "command 0x%x\n", op);
718 vhcr->status = CMD_STAT_BAD_PARAM;
719 }
720 }
721 ret = mlx4_status_to_errno(vhcr->status);
722 } else
723 MLX4_DEBUG( "failed execution of VHCR_POST command"
724 "opcode %s (0x%x)\n", cmd_to_str(op), op);
725 }
726
727 mutex_unlock(&priv->cmd.slave_cmd_mutex);
728 return ret;
729 }
730 */
731static int mlx4_cmd_poll(struct mlx4_priv *priv, u64 in_param, u64 *out_param,
732		int out_is_imm, u32 in_modifier, u8 op_modifier, u16 op,
733		unsigned long timeout) {
734	/*struct mlx4_priv *priv = mlx4_priv(dev);*/
735	void *hcr = priv->cmd.hcr;
736	int err = 0;
737	unsigned long end = 0;
738	u32 stat;
739
740	/*down(&priv->cmd.poll_sem);
741
742	 if (pci_channel_offline(dev->pdev)) {
743
744	 *Device
745	 is going
746	 through error
747	 recovery * and
748	 cannot accept
749	 commands.
750
751	 err = -EIO;
752	 goto out;
753	 }
754	 */
755	err = mlx4_cmd_post(priv, NULL, in_param, out_param ? *out_param : 0,
756			in_modifier, op_modifier, op, CMD_POLL_TOKEN, 0);
757	if (err)
758		goto out;
759
760	/*MLX4_DEBUG("command %s (0x%x) \n", cmd_to_str(op), op);*/
761
762	/*TODO: replace "end" with a barrelfish timestamp*/
763	while (cmd_pending(priv) && end < 10000) {
764		if (pci_channel_offline()) {
765			/*
766			 * Device is going through error recovery
767			 * and cannot accept commands.
768			 */
769			err = -EIO;
770			goto out;
771		}
772		barrelfish_usleep(1000);
773		/*MLX4_DEBUG("command %lu\n", end);*/
774		end++;
775	}
776	if (cmd_pending(priv)) {
777		MLX4_DEBUG("command %s (0x%x) timed out (go bit not cleared)\n",
778				cmd_to_str(op), op);
779		err = -ETIMEDOUT;
780		goto out;
781	}
782
783	if (out_is_imm)
784	*out_param = (u64)
785	be32_to_cpu(
786			(__force __be32) __raw_readl(hcr + HCR_OUT_PARAM_OFFSET)) << 32 |
787	(u64) be32_to_cpu((__force __be32)
788			__raw_readl(hcr + HCR_OUT_PARAM_OFFSET + 4));
789	stat = be32_to_cpu((__force __be32) __raw_readl(hcr + HCR_STATUS_OFFSET)) >> 24;
790	err = mlx4_status_to_errno(stat);
791	if (err)
792		MLX4_DEBUG("command %s (0x%x) failed: fw status = 0x%x\n",
793				cmd_to_str(op), op, stat);
794
795	out: /*up(&priv->cmd.poll_sem);*/
796	return err;
797}
798
799void mlx4_cmd_event(struct mlx4_priv *priv, u16 token, u8 status, u64 out_param) {
800	struct mlx4_cmd_context *context = &priv->cmd.context[token
801			& priv->cmd.token_mask];
802
803	/*previously timed
804	 out command
805	 completing at
806	 long last*/
807	if (token != context->token)
808		return;
809
810	context->fw_status = status;
811	context->result = mlx4_status_to_errno(status);
812	context->out_param = out_param;
813
814	got_irq = true;
815}
816
817static inline int mlx4_cmd_wait(struct mlx4_priv *priv, u64 in_param,
818		u64 *out_param, int out_is_imm, u32 in_modifier, u8 op_modifier, u16 op,
819		unsigned long timeout) {
820	struct mlx4_cmd *cmd = &priv->cmd;
821	struct mlx4_cmd_context *context;
822	int err = 0;
823	int go_bit = 0, t_bit = 0, stat_err;
824	u32 status = 0;
825	struct timespec ts1/*, ts2*/;
826	/*ktime_t t1, t2, delta;
827	 s64 ds;*/
828	uint64_t current, ticks_per_msec;
829
830	if (out_is_imm && !out_param)
831		return -EINVAL;
832
833	/*down(&cmd->event_sem);
834
835	 spin_lock(&cmd->context_lock);
836	 BUG_ON(cmd->free_head < 0);*/
837	context = &cmd->context[cmd->free_head];
838	context->token += cmd->token_mask + 1;
839	cmd->free_head = context->next;
840	/*spin_unlock(&cmd->context_lock);*/
841
842	/*init_completion(&context->done);*/
843
844	err = mlx4_cmd_post(priv, &ts1, in_param, out_param ? *out_param : 0,
845			in_modifier, op_modifier, op, context->token, 1);
846	if (err)
847		goto out;
848
849	MLX4_DEBUG("command %s (0x%x) \n", cmd_to_str(op), op);
850
851	got_irq = false;
852	current = rdtsc();
853	sys_debug_get_tsc_per_ms(&ticks_per_msec);
854	while (!got_irq) {
855		if (rdtsc() >= current + timeout * ticks_per_msec) {
856			stat_err = get_status(priv, &status, &go_bit, &t_bit);
857			MLX4_DEBUG("command %s (0x%x) timed out: in_param=0x%llx, "
858					"in_mod=0x%x, op_mod=0x%x, get_status err=%d, "
859					"status_reg=0x%x, go_bit=%d, t_bit=%d, toggle=0x%x\n",
860					cmd_to_str(op), op, (unsigned long long ) in_param,
861					in_modifier, op_modifier, stat_err, status, go_bit, t_bit,
862					priv->cmd.toggle);
863			err = -EBUSY;
864			goto out;
865		}
866		event_dispatch_non_block(get_default_waitset());
867	}
868
869	/*if (mlx4_debug_level & MLX4_DEBUG_MASK_CMD_TIME) {
870	 ktime_get_ts(&ts2);
871	 t1 = timespec_to_ktime(ts1);
872	 t2 = timespec_to_ktime(ts2);
873	 delta = ktime_sub(t2, t1);
874	 ds = ktime_to_ns(delta);
875	 pr_info("mlx4: fw exec time for %s is %lld nsec\n", cmd_to_str(op),
876	 (long long) ds);
877	 }*/
878
879	err = context->result;
880	if (err) {
881		MLX4_DEBUG("command %s (0x%x) failed: in_param=0x%llx, "
882				"in_mod=0x%x, op_mod=0x%x, fw status = 0x%x\n", cmd_to_str(op),
883				op, (unsigned long long ) in_param, in_modifier, op_modifier,
884				context->fw_status);
885
886		switch (context->fw_status) {
887		case CMD_STAT_BAD_PARAM:
888			MLX4_DEBUG("Parameter is not supported, "
889					"parameter is out of range\n");
890			break;
891		case CMD_STAT_EXCEED_LIM:
892			MLX4_DEBUG("Required capability exceeded "
893					"device limits\n");
894			break;
895		default:
896			break;
897		}
898		goto out;
899	}
900
901	if (out_is_imm)
902		*out_param = context->out_param;
903
904	out: /*spin_lock(&cmd->context_lock);*/
905	context->next = cmd->free_head;
906	cmd->free_head = context - cmd->context;
907	/*spin_unlock(&cmd->context_lock);*/
908
909	/*up(&cmd->event_sem);*/
910	return err;
911}
912
913int __mlx4_cmd(struct mlx4_dev *dev, uint64_t in_param, uint64_t *out_param,
914		int out_is_imm, uint32_t in_modifier, uint32_t op_modifier, uint16_t op,
915		unsigned long timeout, int native) {
916	/*
917	 if (pci_channel_offline(dev->pdev))
918	 return -EIO;
919	 */
920	struct mlx4_priv *priv = mlx4_priv(dev);
921
922	/*if (priv->cmd.use_events)
923	 return mlx4_cmd_wait(priv, in_param, out_param, out_is_imm, in_modifier,
924	 op_modifier, op, timeout);
925	 else*/
926	return mlx4_cmd_poll(priv, in_param, out_param, out_is_imm, in_modifier,
927			op_modifier, op, timeout);
928}
929/*
930 EXPORT_SYMBOL_GPL(__mlx4_cmd);
931
932
933 static int mlx4_ARM_COMM_CHANNEL(struct mlx4_priv *priv)
934 {
935 return mlx4_cmd(dev, 0, 0, 0, MLX4_CMD_ARM_COMM_CHANNEL,
936 MLX4_CMD_TIME_CLASS_B, MLX4_CMD_NATIVE);
937 }
938
939 static int mlx4_ACCESS_MEM(struct mlx4_priv *priv, u64 master_addr,
940 int slave, u64 slave_addr,
941 int size, int is_read)
942 {
943 u64 in_param;
944 u64 out_param;
945
946 if ((slave_addr & 0xfff) | (master_addr & 0xfff) |
947 (slave & ~0x7f) | (size & 0xff)) {
948 MLX4_DEBUG( "Bad access mem params - slave_addr:0x%llx "
949 "master_addr:0x%llx slave_id:%d size:%d\n",
950 (unsigned long long) slave_addr, (unsigned long long) master_addr, slave, size);
951 return -EINVAL;
952 }
953
954 if (is_read) {
955 in_param = (u64) slave | slave_addr;
956 out_param = (u64) dev->caps.function | master_addr;
957 } else {
958 in_param = (u64) dev->caps.function | master_addr;
959 out_param = (u64) slave | slave_addr;
960 }
961
962 return mlx4_cmd_imm(dev, in_param, &out_param, size, 0,
963 MLX4_CMD_ACCESS_MEM,
964 MLX4_CMD_TIME_CLASS_A, MLX4_CMD_NATIVE);
965 }
966
967 static int query_pkey_block(struct mlx4_priv *priv, u8 port, u16 index, u16 *pkey,
968 struct mlx4_cmd_mailbox *inbox,
969 struct mlx4_cmd_mailbox *outbox)
970 {
971 struct ib_smp *in_mad = (struct ib_smp *)(inbox->buf);
972 struct ib_smp *out_mad = (struct ib_smp *)(outbox->buf);
973 int err;
974 int i;
975
976 if (index & 0x1f)
977 return -EINVAL;
978
979 in_mad->attr_mod = cpu_to_be32(index / 32);
980
981 err = mlx4_cmd_box(dev, inbox->dma, outbox->dma, port, 3,
982 MLX4_CMD_MAD_IFC, MLX4_CMD_TIME_CLASS_C,
983 MLX4_CMD_NATIVE);
984 if (err)
985 return err;
986
987 for (i = 0; i < 32; ++i)
988 pkey[i] = be16_to_cpu(((__be16 *) out_mad->data)[i]);
989
990 return err;
991 }
992
993 static int get_full_pkey_table(struct mlx4_priv *priv, u8 port, u16 *table,
994 struct mlx4_cmd_mailbox *inbox,
995 struct mlx4_cmd_mailbox *outbox)
996 {
997 int i;
998 int err;
999
1000 for (i = 0; i < dev->caps.pkey_table_len[port]; i += 32) {
1001 err = query_pkey_block(dev, port, i, table + i, inbox, outbox);
1002 if (err)
1003 return err;
1004 }
1005
1006 return 0;
1007 }
1008 #define PORT_CAPABILITY_LOCATION_IN_SMP 20
1009 #define PORT_STATE_OFFSET 32
1010
1011 static enum ib_port_state vf_port_state(struct mlx4_priv *priv, int port, int vf)
1012 {
1013 if (mlx4_get_slave_port_state(dev, vf, port) == SLAVE_PORT_UP)
1014 return IB_PORT_ACTIVE;
1015 else
1016 return IB_PORT_DOWN;
1017 }
1018
1019 static int mlx4_MAD_IFC_wrapper(struct mlx4_priv *priv, int slave,
1020 struct mlx4_vhcr *vhcr,
1021 struct mlx4_cmd_mailbox *inbox,
1022 struct mlx4_cmd_mailbox *outbox,
1023 struct mlx4_cmd_info *cmd)
1024 {
1025 struct ib_smp *smp = inbox->buf;
1026 u32 index;
1027 u8 port;
1028 u16 *table;
1029 int err;
1030 int vidx, pidx;
1031 struct mlx4_priv *priv = mlx4_priv(dev);
1032 struct ib_smp *outsmp = outbox->buf;
1033 __be16 *outtab = (__be16 *)(outsmp->data);
1034 __be32 slave_cap_mask;
1035 __be64 slave_node_guid;
1036 port = vhcr->in_modifier;
1037
1038 if (smp->base_version == 1 &&
1039 smp->mgmt_class == IB_MGMT_CLASS_SUBN_LID_ROUTED &&
1040 smp->class_version == 1) {
1041 if (smp->method	== IB_MGMT_METHOD_GET) {
1042 if (smp->attr_id == IB_SMP_ATTR_PKEY_TABLE) {
1043 index = be32_to_cpu(smp->attr_mod);
1044 if (port < 1 || port > dev->caps.num_ports)
1045 return -EINVAL;
1046 table = kcalloc(dev->caps.pkey_table_len[port], sizeof *table, GFP_KERNEL);
1047 if (!table)
1048 return -ENOMEM;
1049 need to get the full pkey table because the paravirtualized
1050 * pkeys may be scattered among several pkey blocks.
1051
1052 err = get_full_pkey_table(dev, port, table, inbox, outbox);
1053 if (!err) {
1054 for (vidx = index * 32; vidx < (index + 1) * 32; ++vidx) {
1055 pidx = priv->virt2phys_pkey[slave][port - 1][vidx];
1056 outtab[vidx % 32] = cpu_to_be16(table[pidx]);
1057 }
1058 }
1059 kfree(table);
1060 return err;
1061 }
1062 if (smp->attr_id == IB_SMP_ATTR_PORT_INFO) {
1063 get the slave specific caps:
1064 do the command
1065 err = mlx4_cmd_box(dev, inbox->dma, outbox->dma,
1066 vhcr->in_modifier, vhcr->op_modifier,
1067 vhcr->op, MLX4_CMD_TIME_CLASS_C, MLX4_CMD_NATIVE);
1068 modify the response for slaves
1069 if (!err && slave != mlx4_master_func_num(dev)) {
1070 u8 *state = outsmp->data + PORT_STATE_OFFSET;
1071
1072 *state = (*state & 0xf0) | vf_port_state(dev, port, slave);
1073 slave_cap_mask = priv->mfunc.master.slave_state[slave].ib_cap_mask[port];
1074 memcpy(outsmp->data + PORT_CAPABILITY_LOCATION_IN_SMP, &slave_cap_mask, 4);
1075 }
1076 return err;
1077 }
1078 if (smp->attr_id == IB_SMP_ATTR_GUID_INFO) {
1079 compute slave's gid block
1080 smp->attr_mod = cpu_to_be32(slave / 8);
1081 execute cmd
1082 err = mlx4_cmd_box(dev, inbox->dma, outbox->dma,
1083 vhcr->in_modifier, vhcr->op_modifier,
1084 vhcr->op, MLX4_CMD_TIME_CLASS_C, MLX4_CMD_NATIVE);
1085 if (!err) {
1086 if needed, move slave gid to index 0
1087 if (slave % 8)
1088 memcpy(outsmp->data,
1089 outsmp->data + (slave % 8) * 8, 8);
1090 delete all other gids
1091 memset(outsmp->data + 8, 0, 56);
1092 }
1093 return err;
1094 }
1095 if (smp->attr_id == IB_SMP_ATTR_NODE_INFO) {
1096 err = mlx4_cmd_box(dev, inbox->dma, outbox->dma,
1097 vhcr->in_modifier, vhcr->op_modifier,
1098 vhcr->op, MLX4_CMD_TIME_CLASS_C, MLX4_CMD_NATIVE);
1099 if (!err) {
1100 slave_node_guid =  mlx4_get_slave_node_guid(dev, slave);
1101 memcpy(outsmp->data + 12, &slave_node_guid, 8);
1102 }
1103 return err;
1104 }
1105 }
1106 }
1107 if (slave != mlx4_master_func_num(dev) &&
1108 ((smp->mgmt_class == IB_MGMT_CLASS_SUBN_DIRECTED_ROUTE) ||
1109 (smp->mgmt_class == IB_MGMT_CLASS_SUBN_LID_ROUTED &&
1110 smp->method == IB_MGMT_METHOD_SET))) {
1111 MLX4_DEBUG( "slave %d is trying to execute a Subnet MGMT MAD, "
1112 "class 0x%x, method 0x%x for attr 0x%x. Rejecting\n",
1113 slave, smp->method, smp->mgmt_class,
1114 be16_to_cpu(smp->attr_id));
1115 return -EPERM;
1116 }
1117 default:
1118 return mlx4_cmd_box(dev, inbox->dma, outbox->dma,
1119 vhcr->in_modifier, vhcr->op_modifier,
1120 vhcr->op, MLX4_CMD_TIME_CLASS_C, MLX4_CMD_NATIVE);
1121 }
1122
1123 static int MLX4_CMD_DIAG_RPRT_wrapper(struct mlx4_priv *priv, int slave,
1124 struct mlx4_vhcr *vhcr,
1125 struct mlx4_cmd_mailbox *inbox,
1126 struct mlx4_cmd_mailbox *outbox,
1127 struct mlx4_cmd_info *cmd)
1128 {
1129 return -EPERM;
1130 }
1131
1132 static int MLX4_CMD_UPDATE_QP_wrapper(struct mlx4_priv *priv, int slave,
1133 struct mlx4_vhcr *vhcr,
1134 struct mlx4_cmd_mailbox *inbox,
1135 struct mlx4_cmd_mailbox *outbox,
1136 struct mlx4_cmd_info *cmd)
1137 {
1138 return -EPERM;
1139 }
1140
1141 int mlx4_DMA_wrapper(struct mlx4_priv *priv, int slave,
1142 struct mlx4_vhcr *vhcr,
1143 struct mlx4_cmd_mailbox *inbox,
1144 struct mlx4_cmd_mailbox *outbox,
1145 struct mlx4_cmd_info *cmd)
1146 {
1147 u64 in_param;
1148 u64 out_param;
1149 int err;
1150
1151 in_param = cmd->has_inbox ? (u64) inbox->dma : vhcr->in_param;
1152 out_param = cmd->has_outbox ? (u64) outbox->dma : vhcr->out_param;
1153 if (cmd->encode_slave_id) {
1154 in_param &= 0xffffffffffffff00ll;
1155 in_param |= slave;
1156 }
1157
1158 err = __mlx4_cmd(dev, in_param, &out_param, cmd->out_is_imm,
1159 vhcr->in_modifier, vhcr->op_modifier, vhcr->op,
1160 MLX4_CMD_TIME_CLASS_A, MLX4_CMD_NATIVE);
1161
1162 if (cmd->out_is_imm)
1163 vhcr->out_param = out_param;
1164
1165 return err;
1166 }
1167
1168 static struct mlx4_cmd_info cmd_info[] = {
1169 {
1170 .opcode = MLX4_CMD_QUERY_FW,
1171 .has_inbox = false,
1172 .has_outbox = true,
1173 .out_is_imm = false,
1174 .encode_slave_id = false,
1175 .verify = NULL,
1176 .wrapper = mlx4_QUERY_FW_wrapper
1177 },
1178 {
1179 .opcode = MLX4_CMD_QUERY_HCA,
1180 .has_inbox = false,
1181 .has_outbox = true,
1182 .out_is_imm = false,
1183 .encode_slave_id = false,
1184 .verify = NULL,
1185 .wrapper = NULL
1186 },
1187 {
1188 .opcode = MLX4_CMD_QUERY_DEV_CAP,
1189 .has_inbox = false,
1190 .has_outbox = true,
1191 .out_is_imm = false,
1192 .encode_slave_id = false,
1193 .verify = NULL,
1194 .wrapper = mlx4_QUERY_DEV_CAP_wrapper
1195 },
1196 {
1197 .opcode = MLX4_CMD_QUERY_FUNC_CAP,
1198 .has_inbox = false,
1199 .has_outbox = true,
1200 .out_is_imm = false,
1201 .encode_slave_id = false,
1202 .verify = NULL,
1203 .wrapper = mlx4_QUERY_FUNC_CAP_wrapper
1204 },
1205 {
1206 .opcode = MLX4_CMD_QUERY_ADAPTER,
1207 .has_inbox = false,
1208 .has_outbox = true,
1209 .out_is_imm = false,
1210 .encode_slave_id = false,
1211 .verify = NULL,
1212 .wrapper = NULL
1213 },
1214 {
1215 .opcode = MLX4_CMD_INIT_PORT,
1216 .has_inbox = false,
1217 .has_outbox = false,
1218 .out_is_imm = false,
1219 .encode_slave_id = false,
1220 .verify = NULL,
1221 .wrapper = mlx4_INIT_PORT_wrapper
1222 },
1223 {
1224 .opcode = MLX4_CMD_CLOSE_PORT,
1225 .has_inbox = false,
1226 .has_outbox = false,
1227 .out_is_imm  = false,
1228 .encode_slave_id = false,
1229 .verify = NULL,
1230 .wrapper = mlx4_CLOSE_PORT_wrapper
1231 },
1232 {
1233 .opcode = MLX4_CMD_QUERY_PORT,
1234 .has_inbox = false,
1235 .has_outbox = true,
1236 .out_is_imm = false,
1237 .encode_slave_id = false,
1238 .verify = NULL,
1239 .wrapper = mlx4_QUERY_PORT_wrapper
1240 },
1241 {
1242 .opcode = MLX4_CMD_SET_PORT,
1243 .has_inbox = true,
1244 .has_outbox = false,
1245 .out_is_imm = false,
1246 .encode_slave_id = false,
1247 .verify = NULL,
1248 .wrapper = mlx4_SET_PORT_wrapper
1249 },
1250 {
1251 .opcode = MLX4_CMD_MAP_EQ,
1252 .has_inbox = false,
1253 .has_outbox = false,
1254 .out_is_imm = false,
1255 .encode_slave_id = false,
1256 .verify = NULL,
1257 .wrapper = mlx4_MAP_EQ_wrapper
1258 },
1259 {
1260 .opcode = MLX4_CMD_SW2HW_EQ,
1261 .has_inbox = true,
1262 .has_outbox = false,
1263 .out_is_imm = false,
1264 .encode_slave_id = true,
1265 .verify = NULL,
1266 .wrapper = mlx4_SW2HW_EQ_wrapper
1267 },
1268 {
1269 .opcode = MLX4_CMD_HW_HEALTH_CHECK,
1270 .has_inbox = false,
1271 .has_outbox = false,
1272 .out_is_imm = false,
1273 .encode_slave_id = false,
1274 .verify = NULL,
1275 .wrapper = NULL
1276 },
1277 {
1278 .opcode = MLX4_CMD_DIAG_RPRT,
1279 .has_inbox = false,
1280 .has_outbox = false,
1281 .out_is_imm = false,
1282 .encode_slave_id = false,
1283 .skip_err_print = true,
1284 .verify = NULL,
1285 .wrapper = MLX4_CMD_DIAG_RPRT_wrapper
1286 },
1287 {
1288 .opcode = MLX4_CMD_NOP,
1289 .has_inbox = false,
1290 .has_outbox = false,
1291 .out_is_imm = false,
1292 .encode_slave_id = false,
1293 .verify = NULL,
1294 .wrapper = NULL
1295 },
1296 {
1297 .opcode = MLX4_CMD_ALLOC_RES,
1298 .has_inbox = false,
1299 .has_outbox = false,
1300 .out_is_imm = true,
1301 .encode_slave_id = false,
1302 .verify = NULL,
1303 .wrapper = mlx4_ALLOC_RES_wrapper
1304 },
1305 {
1306 .opcode = MLX4_CMD_FREE_RES,
1307 .has_inbox = false,
1308 .has_outbox = false,
1309 .out_is_imm = false,
1310 .encode_slave_id = false,
1311 .verify = NULL,
1312 .wrapper = mlx4_FREE_RES_wrapper
1313 },
1314 {
1315 .opcode = MLX4_CMD_SW2HW_MPT,
1316 .has_inbox = true,
1317 .has_outbox = false,
1318 .out_is_imm = false,
1319 .encode_slave_id = true,
1320 .verify = NULL,
1321 .wrapper = mlx4_SW2HW_MPT_wrapper
1322 },
1323 {
1324 .opcode = MLX4_CMD_QUERY_MPT,
1325 .has_inbox = false,
1326 .has_outbox = true,
1327 .out_is_imm = false,
1328 .encode_slave_id = false,
1329 .verify = NULL,
1330 .wrapper = mlx4_QUERY_MPT_wrapper
1331 },
1332 {
1333 .opcode = MLX4_CMD_HW2SW_MPT,
1334 .has_inbox = false,
1335 .has_outbox = false,
1336 .out_is_imm = false,
1337 .encode_slave_id = false,
1338 .verify = NULL,
1339 .wrapper = mlx4_HW2SW_MPT_wrapper
1340 },
1341 {
1342 .opcode = MLX4_CMD_READ_MTT,
1343 .has_inbox = false,
1344 .has_outbox = true,
1345 .out_is_imm = false,
1346 .encode_slave_id = false,
1347 .verify = NULL,
1348 .wrapper = NULL
1349 },
1350 {
1351 .opcode = MLX4_CMD_WRITE_MTT,
1352 .has_inbox = true,
1353 .has_outbox = false,
1354 .out_is_imm = false,
1355 .encode_slave_id = false,
1356 .verify = NULL,
1357 .wrapper = mlx4_WRITE_MTT_wrapper
1358 },
1359 {
1360 .opcode = MLX4_CMD_SYNC_TPT,
1361 .has_inbox = true,
1362 .has_outbox = false,
1363 .out_is_imm = false,
1364 .encode_slave_id = false,
1365 .verify = NULL,
1366 .wrapper = NULL
1367 },
1368 {
1369 .opcode = MLX4_CMD_HW2SW_EQ,
1370 .has_inbox = false,
1371 .has_outbox = true,
1372 .out_is_imm = false,
1373 .encode_slave_id = true,
1374 .verify = NULL,
1375 .wrapper = mlx4_HW2SW_EQ_wrapper
1376 },
1377 {
1378 .opcode = MLX4_CMD_QUERY_EQ,
1379 .has_inbox = false,
1380 .has_outbox = true,
1381 .out_is_imm = false,
1382 .encode_slave_id = true,
1383 .verify = NULL,
1384 .wrapper = mlx4_QUERY_EQ_wrapper
1385 },
1386 {
1387 .opcode = MLX4_CMD_SW2HW_CQ,
1388 .has_inbox = true,
1389 .has_outbox = false,
1390 .out_is_imm = false,
1391 .encode_slave_id = true,
1392 .verify = NULL,
1393 .wrapper = mlx4_SW2HW_CQ_wrapper
1394 },
1395 {
1396 .opcode = MLX4_CMD_HW2SW_CQ,
1397 .has_inbox = false,
1398 .has_outbox = false,
1399 .out_is_imm = false,
1400 .encode_slave_id = false,
1401 .verify = NULL,
1402 .wrapper = mlx4_HW2SW_CQ_wrapper
1403 },
1404 {
1405 .opcode = MLX4_CMD_QUERY_CQ,
1406 .has_inbox = false,
1407 .has_outbox = true,
1408 .out_is_imm = false,
1409 .encode_slave_id = false,
1410 .verify = NULL,
1411 .wrapper = mlx4_QUERY_CQ_wrapper
1412 },
1413 {
1414 .opcode = MLX4_CMD_MODIFY_CQ,
1415 .has_inbox = true,
1416 .has_outbox = false,
1417 .out_is_imm = true,
1418 .encode_slave_id = false,
1419 .verify = NULL,
1420 .wrapper = mlx4_MODIFY_CQ_wrapper
1421 },
1422 {
1423 .opcode = MLX4_CMD_SW2HW_SRQ,
1424 .has_inbox = true,
1425 .has_outbox = false,
1426 .out_is_imm = false,
1427 .encode_slave_id = true,
1428 .verify = NULL,
1429 .wrapper = mlx4_SW2HW_SRQ_wrapper
1430 },
1431 {
1432 .opcode = MLX4_CMD_HW2SW_SRQ,
1433 .has_inbox = false,
1434 .has_outbox = false,
1435 .out_is_imm = false,
1436 .encode_slave_id = false,
1437 .verify = NULL,
1438 .wrapper = mlx4_HW2SW_SRQ_wrapper
1439 },
1440 {
1441 .opcode = MLX4_CMD_QUERY_SRQ,
1442 .has_inbox = false,
1443 .has_outbox = true,
1444 .out_is_imm = false,
1445 .encode_slave_id = false,
1446 .verify = NULL,
1447 .wrapper = mlx4_QUERY_SRQ_wrapper
1448 },
1449 {
1450 .opcode = MLX4_CMD_ARM_SRQ,
1451 .has_inbox = false,
1452 .has_outbox = false,
1453 .out_is_imm = false,
1454 .encode_slave_id = false,
1455 .verify = NULL,
1456 .wrapper = mlx4_ARM_SRQ_wrapper
1457 },
1458 {
1459 .opcode = MLX4_CMD_RST2INIT_QP,
1460 .has_inbox = true,
1461 .has_outbox = false,
1462 .out_is_imm = false,
1463 .encode_slave_id = true,
1464 .verify = NULL,
1465 .wrapper = mlx4_RST2INIT_QP_wrapper
1466 },
1467 {
1468 .opcode = MLX4_CMD_INIT2INIT_QP,
1469 .has_inbox = true,
1470 .has_outbox = false,
1471 .out_is_imm = false,
1472 .encode_slave_id = false,
1473 .verify = NULL,
1474 .wrapper = mlx4_INIT2INIT_QP_wrapper
1475 },
1476 {
1477 .opcode = MLX4_CMD_INIT2RTR_QP,
1478 .has_inbox = true,
1479 .has_outbox = false,
1480 .out_is_imm = false,
1481 .encode_slave_id = false,
1482 .verify = NULL,
1483 .wrapper = mlx4_INIT2RTR_QP_wrapper
1484 },
1485 {
1486 .opcode = MLX4_CMD_RTR2RTS_QP,
1487 .has_inbox = true,
1488 .has_outbox = false,
1489 .out_is_imm = false,
1490 .encode_slave_id = false,
1491 .verify = NULL,
1492 .wrapper = mlx4_RTR2RTS_QP_wrapper
1493 },
1494 {
1495 .opcode = MLX4_CMD_RTS2RTS_QP,
1496 .has_inbox = true,
1497 .has_outbox = false,
1498 .out_is_imm = false,
1499 .encode_slave_id = false,
1500 .verify = NULL,
1501 .wrapper = mlx4_RTS2RTS_QP_wrapper
1502 },
1503 {
1504 .opcode = MLX4_CMD_SQERR2RTS_QP,
1505 .has_inbox = true,
1506 .has_outbox = false,
1507 .out_is_imm = false,
1508 .encode_slave_id = false,
1509 .verify = NULL,
1510 .wrapper = mlx4_SQERR2RTS_QP_wrapper
1511 },
1512 {
1513 .opcode = MLX4_CMD_2ERR_QP,
1514 .has_inbox = false,
1515 .has_outbox = false,
1516 .out_is_imm = false,
1517 .encode_slave_id = false,
1518 .verify = NULL,
1519 .wrapper = mlx4_GEN_QP_wrapper
1520 },
1521 {
1522 .opcode = MLX4_CMD_RTS2SQD_QP,
1523 .has_inbox = false,
1524 .has_outbox = false,
1525 .out_is_imm = false,
1526 .encode_slave_id = false,
1527 .verify = NULL,
1528 .wrapper = mlx4_GEN_QP_wrapper
1529 },
1530 {
1531 .opcode = MLX4_CMD_SQD2SQD_QP,
1532 .has_inbox = true,
1533 .has_outbox = false,
1534 .out_is_imm = false,
1535 .encode_slave_id = false,
1536 .verify = NULL,
1537 .wrapper = mlx4_SQD2SQD_QP_wrapper
1538 },
1539 {
1540 .opcode = MLX4_CMD_SQD2RTS_QP,
1541 .has_inbox = true,
1542 .has_outbox = false,
1543 .out_is_imm = false,
1544 .encode_slave_id = false,
1545 .verify = NULL,
1546 .wrapper = mlx4_SQD2RTS_QP_wrapper
1547 },
1548 {
1549 .opcode = MLX4_CMD_2RST_QP,
1550 .has_inbox = false,
1551 .has_outbox = false,
1552 .out_is_imm = false,
1553 .encode_slave_id = false,
1554 .verify = NULL,
1555 .wrapper = mlx4_2RST_QP_wrapper
1556 },
1557 {
1558 .opcode = MLX4_CMD_QUERY_QP,
1559 .has_inbox = false,
1560 .has_outbox = true,
1561 .out_is_imm = false,
1562 .encode_slave_id = false,
1563 .verify = NULL,
1564 .wrapper = mlx4_GEN_QP_wrapper
1565 },
1566 {
1567 .opcode = MLX4_CMD_SUSPEND_QP,
1568 .has_inbox = false,
1569 .has_outbox = false,
1570 .out_is_imm = false,
1571 .encode_slave_id = false,
1572 .verify = NULL,
1573 .wrapper = mlx4_GEN_QP_wrapper
1574 },
1575 {
1576 .opcode = MLX4_CMD_UNSUSPEND_QP,
1577 .has_inbox = false,
1578 .has_outbox = false,
1579 .out_is_imm = false,
1580 .encode_slave_id = false,
1581 .verify = NULL,
1582 .wrapper = mlx4_GEN_QP_wrapper
1583 },
1584 {
1585 .opcode = MLX4_CMD_UPDATE_QP,
1586 .has_inbox = false,
1587 .has_outbox = false,
1588 .out_is_imm = false,
1589 .encode_slave_id = false,
1590 .skip_err_print = true,
1591 .verify = NULL,
1592 .wrapper = MLX4_CMD_UPDATE_QP_wrapper
1593 },
1594 {
1595 .opcode = MLX4_CMD_CONF_SPECIAL_QP,
1596 .has_inbox = false,
1597 .has_outbox = false,
1598 .out_is_imm = false,
1599 .encode_slave_id = false,
1600 .verify = NULL,  XXX verify: only demux can do this
1601 .wrapper = NULL
1602 },
1603 {
1604 .opcode = MLX4_CMD_MAD_IFC,
1605 .has_inbox = true,
1606 .has_outbox = true,
1607 .out_is_imm = false,
1608 .encode_slave_id = false,
1609 .verify = NULL,
1610 .wrapper = mlx4_MAD_IFC_wrapper
1611 },
1612 {
1613 .opcode = MLX4_CMD_QUERY_IF_STAT,
1614 .has_inbox = false,
1615 .has_outbox = true,
1616 .out_is_imm = false,
1617 .encode_slave_id = false,
1618 .verify = NULL,
1619 .wrapper = mlx4_QUERY_IF_STAT_wrapper
1620 },
1621 Native multicast commands are not available for guests
1622 {
1623 .opcode = MLX4_CMD_QP_ATTACH,
1624 .has_inbox = true,
1625 .has_outbox = false,
1626 .out_is_imm = false,
1627 .encode_slave_id = false,
1628 .verify = NULL,
1629 .wrapper = mlx4_QP_ATTACH_wrapper
1630 },
1631 {
1632 .opcode = MLX4_CMD_PROMISC,
1633 .has_inbox = false,
1634 .has_outbox = false,
1635 .out_is_imm = false,
1636 .encode_slave_id = false,
1637 .verify = NULL,
1638 .wrapper = mlx4_PROMISC_wrapper
1639 },
1640 Ethernet specific commands
1641 {
1642 .opcode = MLX4_CMD_SET_VLAN_FLTR,
1643 .has_inbox = true,
1644 .has_outbox = false,
1645 .out_is_imm = false,
1646 .encode_slave_id = false,
1647 .verify = NULL,
1648 .wrapper = mlx4_SET_VLAN_FLTR_wrapper
1649 },
1650 {
1651 .opcode = MLX4_CMD_SET_MCAST_FLTR,
1652 .has_inbox = false,
1653 .has_outbox = false,
1654 .out_is_imm = false,
1655 .encode_slave_id = false,
1656 .verify = NULL,
1657 .wrapper = mlx4_SET_MCAST_FLTR_wrapper
1658 },
1659 {
1660 .opcode = MLX4_CMD_DUMP_ETH_STATS,
1661 .has_inbox = false,
1662 .has_outbox = true,
1663 .out_is_imm = false,
1664 .encode_slave_id = false,
1665 .verify = NULL,
1666 .wrapper = mlx4_DUMP_ETH_STATS_wrapper
1667 },
1668 {
1669 .opcode = MLX4_CMD_INFORM_FLR_DONE,
1670 .has_inbox = false,
1671 .has_outbox = false,
1672 .out_is_imm = false,
1673 .encode_slave_id = false,
1674 .verify = NULL,
1675 .wrapper = NULL
1676 },
1677 flow steering commands
1678 {
1679 .opcode = MLX4_QP_FLOW_STEERING_ATTACH,
1680 .has_inbox = true,
1681 .has_outbox = false,
1682 .out_is_imm = true,
1683 .encode_slave_id = false,
1684 .verify = NULL,
1685 .wrapper = mlx4_QP_FLOW_STEERING_ATTACH_wrapper
1686 },
1687 {
1688 .opcode = MLX4_QP_FLOW_STEERING_DETACH,
1689 .has_inbox = false,
1690 .has_outbox = false,
1691 .out_is_imm = false,
1692 .encode_slave_id = false,
1693 .verify = NULL,
1694 .wrapper = mlx4_QP_FLOW_STEERING_DETACH_wrapper
1695 },
1696 wol commands
1697 {
1698 .opcode = MLX4_CMD_MOD_STAT_CFG,
1699 .has_inbox = false,
1700 .has_outbox = false,
1701 .out_is_imm = false,
1702 .encode_slave_id = false,
1703 .skip_err_print = true,
1704 .verify = NULL,
1705 .wrapper = mlx4_MOD_STAT_CFG_wrapper
1706 },
1707 };
1708
1709 static int mlx4_master_process_vhcr(struct mlx4_priv *priv, int slave,
1710 struct mlx4_vhcr_cmd *in_vhcr)
1711 {
1712 struct mlx4_priv *priv = mlx4_priv(dev);
1713 struct mlx4_cmd_info *cmd = NULL;
1714 struct mlx4_vhcr_cmd *vhcr_cmd = in_vhcr ? in_vhcr : priv->mfunc.vhcr;
1715 struct mlx4_vhcr *vhcr;
1716 struct mlx4_cmd_mailbox *inbox = NULL;
1717 struct mlx4_cmd_mailbox *outbox = NULL;
1718 u64 in_param;
1719 u64 out_param;
1720 int ret = 0;
1721 int i;
1722 int err = 0;
1723
1724 Create sw representation of Virtual HCR
1725 vhcr = kzalloc(sizeof(struct mlx4_vhcr), GFP_KERNEL);
1726 if (!vhcr)
1727 return -ENOMEM;
1728
1729 DMA in the vHCR
1730 if (!in_vhcr) {
1731 ret = mlx4_ACCESS_MEM(dev, priv->mfunc.vhcr_dma, slave,
1732 priv->mfunc.master.slave_state[slave].vhcr_dma,
1733 ALIGN(sizeof(struct mlx4_vhcr_cmd),
1734 MLX4_ACCESS_MEM_ALIGN), 1);
1735 if (ret) {
1736 MLX4_DEBUG( "%s:Failed reading vhcr"
1737 "ret: 0x%x\n", __func__, ret);
1738 kfree(vhcr);
1739 return ret;
1740 }
1741 }
1742
1743 Fill SW VHCR fields
1744 vhcr->in_param = be64_to_cpu(vhcr_cmd->in_param);
1745 vhcr->out_param = be64_to_cpu(vhcr_cmd->out_param);
1746 vhcr->in_modifier = be32_to_cpu(vhcr_cmd->in_modifier);
1747 vhcr->token = be16_to_cpu(vhcr_cmd->token);
1748 vhcr->op = be16_to_cpu(vhcr_cmd->opcode) & 0xfff;
1749 vhcr->op_modifier = (u8) (be16_to_cpu(vhcr_cmd->opcode) >> 12);
1750 vhcr->e_bit = vhcr_cmd->flags & (1 << 6);
1751
1752 Lookup command
1753 for (i = 0; i < ARRAY_SIZE(cmd_info); ++i) {
1754 if (vhcr->op == cmd_info[i].opcode) {
1755 cmd = &cmd_info[i];
1756 break;
1757 }
1758 }
1759 if (!cmd) {
1760 MLX4_DEBUG( "unparavirt command: %s (0x%x) accepted from slave:%d\n",
1761 cmd_to_str(vhcr->op), vhcr->op, slave);
1762 vhcr_cmd->status = CMD_STAT_BAD_PARAM;
1763 goto out_status;
1764 }
1765
1766 Read inbox
1767 if (cmd->has_inbox) {
1768 vhcr->in_param &= INBOX_MASK;
1769 inbox = mlx4_alloc_cmd_mailbox(dev);
1770 if (IS_ERR(inbox)) {
1771 vhcr_cmd->status = CMD_STAT_BAD_SIZE;
1772 inbox = NULL;
1773 goto out_status;
1774 }
1775
1776 if (mlx4_ACCESS_MEM(dev, inbox->dma, slave,
1777 vhcr->in_param,
1778 MLX4_MAILBOX_SIZE, 1)) {
1779 MLX4_DEBUG( "%s: Failed reading inbox for cmd %s (0x%x)\n",
1780 __func__, cmd_to_str(cmd->opcode), cmd->opcode);
1781 vhcr_cmd->status = CMD_STAT_INTERNAL_ERR;
1782 goto out_status;
1783 }
1784 }
1785
1786 Apply permission and bound checks if applicable
1787 if (cmd->verify && cmd->verify(dev, slave, vhcr, inbox)) {
1788 MLX4_DEBUG( "Command %s (0x%x) from slave: %d failed protection "
1789 "checks for resource_id: %d\n", cmd_to_str(vhcr->op),
1790 vhcr->op, slave, vhcr->in_modifier);
1791 vhcr_cmd->status = CMD_STAT_BAD_OP;
1792 goto out_status;
1793 }
1794
1795 Allocate outbox
1796 if (cmd->has_outbox) {
1797 outbox = mlx4_alloc_cmd_mailbox(dev);
1798 if (IS_ERR(outbox)) {
1799 vhcr_cmd->status = CMD_STAT_BAD_SIZE;
1800 outbox = NULL;
1801 goto out_status;
1802 }
1803 }
1804
1805 Execute the command!
1806 if (cmd->wrapper) {
1807 err = cmd->wrapper(dev, slave, vhcr, inbox, outbox,
1808 cmd);
1809 if (cmd->out_is_imm)
1810 vhcr_cmd->out_param = cpu_to_be64(vhcr->out_param);
1811 } else {
1812 in_param = cmd->has_inbox ? (u64) inbox->dma :
1813 vhcr->in_param;
1814 out_param = cmd->has_outbox ? (u64) outbox->dma :
1815 vhcr->out_param;
1816 err = __mlx4_cmd(dev, in_param, &out_param,
1817 cmd->out_is_imm, vhcr->in_modifier,
1818 vhcr->op_modifier, vhcr->op,
1819 MLX4_CMD_TIME_CLASS_A,
1820 MLX4_CMD_NATIVE);
1821
1822 if (cmd->out_is_imm) {
1823 vhcr->out_param = out_param;
1824 vhcr_cmd->out_param = cpu_to_be64(vhcr->out_param);
1825 }
1826 }
1827
1828 if (err) {
1829 if (!cmd->skip_err_print)
1830 MLX4_DEBUG( "vhcr command %s (0x%x) slave:%d "
1831 "in_param 0x%llx in_mod=0x%x, op_mod=0x%x "
1832 "failed with error:%d, status %d\n",
1833 cmd_to_str(vhcr->op), vhcr->op, slave,
1834 (unsigned long long) vhcr->in_param, vhcr->in_modifier,
1835 vhcr->op_modifier, vhcr->errno, err);
1836 vhcr_cmd->status = mlx4_errno_to_status(err);
1837 goto out_status;
1838 }
1839
1840
1841 Write outbox if command completed successfully
1842 if (cmd->has_outbox && !vhcr_cmd->status) {
1843 ret = mlx4_ACCESS_MEM(dev, outbox->dma, slave,
1844 vhcr->out_param,
1845 MLX4_MAILBOX_SIZE, MLX4_CMD_WRAPPED);
1846 if (ret) {
1847 If we failed to write back the outbox after the
1848 *command was successfully executed, we must fail this
1849 * slave, as it is now in undefined state
1850 MLX4_DEBUG( "%s: Failed writing outbox\n", __func__);
1851 goto out;
1852 }
1853 }
1854
1855 out_status:
1856 DMA back vhcr result
1857 if (!in_vhcr) {
1858 ret = mlx4_ACCESS_MEM(dev, priv->mfunc.vhcr_dma, slave,
1859 priv->mfunc.master.slave_state[slave].vhcr_dma,
1860 ALIGN(sizeof(struct mlx4_vhcr),
1861 MLX4_ACCESS_MEM_ALIGN),
1862 MLX4_CMD_WRAPPED);
1863 if (ret)
1864 MLX4_DEBUG( "%s:Failed writing vhcr result\n",
1865 __func__);
1866 else if (vhcr->e_bit &&
1867 mlx4_GEN_EQE(dev, slave, &priv->mfunc.master.cmd_eqe))
1868 MLX4_DEBUG( "Failed to generate command completion "
1869 "eqe for slave %d\n", slave);
1870 }
1871
1872 out:
1873 kfree(vhcr);
1874 mlx4_free_cmd_mailbox(dev, inbox);
1875 mlx4_free_cmd_mailbox(dev, outbox);
1876 return ret;
1877 }
1878
1879 static int mlx4_master_immediate_activate_vlan_qos(struct mlx4_priv *priv,
1880 int slave, int port)
1881 {
1882 struct mlx4_vport_oper_state *vp_oper;
1883 struct mlx4_vport_state *vp_admin;
1884 struct mlx4_vf_immed_vlan_work *work;
1885 int err;
1886 int admin_vlan_ix = NO_INDX;
1887
1888 vp_oper = &priv->mfunc.master.vf_oper[slave].vport[port];
1889 vp_admin = &priv->mfunc.master.vf_admin[slave].vport[port];
1890
1891 if (vp_oper->state.default_vlan == vp_admin->default_vlan &&
1892 vp_oper->state.default_qos == vp_admin->default_qos)
1893 return 0;
1894
1895 work = kzalloc(sizeof(*work), GFP_KERNEL);
1896 if (!work)
1897 return -ENOMEM;
1898
1899 if (vp_oper->state.default_vlan != vp_admin->default_vlan) {
1900 if (MLX4_VGT != vp_admin->default_vlan) {
1901 err = __mlx4_register_vlan(&priv->dev, port,
1902 vp_admin->default_vlan,
1903 &admin_vlan_ix);
1904 if (err) {
1905 mlx4_warn((&priv->dev),
1906 "No vlan resources slave %d, port %d\n",
1907 slave, port);
1908 kfree(work);
1909 return err;
1910 }
1911 } else {
1912 admin_vlan_ix = NO_INDX;
1913 }
1914 work->flags |= MLX4_VF_IMMED_VLAN_FLAG_VLAN;
1915 mlx4_dbg((&(priv->dev)),
1916 "alloc vlan %d idx  %d slave %d port %d\n",
1917 (int)(vp_admin->default_vlan),
1918 admin_vlan_ix, slave, port);
1919 }
1920
1921 save original vlan ix and vlan id
1922 work->orig_vlan_id = vp_oper->state.default_vlan;
1923 work->orig_vlan_ix = vp_oper->vlan_idx;
1924
1925 handle new qos
1926 if (vp_oper->state.default_qos != vp_admin->default_qos)
1927 work->flags |= MLX4_VF_IMMED_VLAN_FLAG_QOS;
1928
1929 if (work->flags & MLX4_VF_IMMED_VLAN_FLAG_VLAN)
1930 vp_oper->vlan_idx = admin_vlan_ix;
1931
1932 vp_oper->state.default_vlan = vp_admin->default_vlan;
1933 vp_oper->state.default_qos = vp_admin->default_qos;
1934
1935 iterate over QPs owned by this slave, using UPDATE_QP
1936 work->port = port;
1937 work->slave = slave;
1938 work->qos = vp_oper->state.default_qos;
1939 work->vlan_id = vp_oper->state.default_vlan;
1940 work->vlan_ix = vp_oper->vlan_idx;
1941 work->priv = priv;
1942 INIT_WORK(&work->work, mlx4_vf_immed_vlan_work_handler);
1943 queue_work(priv->mfunc.master.comm_wq, &work->work);
1944
1945 return 0;
1946 }
1947
1948
1949 static int mlx4_master_activate_admin_state(struct mlx4_priv *priv, int slave)
1950 {
1951 int port, err;
1952 struct mlx4_vport_state *vp_admin;
1953 struct mlx4_vport_oper_state *vp_oper;
1954
1955 for (port = 1; port <= MLX4_MAX_PORTS; port++) {
1956 vp_oper = &priv->mfunc.master.vf_oper[slave].vport[port];
1957 vp_admin = &priv->mfunc.master.vf_admin[slave].vport[port];
1958 vp_oper->state = *vp_admin;
1959 if (MLX4_VGT != vp_admin->default_vlan) {
1960 err = __mlx4_register_vlan(&priv->dev, port,
1961 vp_admin->default_vlan, &(vp_oper->vlan_idx));
1962 if (err) {
1963 vp_oper->vlan_idx = NO_INDX;
1964 mlx4_warn((&priv->dev),
1965 "No vlan resorces slave %d, port %d\n",
1966 slave, port);
1967 return err;
1968 }
1969 mlx4_dbg((&(priv->dev)), "alloc vlan %d idx  %d slave %d port %d\n",
1970 (int)(vp_oper->state.default_vlan),
1971 vp_oper->vlan_idx, slave, port);
1972 }
1973 if (vp_admin->spoofchk) {
1974 vp_oper->mac_idx = __mlx4_register_mac(&priv->dev,
1975 port,
1976 vp_admin->mac);
1977 if (0 > vp_oper->mac_idx) {
1978 err = vp_oper->mac_idx;
1979 vp_oper->mac_idx = NO_INDX;
1980 mlx4_warn((&priv->dev),
1981 "No mac resources slave %d, port %d\n",
1982 slave, port);
1983 return err;
1984 }
1985 mlx4_dbg((&(priv->dev)), "alloc mac %llx idx  %d slave %d port %d\n",
1986 (unsigned long long) vp_oper->state.mac, vp_oper->mac_idx, slave, port);
1987 }
1988 }
1989 return 0;
1990 }
1991
1992 static void mlx4_master_deactivate_admin_state(struct mlx4_priv *priv, int slave)
1993 {
1994 int port;
1995 struct mlx4_vport_oper_state *vp_oper;
1996
1997 for (port = 1; port <= MLX4_MAX_PORTS; port++) {
1998 vp_oper = &priv->mfunc.master.vf_oper[slave].vport[port];
1999 if (NO_INDX != vp_oper->vlan_idx) {
2000 __mlx4_unregister_vlan(&priv->dev,
2001 port, vp_oper->state.default_vlan);
2002 vp_oper->vlan_idx = NO_INDX;
2003 }
2004 if (NO_INDX != vp_oper->mac_idx) {
2005 __mlx4_unregister_mac(&priv->dev, port, vp_oper->state.mac);
2006 vp_oper->mac_idx = NO_INDX;
2007 }
2008 }
2009 return;
2010 }
2011
2012 static void mlx4_master_do_cmd(struct mlx4_priv *priv, int slave, u8 cmd,
2013 u16 param, u8 toggle)
2014 {
2015 struct mlx4_priv *priv = mlx4_priv(dev);
2016 struct mlx4_slave_state *slave_state = priv->mfunc.master.slave_state;
2017 u32 reply;
2018 u8 is_going_down = 0;
2019 int i;
2020 unsigned long flags;
2021
2022 slave_state[slave].comm_toggle ^= 1;
2023 reply = (u32) slave_state[slave].comm_toggle << 31;
2024 if (toggle != slave_state[slave].comm_toggle) {
2025 MLX4_DEBUG( "Incorrect toggle %d from slave %d. *** MASTER"
2026 "STATE COMPROMISIED ***\n", toggle, slave);
2027 goto reset_slave;
2028 }
2029 if (cmd == MLX4_COMM_CMD_RESET) {
2030 MLX4_DEBUG( "Received reset from slave:%d\n", slave);
2031 slave_state[slave].active = false;
2032 slave_state[slave].old_vlan_api = false;
2033 mlx4_master_deactivate_admin_state(priv, slave);
2034 for (i = 0; i < MLX4_EVENT_TYPES_NUM; ++i) {
2035 slave_state[slave].event_eq[i].eqn = -1;
2036 slave_state[slave].event_eq[i].token = 0;
2037 }
2038 check if we are in the middle of FLR process,
2039 if so return "retry" status to the slave
2040 if (MLX4_COMM_CMD_FLR == slave_state[slave].last_cmd)
2041 goto inform_slave_state;
2042
2043 mlx4_dispatch_event(dev, MLX4_DEV_EVENT_SLAVE_SHUTDOWN, slave);
2044
2045 write the version in the event field
2046 reply |= mlx4_comm_get_version();
2047
2048 goto reset_slave;
2049 }
2050 command from slave in the middle of FLR
2051 if (cmd != MLX4_COMM_CMD_RESET &&
2052 MLX4_COMM_CMD_FLR == slave_state[slave].last_cmd) {
2053 MLX4_DEBUG( "slave:%d is Trying to run cmd (0x%x) "
2054 "in the middle of FLR\n", slave, cmd);
2055 return;
2056 }
2057
2058 switch (cmd) {
2059 case MLX4_COMM_CMD_VHCR0:
2060 if (slave_state[slave].last_cmd != MLX4_COMM_CMD_RESET)
2061 goto reset_slave;
2062 slave_state[slave].vhcr_dma = ((u64) param) << 48;
2063 priv->mfunc.master.slave_state[slave].cookie = 0;
2064 break;
2065 case MLX4_COMM_CMD_VHCR1:
2066 if (slave_state[slave].last_cmd != MLX4_COMM_CMD_VHCR0)
2067 goto reset_slave;
2068 slave_state[slave].vhcr_dma |= ((u64) param) << 32;
2069 break;
2070 case MLX4_COMM_CMD_VHCR2:
2071 if (slave_state[slave].last_cmd != MLX4_COMM_CMD_VHCR1)
2072 goto reset_slave;
2073 slave_state[slave].vhcr_dma |= ((u64) param) << 16;
2074 break;
2075 case MLX4_COMM_CMD_VHCR_EN:
2076 if (slave_state[slave].last_cmd != MLX4_COMM_CMD_VHCR2)
2077 goto reset_slave;
2078 slave_state[slave].vhcr_dma |= param;
2079 if (mlx4_master_activate_admin_state(priv, slave))
2080 goto reset_slave;
2081 slave_state[slave].active = true;
2082 mlx4_dispatch_event(dev, MLX4_DEV_EVENT_SLAVE_INIT, slave);
2083 break;
2084 case MLX4_COMM_CMD_VHCR_POST:
2085 if ((slave_state[slave].last_cmd != MLX4_COMM_CMD_VHCR_EN) &&
2086 (slave_state[slave].last_cmd != MLX4_COMM_CMD_VHCR_POST))
2087 goto reset_slave;
2088
2089 mutex_lock(&priv->cmd.slave_cmd_mutex);
2090 if (mlx4_master_process_vhcr(dev, slave, NULL)) {
2091 MLX4_DEBUG( "Failed processing vhcr for slave: %d,"
2092 " resetting slave.\n", slave);
2093 mutex_unlock(&priv->cmd.slave_cmd_mutex);
2094 goto reset_slave;
2095 }
2096 mutex_unlock(&priv->cmd.slave_cmd_mutex);
2097 break;
2098 default:
2099 MLX4_DEBUG( "Bad comm cmd: %d from slave: %d\n", cmd, slave);
2100 goto reset_slave;
2101 }
2102 spin_lock_irqsave(&priv->mfunc.master.slave_state_lock, flags);
2103 if (!slave_state[slave].is_slave_going_down)
2104 slave_state[slave].last_cmd = cmd;
2105 else
2106 is_going_down = 1;
2107 spin_unlock_irqrestore(&priv->mfunc.master.slave_state_lock, flags);
2108 if (is_going_down) {
2109 MLX4_DEBUG( "Slave is going down aborting command (%d)"
2110 " executing from slave: %d\n",
2111 cmd, slave);
2112 return;
2113 }
2114 __raw_writel((__force u32) cpu_to_be32(reply),
2115 &priv->mfunc.comm[slave].slave_read);
2116 mmiowb();
2117
2118 return;
2119
2120 reset_slave:
2121 cleanup any slave resources
2122 mlx4_delete_all_resources_for_slave(dev, slave);
2123 spin_lock_irqsave(&priv->mfunc.master.slave_state_lock, flags);
2124 if (!slave_state[slave].is_slave_going_down)
2125 slave_state[slave].last_cmd = MLX4_COMM_CMD_RESET;
2126 spin_unlock_irqrestore(&priv->mfunc.master.slave_state_lock, flags);
2127 with slave in the middle of flr, no need to clean resources again.
2128 inform_slave_state:
2129 __raw_writel((__force u32) cpu_to_be32(reply),
2130 &priv->mfunc.comm[slave].slave_read);
2131 wmb();
2132 }
2133
2134 master command processing
2135 void mlx4_master_comm_channel(struct work_struct *work)
2136 {
2137 struct mlx4_mfunc_master_ctx *master =
2138 container_of(work,
2139 struct mlx4_mfunc_master_ctx,
2140 comm_work);
2141 struct mlx4_mfunc *mfunc =
2142 container_of(master, struct mlx4_mfunc, master);
2143 struct mlx4_priv *priv =
2144 container_of(mfunc, struct mlx4_priv, mfunc);
2145 struct mlx4_priv *priv = &priv->dev;
2146 __be32 *bit_vec;
2147 u32 comm_cmd;
2148 u32 vec;
2149 int i, j, slave;
2150 int toggle;
2151 int served = 0;
2152 int reported = 0;
2153 u32 slt;
2154
2155 bit_vec = master->comm_arm_bit_vector;
2156 for (i = 0; i < COMM_CHANNEL_BIT_ARRAY_SIZE; i++) {
2157 vec = be32_to_cpu(bit_vec[i]);
2158 for (j = 0; j < 32; j++) {
2159 if (!(vec & (1 << j)))
2160 continue;
2161 ++reported;
2162 slave = (i * 32) + j;
2163 comm_cmd = swab32(readl(
2164 &mfunc->comm[slave].slave_write));
2165 slt = swab32(readl(&mfunc->comm[slave].slave_read))
2166 >> 31;
2167 toggle = comm_cmd >> 31;
2168 if (toggle != slt) {
2169 if (master->slave_state[slave].comm_toggle
2170 != slt) {
2171 MLX4_DEBUG( "slave %d out of sync."
2172 " read toggle %d, state toggle %d. "
2173 "Resynching.\n", slave, slt,
2174 master->slave_state[slave].comm_toggle);
2175 master->slave_state[slave].comm_toggle =
2176 slt;
2177 }
2178 mlx4_master_do_cmd(dev, slave,
2179 comm_cmd >> 16 & 0xff,
2180 comm_cmd & 0xffff, toggle);
2181 ++served;
2182 } else
2183 MLX4_DEBUG( "slave %d out of sync."
2184 " read toggle %d, write toggle %d.\n", slave, slt,
2185 toggle);
2186 }
2187 }
2188
2189 if (reported && reported != served)
2190 MLX4_DEBUG( "Got command event with bitmask from %d slaves"
2191 " but %d were served\n",
2192 reported, served);
2193 }
2194 master command processing
2195 void mlx4_master_arm_comm_channel(struct work_struct *work)
2196 {
2197 struct mlx4_mfunc_master_ctx *master =
2198 container_of(work,
2199 struct mlx4_mfunc_master_ctx,
2200 arm_comm_work);
2201 struct mlx4_mfunc *mfunc =
2202 container_of(master, struct mlx4_mfunc, master);
2203 struct mlx4_priv *priv =
2204 container_of(mfunc, struct mlx4_priv, mfunc);
2205 struct mlx4_priv *priv = &priv->dev;
2206
2207 if (mlx4_ARM_COMM_CHANNEL(dev))
2208 MLX4_DEBUG( "Failed to arm comm channel events\n");
2209 }
2210
2211 static int sync_toggles(struct mlx4_priv *priv)
2212 {
2213 struct mlx4_priv *priv = mlx4_priv(dev);
2214 int wr_toggle;
2215 int rd_toggle;
2216 unsigned long end;
2217
2218 wr_toggle = swab32(readl(&priv->mfunc.comm->slave_write)) >> 31;
2219 end = jiffies + msecs_to_jiffies(5000);
2220
2221 while (time_before(jiffies, end)) {
2222 rd_toggle = swab32(readl(&priv->mfunc.comm->slave_read)) >> 31;
2223 if (rd_toggle == wr_toggle) {
2224 priv->cmd.comm_toggle = rd_toggle;
2225 return 0;
2226 }
2227
2228 cond_resched();
2229 }
2230
2231
2232 * we could reach here if for example the previous VM using this
2233 * function misbehaved and left the channel with unsynced state. We
2234 * should fix this here and give this VM a chance to use a properly
2235 * synced channel
2236
2237 MLX4_DEBUG( "recovering from previously mis-behaved VM\n");
2238 __raw_writel((__force u32) 0, &priv->mfunc.comm->slave_read);
2239 __raw_writel((__force u32) 0, &priv->mfunc.comm->slave_write);
2240 priv->cmd.comm_toggle = 0;
2241
2242 return 0;
2243 }
2244
2245 int mlx4_multi_func_init(struct mlx4_priv *priv)
2246 {
2247 struct mlx4_priv *priv = mlx4_priv(dev);
2248 struct mlx4_slave_state *s_state;
2249 int i, j, err, port;
2250
2251 if (mlx4_is_master(dev))
2252 priv->mfunc.comm =
2253 ioremap(pci_resource_start(dev->pdev, priv->fw.comm_bar) +
2254 priv->fw.comm_base, MLX4_COMM_PAGESIZE);
2255 else
2256 priv->mfunc.comm =
2257 ioremap(pci_resource_start(dev->pdev, 2) +
2258 MLX4_SLAVE_COMM_BASE, MLX4_COMM_PAGESIZE);
2259 if (!priv->mfunc.comm) {
2260 MLX4_DEBUG( "Couldn't map communication vector.\n");
2261 goto err_vhcr;
2262 }
2263
2264 if (mlx4_is_master(dev)) {
2265 priv->mfunc.master.slave_state =
2266 kzalloc(dev->num_slaves *
2267 sizeof(struct mlx4_slave_state), GFP_KERNEL);
2268 if (!priv->mfunc.master.slave_state)
2269 goto err_comm;
2270
2271 priv->mfunc.master.vf_admin =
2272 kzalloc(dev->num_slaves *
2273 sizeof(struct mlx4_vf_admin_state), GFP_KERNEL);
2274 if (!priv->mfunc.master.vf_admin)
2275 goto err_comm_admin;
2276
2277 priv->mfunc.master.vf_oper =
2278 kzalloc(dev->num_slaves *
2279 sizeof(struct mlx4_vf_oper_state), GFP_KERNEL);
2280 if (!priv->mfunc.master.vf_oper)
2281 goto err_comm_oper;
2282
2283 for (i = 0; i < dev->num_slaves; ++i) {
2284 s_state = &priv->mfunc.master.slave_state[i];
2285 s_state->last_cmd = MLX4_COMM_CMD_RESET;
2286 mutex_init(&priv->mfunc.master.gen_eqe_mutex[i]);
2287 for (j = 0; j < MLX4_EVENT_TYPES_NUM; ++j)
2288 s_state->event_eq[j].eqn = -1;
2289 __raw_writel((__force u32) 0,
2290 &priv->mfunc.comm[i].slave_write);
2291 __raw_writel((__force u32) 0,
2292 &priv->mfunc.comm[i].slave_read);
2293 mmiowb();
2294 for (port = 1; port <= MLX4_MAX_PORTS; port++) {
2295 s_state->vlan_filter[port] =
2296 kzalloc(sizeof(struct mlx4_vlan_fltr),
2297 GFP_KERNEL);
2298 if (!s_state->vlan_filter[port]) {
2299 if (--port)
2300 kfree(s_state->vlan_filter[port]);
2301 goto err_slaves;
2302 }
2303 INIT_LIST_HEAD(&s_state->mcast_filters[port]);
2304 priv->mfunc.master.vf_admin[i].vport[port].default_vlan = MLX4_VGT;
2305 priv->mfunc.master.vf_oper[i].vport[port].state.default_vlan = MLX4_VGT;
2306 priv->mfunc.master.vf_oper[i].vport[port].vlan_idx = NO_INDX;
2307 priv->mfunc.master.vf_oper[i].vport[port].mac_idx = NO_INDX;
2308 }
2309 spin_lock_init(&s_state->lock);
2310 }
2311
2312 memset(&priv->mfunc.master.cmd_eqe, 0, dev->caps.eqe_size);
2313 priv->mfunc.master.cmd_eqe.type = MLX4_EVENT_TYPE_CMD;
2314 INIT_WORK(&priv->mfunc.master.comm_work,
2315 mlx4_master_comm_channel);
2316 INIT_WORK(&priv->mfunc.master.arm_comm_work,
2317 mlx4_master_arm_comm_channel);
2318 INIT_WORK(&priv->mfunc.master.slave_event_work,
2319 mlx4_gen_slave_eqe);
2320 INIT_WORK(&priv->mfunc.master.slave_flr_event_work,
2321 mlx4_master_handle_slave_flr);
2322 spin_lock_init(&priv->mfunc.master.slave_state_lock);
2323 spin_lock_init(&priv->mfunc.master.slave_eq.event_lock);
2324 priv->mfunc.master.comm_wq =
2325 create_singlethread_workqueue("mlx4_comm");
2326 if (!priv->mfunc.master.comm_wq)
2327 goto err_slaves;
2328
2329 if (mlx4_init_resource_tracker(dev))
2330 goto err_thread;
2331
2332 err = mlx4_ARM_COMM_CHANNEL(dev);
2333 if (err) {
2334 MLX4_DEBUG( " Failed to arm comm channel eq: %x\n",
2335 err);
2336 goto err_resource;
2337 }
2338
2339 } else {
2340 err = sync_toggles(dev);
2341 if (err) {
2342 MLX4_DEBUG( "Couldn't sync toggles\n");
2343 goto err_comm;
2344 }
2345 }
2346 return 0;
2347
2348 err_resource:
2349 mlx4_free_resource_tracker(dev, RES_TR_FREE_ALL);
2350 err_thread:
2351 flush_workqueue(priv->mfunc.master.comm_wq);
2352 destroy_workqueue(priv->mfunc.master.comm_wq);
2353 err_slaves:
2354 while (--i) {
2355 for (port = 1; port <= MLX4_MAX_PORTS; port++)
2356 kfree(priv->mfunc.master.slave_state[i].vlan_filter[port]);
2357 }
2358 kfree(priv->mfunc.master.vf_oper);
2359 err_comm_oper:
2360 kfree(priv->mfunc.master.vf_admin);
2361 err_comm_admin:
2362 kfree(priv->mfunc.master.slave_state);
2363 err_comm:
2364 iounmap(priv->mfunc.comm);
2365 err_vhcr:
2366 dma_free_coherent(&(dev->pdev->dev), PAGE_SIZE,
2367 priv->mfunc.vhcr,
2368 priv->mfunc.vhcr_dma);
2369 priv->mfunc.vhcr = NULL;
2370 return -ENOMEM;
2371 }
2372 */
2373int mlx4_cmd_init(struct mlx4_priv *priv) {
2374
2375	/*mutex_init(&priv->cmd.hcr_mutex);
2376	 mutex_init(&priv->cmd.slave_cmd_mutex);
2377	 sema_init(&priv->cmd.poll_sem, 1);*/
2378	priv->cmd.use_events = 0;
2379	priv->cmd.toggle = 1;
2380
2381	/*priv->mfunc.vhcr = NULL;*/
2382
2383	/*if (!mlx4_is_slave(dev)) {*/
2384
2385	priv->cmd.hcr = priv->dev.bar_info->vaddr + MLX4_HCR_BASE;
2386	/*priv->cmd.hcr = ioremap(pci_resource_start(dev->pdev, 0) + MLX4_HCR_BASE,
2387	 MLX4_HCR_SIZE);
2388	 if (!priv->cmd.hcr) {
2389	 MLX4_DEBUG( "Couldn't map command register.\n");
2390	 return -ENOMEM;
2391	 }*/
2392	/*}*/
2393
2394	/*if (mlx4_is_mfunc(dev)) {
2395	 priv->mfunc.vhcr = dma_alloc_coherent(&(dev->pdev->dev), PAGE_SIZE,
2396	 &priv->mfunc.vhcr_dma, GFP_KERNEL);
2397	 if (!priv->mfunc.vhcr) {
2398	 MLX4_DEBUG( "Couldn't allocate VHCR.\n");
2399	 goto err_hcr;
2400	 }
2401	 }*/
2402
2403	/*priv->cmd.pool = pci_pool_create("mlx4_cmd", dev->pdev, MLX4_MAILBOX_SIZE,
2404	 MLX4_MAILBOX_SIZE, 0);
2405	 if (!priv->cmd.pool)
2406	 goto err_vhcr;*/
2407
2408	return 0;
2409
2410	/*err_vhcr: if (mlx4_is_mfunc(dev))
2411	 dma_free_coherent(&(dev->pdev->dev), PAGE_SIZE, priv->mfunc.vhcr,
2412	 priv->mfunc.vhcr_dma);
2413	 priv->mfunc.vhcr = NULL;
2414
2415	 err_hcr: if (!mlx4_is_slave(dev))
2416	 iounmap(priv->cmd.hcr);
2417	 return -ENOMEM;*/
2418}
2419/*
2420 void mlx4_multi_func_cleanup(struct mlx4_priv *priv)
2421 {
2422 struct mlx4_priv *priv = mlx4_priv(dev);
2423 int i, port;
2424
2425 if (mlx4_is_master(dev)) {
2426 flush_workqueue(priv->mfunc.master.comm_wq);
2427 destroy_workqueue(priv->mfunc.master.comm_wq);
2428 for (i = 0; i < dev->num_slaves; i++) {
2429 for (port = 1; port <= MLX4_MAX_PORTS; port++)
2430 kfree(priv->mfunc.master.slave_state[i].vlan_filter[port]);
2431 }
2432 kfree(priv->mfunc.master.slave_state);
2433 kfree(priv->mfunc.master.vf_admin);
2434 kfree(priv->mfunc.master.vf_oper);
2435 }
2436
2437 iounmap(priv->mfunc.comm);
2438 }
2439
2440 void mlx4_cmd_cleanup(struct mlx4_priv *priv)
2441 {
2442 struct mlx4_priv *priv = mlx4_priv(dev);
2443
2444 pci_pool_destroy(priv->cmd.pool);
2445
2446 if (!mlx4_is_slave(dev))
2447 iounmap(priv->cmd.hcr);
2448 if (mlx4_is_mfunc(dev))
2449 dma_free_coherent(&(dev->pdev->dev), PAGE_SIZE,
2450 priv->mfunc.vhcr, priv->mfunc.vhcr_dma);
2451 priv->mfunc.vhcr = NULL;
2452 }
2453
2454
2455 * Switch to using events to issue FW commands (can only be called
2456 * after event queue for command events has been initialized).
2457 */
2458int mlx4_cmd_use_events(struct mlx4_priv *priv) {
2459	int i;
2460	int err = 0;
2461
2462	priv->cmd.context = malloc(
2463			priv->cmd.max_cmds * sizeof(struct mlx4_cmd_context));
2464	if (!priv->cmd.context)
2465		return -ENOMEM;
2466
2467	for (i = 0; i < priv->cmd.max_cmds; ++i) {
2468		priv->cmd.context[i].token = i;
2469		priv->cmd.context[i].next = i + 1;
2470	}
2471
2472	priv->cmd.context[priv->cmd.max_cmds - 1].next = -1;
2473	priv->cmd.free_head = 0;
2474
2475	/*sema_init(&priv->cmd.event_sem, priv->cmd.max_cmds);
2476	 spin_lock_init(&priv->cmd.context_lock);*/
2477
2478	for (priv->cmd.token_mask = 1; priv->cmd.token_mask < priv->cmd.max_cmds;
2479			priv->cmd.token_mask <<= 1)
2480		;/*nothing*/
2481	--priv->cmd.token_mask;
2482
2483	/*down(&priv->cmd.poll_sem);*/
2484	priv->cmd.use_events = 1;
2485
2486	return err;
2487}
2488
2489/*
2490 * Switch back to polling (used when shutting down the device)
2491
2492 void mlx4_cmd_use_polling(struct mlx4_priv *priv)
2493 {
2494 struct mlx4_priv *priv = mlx4_priv(dev);
2495 int i;
2496
2497 priv->cmd.use_events = 0;
2498
2499 for (i = 0; i < priv->cmd.max_cmds; ++i)
2500 down(&priv->cmd.event_sem);
2501
2502 kfree(priv->cmd.context);
2503
2504 up(&priv->cmd.poll_sem);
2505 }
2506 */
2507struct mlx4_cmd_mailbox *mlx4_alloc_cmd_mailbox(void) {
2508	errval_t err;
2509	struct mlx4_cmd_mailbox *mailbox;
2510	struct frame_identity fid;
2511
2512	mailbox = calloc(1, sizeof *mailbox);
2513
2514	err = frame_alloc(&mailbox->slot, MLX4_MAILBOX_SIZE, NULL);
2515	assert(err_is_ok(err));
2516
2517	err = invoke_frame_identify(mailbox->slot, &fid);
2518	assert(err_is_ok(err));
2519
2520	mailbox->dma = fid.base; //this is the physical address
2521
2522	err = vspace_map_one_frame_attr(&mailbox->buf, MLX4_MAILBOX_SIZE,
2523			mailbox->slot,
2524			VREGION_FLAGS_READ_WRITE_NOCACHE, NULL,
2525			NULL);
2526	assert(err_is_ok(err));
2527
2528	memset(mailbox->buf, 0, MLX4_MAILBOX_SIZE);
2529
2530	return mailbox;
2531}
2532/*
2533 EXPORT_SYMBOL_GPL(mlx4_alloc_cmd_mailbox);
2534 */
2535void mlx4_free_cmd_mailbox(struct mlx4_cmd_mailbox *mailbox) {
2536	errval_t cleanup_err;
2537
2538	/*int i;
2539	 uint32_t *data = (uint32_t *) mailbox->buf;*/
2540
2541	if (!mailbox)
2542		return;
2543
2544	/*for (i = 0; i < MLX4_MAILBOX_SIZE / 4; ++i) {
2545	 printf("mailbox: 0x%x\n", data[i]);
2546	 }*/
2547
2548	cleanup_err = vspace_unmap(mailbox->buf);
2549	if (err_is_fail(cleanup_err)) {
2550		USER_PANIC_ERR(cleanup_err, "vspace_unmap failed");
2551	}
2552
2553	cleanup_err = cap_destroy(mailbox->slot);
2554	if (err_is_fail(cleanup_err)) {
2555		USER_PANIC_ERR(cleanup_err, "cap_destroy failed");
2556	}
2557
2558	/*pci_pool_free(mlx4_priv(dev)->cmd.pool, mailbox->buf, mailbox->dma);
2559	 kfree(mailbox);*/
2560}
2561/*
2562 EXPORT_SYMBOL_GPL(mlx4_free_cmd_mailbox);
2563
2564 u32 mlx4_comm_get_version(void)
2565 {
2566 return ((u32) CMD_CHAN_IF_REV << 8) | (u32) CMD_CHAN_VER;
2567 }
2568
2569 static int mlx4_get_slave_indx(struct mlx4_priv *priv, int vf)
2570 {
2571 if ((vf < 0) || (vf >= dev->num_vfs)) {
2572 MLX4_DEBUG( "Bad vf number:%d (number of activated vf: %d)\n", vf, dev->num_vfs);
2573 return -EINVAL;
2574 }
2575 return (vf+1);
2576 }
2577
2578 int mlx4_set_vf_mac(struct mlx4_priv *priv, int port, int vf, u8 *mac)
2579 {
2580 struct mlx4_priv *priv = mlx4_priv(dev);
2581 struct mlx4_vport_state *s_info;
2582 int slave;
2583
2584 if (!mlx4_is_master(dev))
2585 return -EPROTONOSUPPORT;
2586
2587 slave = mlx4_get_slave_indx(dev, vf);
2588 if (slave < 0)
2589 return -EINVAL;
2590
2591 s_info = &priv->mfunc.master.vf_admin[slave].vport[port];
2592 s_info->mac = mlx4_mac_to_u64(mac);
2593 MLX4_DEBUG( "default mac on vf %d port %d to %llX will take afect only after vf restart\n",
2594 vf, port, (unsigned long long) s_info->mac);
2595 return 0;
2596 }
2597 EXPORT_SYMBOL_GPL(mlx4_set_vf_mac);
2598
2599 int mlx4_set_vf_vlan(struct mlx4_priv *priv, int port, int vf, u16 vlan, u8 qos)
2600 {
2601 struct mlx4_priv *priv = mlx4_priv(dev);
2602 struct mlx4_vport_oper_state *vf_oper;
2603 struct mlx4_vport_state *vf_admin;
2604 int slave;
2605
2606 if ((!mlx4_is_master(dev)) ||
2607 !(dev->caps.flags2 & MLX4_DEV_CAP_FLAG2_VLAN_CONTROL))
2608 return -EPROTONOSUPPORT;
2609
2610 if ((vlan > 4095) || (qos > 7))
2611 return -EINVAL;
2612
2613 slave = mlx4_get_slave_indx(dev, vf);
2614 if (slave < 0)
2615 return -EINVAL;
2616
2617 vf_admin = &priv->mfunc.master.vf_admin[slave].vport[port];
2618 vf_oper = &priv->mfunc.master.vf_oper[slave].vport[port];
2619
2620 if ((0 == vlan) && (0 == qos))
2621 vf_admin->default_vlan = MLX4_VGT;
2622 else
2623 vf_admin->default_vlan = vlan;
2624 vf_admin->default_qos = qos;
2625
2626 if (priv->mfunc.master.slave_state[slave].active &&
2627 dev->caps.flags2 & MLX4_DEV_CAP_FLAG2_UPDATE_QP) {
2628 MLX4_DEBUG( "updating vf %d port %d config params immediately\n",
2629 vf, port);
2630 mlx4_master_immediate_activate_vlan_qos(priv, slave, port);
2631 }
2632 return 0;
2633 }
2634 EXPORT_SYMBOL_GPL(mlx4_set_vf_vlan);
2635
2636 mlx4_get_slave_default_vlan -
2637 * retrun true if VST ( default vlan)
2638 * if VST will fill vlan & qos (if not NULL)
2639 bool mlx4_get_slave_default_vlan(struct mlx4_priv *priv, int port, int slave, u16 *vlan, u8 *qos)
2640 {
2641 struct mlx4_vport_oper_state *vp_oper;
2642 struct mlx4_priv *priv;
2643
2644 priv = mlx4_priv(dev);
2645 vp_oper = &priv->mfunc.master.vf_oper[slave].vport[port];
2646
2647 if (MLX4_VGT != vp_oper->state.default_vlan) {
2648 if (vlan)
2649 *vlan = vp_oper->state.default_vlan;
2650 if (qos)
2651 *qos = vp_oper->state.default_qos;
2652 return true;
2653 }
2654 return false;
2655 }
2656 EXPORT_SYMBOL_GPL(mlx4_get_slave_default_vlan);
2657
2658 int mlx4_set_vf_spoofchk(struct mlx4_priv *priv, int port, int vf, bool setting)
2659 {
2660 struct mlx4_priv *priv = mlx4_priv(dev);
2661 struct mlx4_vport_state *s_info;
2662 int slave;
2663
2664 if ((!mlx4_is_master(dev)) ||
2665 !(dev->caps.flags2 & MLX4_DEV_CAP_FLAG2_FSM))
2666 return -EPROTONOSUPPORT;
2667
2668 slave = mlx4_get_slave_indx(dev, vf);
2669 if (slave < 0)
2670 return -EINVAL;
2671
2672 s_info = &priv->mfunc.master.vf_admin[slave].vport[port];
2673 s_info->spoofchk = setting;
2674
2675 return 0;
2676 }
2677 EXPORT_SYMBOL_GPL(mlx4_set_vf_spoofchk);
2678
2679 int mlx4_set_vf_link_state(struct mlx4_priv *priv, int port, int vf, int link_state)
2680 {
2681 struct mlx4_priv *priv = mlx4_priv(dev);
2682 struct mlx4_vport_state *s_info;
2683 struct mlx4_vport_oper_state *vp_oper;
2684 int slave;
2685 u8 link_stat_event;
2686
2687 slave = mlx4_get_slave_indx(dev, vf);
2688 if (slave < 0)
2689 return -EINVAL;
2690
2691 switch (link_state) {
2692 case IFLA_VF_LINK_STATE_AUTO:
2693 get link curent state
2694 if (!priv->sense.do_sense_port[port])
2695 link_stat_event = MLX4_PORT_CHANGE_SUBTYPE_ACTIVE;
2696 else
2697 link_stat_event = MLX4_PORT_CHANGE_SUBTYPE_DOWN;
2698 break;
2699
2700 case IFLA_VF_LINK_STATE_ENABLE:
2701 link_stat_event = MLX4_PORT_CHANGE_SUBTYPE_ACTIVE;
2702 break;
2703
2704 case IFLA_VF_LINK_STATE_DISABLE:
2705 link_stat_event = MLX4_PORT_CHANGE_SUBTYPE_DOWN;
2706 break;
2707
2708 default:
2709 MLX4_DEBUG( "unknown value for link_state %02x on slave %d port %d\n",
2710 link_state, slave, port);
2711 return -EINVAL;
2712 };
2713 update the admin & oper state on the link state
2714 s_info = &priv->mfunc.master.vf_admin[slave].vport[port];
2715 vp_oper = &priv->mfunc.master.vf_oper[slave].vport[port];
2716 s_info->link_state = link_state;
2717 vp_oper->state.link_state = link_state;
2718
2719 send event
2720 mlx4_gen_port_state_change_eqe(dev, slave, port, link_stat_event);
2721 return 0;
2722 }
2723 EXPORT_SYMBOL_GPL(mlx4_set_vf_link_state);
2724
2725 int mlx4_get_vf_link_state(struct mlx4_priv *priv, int port, int vf)
2726 {
2727 struct mlx4_priv *priv = mlx4_priv(dev);
2728 struct mlx4_vport_state *s_info;
2729 int slave;
2730
2731 if (!mlx4_is_master(dev))
2732 return -EPROTONOSUPPORT;
2733
2734 slave = mlx4_get_slave_indx(dev, vf);
2735 if (slave < 0)
2736 return -EINVAL;
2737
2738 s_info = &priv->mfunc.master.vf_admin[slave].vport[port];
2739
2740 return s_info->link_state;
2741 }
2742 EXPORT_SYMBOL_GPL(mlx4_get_vf_link_state);*/
2743