RDMA/cma: Queue IB CM MRAs to avoid unnecessary remote retries
[linux-block.git] / drivers / infiniband / hw / mthca / mthca_cmd.c
CommitLineData
1da177e4
LT
1/*
2 * Copyright (c) 2004, 2005 Topspin Communications. All rights reserved.
2a1d9b7f 3 * Copyright (c) 2005 Mellanox Technologies. All rights reserved.
4885bf64 4 * Copyright (c) 2005, 2006 Cisco Systems. All rights reserved.
1da177e4
LT
5 *
6 * This software is available to you under a choice of one of two
7 * licenses. You may choose to be licensed under the terms of the GNU
8 * General Public License (GPL) Version 2, available from the file
9 * COPYING in the main directory of this source tree, or the
10 * OpenIB.org BSD license below:
11 *
12 * Redistribution and use in source and binary forms, with or
13 * without modification, are permitted provided that the following
14 * conditions are met:
15 *
16 * - Redistributions of source code must retain the above
17 * copyright notice, this list of conditions and the following
18 * disclaimer.
19 *
20 * - Redistributions in binary form must reproduce the above
21 * copyright notice, this list of conditions and the following
22 * disclaimer in the documentation and/or other materials
23 * provided with the distribution.
24 *
25 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
26 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
27 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
28 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
29 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
30 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
31 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
32 * SOFTWARE.
33 *
34 * $Id: mthca_cmd.c 1349 2004-12-16 21:09:43Z roland $
35 */
36
2a214182 37#include <linux/completion.h>
1da177e4
LT
38#include <linux/pci.h>
39#include <linux/errno.h>
e8edc6e0 40#include <linux/sched.h>
1da177e4 41#include <asm/io.h>
a4d61e84 42#include <rdma/ib_mad.h>
1da177e4
LT
43
44#include "mthca_dev.h"
45#include "mthca_config_reg.h"
46#include "mthca_cmd.h"
47#include "mthca_memfree.h"
48
49#define CMD_POLL_TOKEN 0xffff
50
51enum {
52 HCR_IN_PARAM_OFFSET = 0x00,
53 HCR_IN_MODIFIER_OFFSET = 0x08,
54 HCR_OUT_PARAM_OFFSET = 0x0c,
55 HCR_TOKEN_OFFSET = 0x14,
56 HCR_STATUS_OFFSET = 0x18,
57
58 HCR_OPMOD_SHIFT = 12,
59 HCA_E_BIT = 22,
60 HCR_GO_BIT = 23
61};
62
63enum {
64 /* initialization and general commands */
65 CMD_SYS_EN = 0x1,
66 CMD_SYS_DIS = 0x2,
67 CMD_MAP_FA = 0xfff,
68 CMD_UNMAP_FA = 0xffe,
69 CMD_RUN_FW = 0xff6,
70 CMD_MOD_STAT_CFG = 0x34,
71 CMD_QUERY_DEV_LIM = 0x3,
72 CMD_QUERY_FW = 0x4,
73 CMD_ENABLE_LAM = 0xff8,
74 CMD_DISABLE_LAM = 0xff7,
75 CMD_QUERY_DDR = 0x5,
76 CMD_QUERY_ADAPTER = 0x6,
77 CMD_INIT_HCA = 0x7,
78 CMD_CLOSE_HCA = 0x8,
79 CMD_INIT_IB = 0x9,
80 CMD_CLOSE_IB = 0xa,
81 CMD_QUERY_HCA = 0xb,
82 CMD_SET_IB = 0xc,
83 CMD_ACCESS_DDR = 0x2e,
84 CMD_MAP_ICM = 0xffa,
85 CMD_UNMAP_ICM = 0xff9,
86 CMD_MAP_ICM_AUX = 0xffc,
87 CMD_UNMAP_ICM_AUX = 0xffb,
88 CMD_SET_ICM_SIZE = 0xffd,
89
90 /* TPT commands */
91 CMD_SW2HW_MPT = 0xd,
92 CMD_QUERY_MPT = 0xe,
93 CMD_HW2SW_MPT = 0xf,
94 CMD_READ_MTT = 0x10,
95 CMD_WRITE_MTT = 0x11,
96 CMD_SYNC_TPT = 0x2f,
97
98 /* EQ commands */
99 CMD_MAP_EQ = 0x12,
100 CMD_SW2HW_EQ = 0x13,
101 CMD_HW2SW_EQ = 0x14,
102 CMD_QUERY_EQ = 0x15,
103
104 /* CQ commands */
105 CMD_SW2HW_CQ = 0x16,
106 CMD_HW2SW_CQ = 0x17,
107 CMD_QUERY_CQ = 0x18,
108 CMD_RESIZE_CQ = 0x2c,
109
110 /* SRQ commands */
111 CMD_SW2HW_SRQ = 0x35,
112 CMD_HW2SW_SRQ = 0x36,
113 CMD_QUERY_SRQ = 0x37,
ec34a922 114 CMD_ARM_SRQ = 0x40,
1da177e4
LT
115
116 /* QP/EE commands */
117 CMD_RST2INIT_QPEE = 0x19,
118 CMD_INIT2RTR_QPEE = 0x1a,
119 CMD_RTR2RTS_QPEE = 0x1b,
120 CMD_RTS2RTS_QPEE = 0x1c,
121 CMD_SQERR2RTS_QPEE = 0x1d,
122 CMD_2ERR_QPEE = 0x1e,
123 CMD_RTS2SQD_QPEE = 0x1f,
124 CMD_SQD2SQD_QPEE = 0x38,
125 CMD_SQD2RTS_QPEE = 0x20,
126 CMD_ERR2RST_QPEE = 0x21,
127 CMD_QUERY_QPEE = 0x22,
128 CMD_INIT2INIT_QPEE = 0x2d,
129 CMD_SUSPEND_QPEE = 0x32,
130 CMD_UNSUSPEND_QPEE = 0x33,
131 /* special QPs and management commands */
132 CMD_CONF_SPECIAL_QP = 0x23,
133 CMD_MAD_IFC = 0x24,
134
135 /* multicast commands */
136 CMD_READ_MGM = 0x25,
137 CMD_WRITE_MGM = 0x26,
138 CMD_MGID_HASH = 0x27,
139
140 /* miscellaneous commands */
141 CMD_DIAG_RPRT = 0x30,
142 CMD_NOP = 0x31,
143
144 /* debug commands */
145 CMD_QUERY_DEBUG_MSG = 0x2a,
146 CMD_SET_DEBUG_MSG = 0x2b,
147};
148
149/*
150 * According to Mellanox code, FW may be starved and never complete
151 * commands. So we can't use strict timeouts described in PRM -- we
152 * just arbitrarily select 60 seconds for now.
153 */
154#if 0
155/*
156 * Round up and add 1 to make sure we get the full wait time (since we
157 * will be starting in the middle of a jiffy)
158 */
159enum {
160 CMD_TIME_CLASS_A = (HZ + 999) / 1000 + 1,
161 CMD_TIME_CLASS_B = (HZ + 99) / 100 + 1,
162 CMD_TIME_CLASS_C = (HZ + 9) / 10 + 1
163};
164#else
165enum {
166 CMD_TIME_CLASS_A = 60 * HZ,
167 CMD_TIME_CLASS_B = 60 * HZ,
168 CMD_TIME_CLASS_C = 60 * HZ
169};
170#endif
171
172enum {
173 GO_BIT_TIMEOUT = HZ * 10
174};
175
176struct mthca_cmd_context {
177 struct completion done;
1da177e4
LT
178 int result;
179 int next;
180 u64 out_param;
181 u16 token;
182 u8 status;
183};
184
1db76c14 185static int fw_cmd_doorbell = 0;
14abdffc
EC
186module_param(fw_cmd_doorbell, int, 0644);
187MODULE_PARM_DESC(fw_cmd_doorbell, "post FW commands through doorbell page if nonzero "
188 "(and supported by FW)");
189
1da177e4
LT
190static inline int go_bit(struct mthca_dev *dev)
191{
192 return readl(dev->hcr + HCR_STATUS_OFFSET) &
193 swab32(1 << HCR_GO_BIT);
194}
195
14abdffc
EC
196static void mthca_cmd_post_dbell(struct mthca_dev *dev,
197 u64 in_param,
198 u64 out_param,
199 u32 in_modifier,
200 u8 op_modifier,
201 u16 op,
202 u16 token)
1da177e4 203{
14abdffc
EC
204 void __iomem *ptr = dev->cmd.dbell_map;
205 u16 *offs = dev->cmd.dbell_offsets;
1da177e4 206
14abdffc
EC
207 __raw_writel((__force u32) cpu_to_be32(in_param >> 32), ptr + offs[0]);
208 wmb();
209 __raw_writel((__force u32) cpu_to_be32(in_param & 0xfffffffful), ptr + offs[1]);
210 wmb();
211 __raw_writel((__force u32) cpu_to_be32(in_modifier), ptr + offs[2]);
212 wmb();
213 __raw_writel((__force u32) cpu_to_be32(out_param >> 32), ptr + offs[3]);
214 wmb();
215 __raw_writel((__force u32) cpu_to_be32(out_param & 0xfffffffful), ptr + offs[4]);
216 wmb();
217 __raw_writel((__force u32) cpu_to_be32(token << 16), ptr + offs[5]);
218 wmb();
219 __raw_writel((__force u32) cpu_to_be32((1 << HCR_GO_BIT) |
220 (1 << HCA_E_BIT) |
221 (op_modifier << HCR_OPMOD_SHIFT) |
222 op), ptr + offs[6]);
223 wmb();
224 __raw_writel((__force u32) 0, ptr + offs[7]);
225 wmb();
226}
1da177e4 227
14abdffc
EC
228static int mthca_cmd_post_hcr(struct mthca_dev *dev,
229 u64 in_param,
230 u64 out_param,
231 u32 in_modifier,
232 u8 op_modifier,
233 u16 op,
234 u16 token,
235 int event)
236{
1da177e4
LT
237 if (event) {
238 unsigned long end = jiffies + GO_BIT_TIMEOUT;
239
240 while (go_bit(dev) && time_before(jiffies, end)) {
241 set_current_state(TASK_RUNNING);
242 schedule();
243 }
244 }
245
14abdffc
EC
246 if (go_bit(dev))
247 return -EAGAIN;
1da177e4
LT
248
249 /*
250 * We use writel (instead of something like memcpy_toio)
251 * because writes of less than 32 bits to the HCR don't work
252 * (and some architectures such as ia64 implement memcpy_toio
253 * in terms of writeb).
254 */
97f52eb4
SH
255 __raw_writel((__force u32) cpu_to_be32(in_param >> 32), dev->hcr + 0 * 4);
256 __raw_writel((__force u32) cpu_to_be32(in_param & 0xfffffffful), dev->hcr + 1 * 4);
257 __raw_writel((__force u32) cpu_to_be32(in_modifier), dev->hcr + 2 * 4);
258 __raw_writel((__force u32) cpu_to_be32(out_param >> 32), dev->hcr + 3 * 4);
259 __raw_writel((__force u32) cpu_to_be32(out_param & 0xfffffffful), dev->hcr + 4 * 4);
260 __raw_writel((__force u32) cpu_to_be32(token << 16), dev->hcr + 5 * 4);
1da177e4
LT
261
262 /* __raw_writel may not order writes. */
263 wmb();
264
97f52eb4
SH
265 __raw_writel((__force u32) cpu_to_be32((1 << HCR_GO_BIT) |
266 (event ? (1 << HCA_E_BIT) : 0) |
267 (op_modifier << HCR_OPMOD_SHIFT) |
268 op), dev->hcr + 6 * 4);
1da177e4 269
14abdffc
EC
270 return 0;
271}
272
273static int mthca_cmd_post(struct mthca_dev *dev,
274 u64 in_param,
275 u64 out_param,
276 u32 in_modifier,
277 u8 op_modifier,
278 u16 op,
279 u16 token,
280 int event)
281{
282 int err = 0;
283
284 mutex_lock(&dev->cmd.hcr_mutex);
285
286 if (event && dev->cmd.flags & MTHCA_CMD_POST_DOORBELLS && fw_cmd_doorbell)
287 mthca_cmd_post_dbell(dev, in_param, out_param, in_modifier,
288 op_modifier, op, token);
289 else
290 err = mthca_cmd_post_hcr(dev, in_param, out_param, in_modifier,
291 op_modifier, op, token, event);
292
fd9cfdd1 293 mutex_unlock(&dev->cmd.hcr_mutex);
1da177e4
LT
294 return err;
295}
296
297static int mthca_cmd_poll(struct mthca_dev *dev,
298 u64 in_param,
299 u64 *out_param,
300 int out_is_imm,
301 u32 in_modifier,
302 u8 op_modifier,
303 u16 op,
304 unsigned long timeout,
305 u8 *status)
306{
307 int err = 0;
308 unsigned long end;
309
e3aa31c5 310 down(&dev->cmd.poll_sem);
1da177e4
LT
311
312 err = mthca_cmd_post(dev, in_param,
313 out_param ? *out_param : 0,
314 in_modifier, op_modifier,
315 op, CMD_POLL_TOKEN, 0);
316 if (err)
317 goto out;
318
319 end = timeout + jiffies;
320 while (go_bit(dev) && time_before(jiffies, end)) {
321 set_current_state(TASK_RUNNING);
322 schedule();
323 }
324
325 if (go_bit(dev)) {
326 err = -EBUSY;
327 goto out;
328 }
329
97f52eb4 330 if (out_is_imm)
2fa5e2eb 331 *out_param =
97f52eb4
SH
332 (u64) be32_to_cpu((__force __be32)
333 __raw_readl(dev->hcr + HCR_OUT_PARAM_OFFSET)) << 32 |
334 (u64) be32_to_cpu((__force __be32)
335 __raw_readl(dev->hcr + HCR_OUT_PARAM_OFFSET + 4));
1da177e4 336
97f52eb4 337 *status = be32_to_cpu((__force __be32) __raw_readl(dev->hcr + HCR_STATUS_OFFSET)) >> 24;
1da177e4
LT
338
339out:
340 up(&dev->cmd.poll_sem);
341 return err;
342}
343
344void mthca_cmd_event(struct mthca_dev *dev,
345 u16 token,
346 u8 status,
347 u64 out_param)
348{
349 struct mthca_cmd_context *context =
350 &dev->cmd.context[token & dev->cmd.token_mask];
351
352 /* previously timed out command completing at long last */
353 if (token != context->token)
354 return;
355
356 context->result = 0;
357 context->status = status;
358 context->out_param = out_param;
359
1da177e4
LT
360 complete(&context->done);
361}
362
1da177e4
LT
363static int mthca_cmd_wait(struct mthca_dev *dev,
364 u64 in_param,
365 u64 *out_param,
366 int out_is_imm,
367 u32 in_modifier,
368 u8 op_modifier,
369 u16 op,
370 unsigned long timeout,
371 u8 *status)
372{
373 int err = 0;
374 struct mthca_cmd_context *context;
375
e3aa31c5 376 down(&dev->cmd.event_sem);
1da177e4
LT
377
378 spin_lock(&dev->cmd.context_lock);
379 BUG_ON(dev->cmd.free_head < 0);
380 context = &dev->cmd.context[dev->cmd.free_head];
c1f74958 381 context->token += dev->cmd.token_mask + 1;
1da177e4
LT
382 dev->cmd.free_head = context->next;
383 spin_unlock(&dev->cmd.context_lock);
384
385 init_completion(&context->done);
386
387 err = mthca_cmd_post(dev, in_param,
388 out_param ? *out_param : 0,
389 in_modifier, op_modifier,
390 op, context->token, 1);
391 if (err)
392 goto out;
393
e9cd5941
RD
394 if (!wait_for_completion_timeout(&context->done, timeout)) {
395 err = -EBUSY;
396 goto out;
397 }
1da177e4
LT
398
399 err = context->result;
400 if (err)
401 goto out;
402
403 *status = context->status;
404 if (*status)
405 mthca_dbg(dev, "Command %02x completed with status %02x\n",
406 op, *status);
407
408 if (out_is_imm)
409 *out_param = context->out_param;
410
411out:
412 spin_lock(&dev->cmd.context_lock);
413 context->next = dev->cmd.free_head;
414 dev->cmd.free_head = context - dev->cmd.context;
415 spin_unlock(&dev->cmd.context_lock);
416
417 up(&dev->cmd.event_sem);
418 return err;
419}
420
421/* Invoke a command with an output mailbox */
422static int mthca_cmd_box(struct mthca_dev *dev,
423 u64 in_param,
424 u64 out_param,
425 u32 in_modifier,
426 u8 op_modifier,
427 u16 op,
428 unsigned long timeout,
429 u8 *status)
430{
14abdffc 431 if (dev->cmd.flags & MTHCA_CMD_USE_EVENTS)
1da177e4
LT
432 return mthca_cmd_wait(dev, in_param, &out_param, 0,
433 in_modifier, op_modifier, op,
434 timeout, status);
435 else
436 return mthca_cmd_poll(dev, in_param, &out_param, 0,
437 in_modifier, op_modifier, op,
438 timeout, status);
439}
440
441/* Invoke a command with no output parameter */
442static int mthca_cmd(struct mthca_dev *dev,
443 u64 in_param,
444 u32 in_modifier,
445 u8 op_modifier,
446 u16 op,
447 unsigned long timeout,
448 u8 *status)
449{
450 return mthca_cmd_box(dev, in_param, 0, in_modifier,
451 op_modifier, op, timeout, status);
452}
453
454/*
455 * Invoke a command with an immediate output parameter (and copy the
456 * output into the caller's out_param pointer after the command
457 * executes).
458 */
459static int mthca_cmd_imm(struct mthca_dev *dev,
460 u64 in_param,
461 u64 *out_param,
462 u32 in_modifier,
463 u8 op_modifier,
464 u16 op,
465 unsigned long timeout,
466 u8 *status)
467{
14abdffc 468 if (dev->cmd.flags & MTHCA_CMD_USE_EVENTS)
1da177e4
LT
469 return mthca_cmd_wait(dev, in_param, out_param, 1,
470 in_modifier, op_modifier, op,
471 timeout, status);
472 else
473 return mthca_cmd_poll(dev, in_param, out_param, 1,
474 in_modifier, op_modifier, op,
475 timeout, status);
476}
477
80fd8238
RD
478int mthca_cmd_init(struct mthca_dev *dev)
479{
fd9cfdd1 480 mutex_init(&dev->cmd.hcr_mutex);
80fd8238 481 sema_init(&dev->cmd.poll_sem, 1);
14abdffc 482 dev->cmd.flags = 0;
80fd8238
RD
483
484 dev->hcr = ioremap(pci_resource_start(dev->pdev, 0) + MTHCA_HCR_BASE,
485 MTHCA_HCR_SIZE);
486 if (!dev->hcr) {
487 mthca_err(dev, "Couldn't map command register.");
488 return -ENOMEM;
489 }
490
ed878458
RD
491 dev->cmd.pool = pci_pool_create("mthca_cmd", dev->pdev,
492 MTHCA_MAILBOX_SIZE,
493 MTHCA_MAILBOX_SIZE, 0);
494 if (!dev->cmd.pool) {
495 iounmap(dev->hcr);
496 return -ENOMEM;
497 }
498
80fd8238
RD
499 return 0;
500}
501
502void mthca_cmd_cleanup(struct mthca_dev *dev)
503{
ed878458 504 pci_pool_destroy(dev->cmd.pool);
80fd8238 505 iounmap(dev->hcr);
14abdffc
EC
506 if (dev->cmd.flags & MTHCA_CMD_POST_DOORBELLS)
507 iounmap(dev->cmd.dbell_map);
80fd8238
RD
508}
509
1da177e4
LT
510/*
511 * Switch to using events to issue FW commands (should be called after
512 * event queue to command events has been initialized).
513 */
514int mthca_cmd_use_events(struct mthca_dev *dev)
515{
516 int i;
517
518 dev->cmd.context = kmalloc(dev->cmd.max_cmds *
519 sizeof (struct mthca_cmd_context),
520 GFP_KERNEL);
521 if (!dev->cmd.context)
522 return -ENOMEM;
523
524 for (i = 0; i < dev->cmd.max_cmds; ++i) {
525 dev->cmd.context[i].token = i;
526 dev->cmd.context[i].next = i + 1;
1da177e4
LT
527 }
528
529 dev->cmd.context[dev->cmd.max_cmds - 1].next = -1;
530 dev->cmd.free_head = 0;
531
532 sema_init(&dev->cmd.event_sem, dev->cmd.max_cmds);
533 spin_lock_init(&dev->cmd.context_lock);
534
535 for (dev->cmd.token_mask = 1;
536 dev->cmd.token_mask < dev->cmd.max_cmds;
537 dev->cmd.token_mask <<= 1)
538 ; /* nothing */
539 --dev->cmd.token_mask;
540
14abdffc
EC
541 dev->cmd.flags |= MTHCA_CMD_USE_EVENTS;
542
1da177e4
LT
543 down(&dev->cmd.poll_sem);
544
545 return 0;
546}
547
548/*
549 * Switch back to polling (used when shutting down the device)
550 */
551void mthca_cmd_use_polling(struct mthca_dev *dev)
552{
553 int i;
554
14abdffc 555 dev->cmd.flags &= ~MTHCA_CMD_USE_EVENTS;
1da177e4
LT
556
557 for (i = 0; i < dev->cmd.max_cmds; ++i)
558 down(&dev->cmd.event_sem);
559
560 kfree(dev->cmd.context);
561
562 up(&dev->cmd.poll_sem);
563}
564
ed878458 565struct mthca_mailbox *mthca_alloc_mailbox(struct mthca_dev *dev,
87b750dc 566 gfp_t gfp_mask)
ed878458
RD
567{
568 struct mthca_mailbox *mailbox;
569
570 mailbox = kmalloc(sizeof *mailbox, gfp_mask);
571 if (!mailbox)
572 return ERR_PTR(-ENOMEM);
573
574 mailbox->buf = pci_pool_alloc(dev->cmd.pool, gfp_mask, &mailbox->dma);
575 if (!mailbox->buf) {
576 kfree(mailbox);
577 return ERR_PTR(-ENOMEM);
578 }
579
580 return mailbox;
581}
582
583void mthca_free_mailbox(struct mthca_dev *dev, struct mthca_mailbox *mailbox)
584{
585 if (!mailbox)
586 return;
587
588 pci_pool_free(dev->cmd.pool, mailbox->buf, mailbox->dma);
589 kfree(mailbox);
590}
591
1da177e4
LT
592int mthca_SYS_EN(struct mthca_dev *dev, u8 *status)
593{
594 u64 out;
595 int ret;
596
597 ret = mthca_cmd_imm(dev, 0, &out, 0, 0, CMD_SYS_EN, HZ, status);
598
599 if (*status == MTHCA_CMD_STAT_DDR_MEM_ERR)
600 mthca_warn(dev, "SYS_EN DDR error: syn=%x, sock=%d, "
601 "sladdr=%d, SPD source=%s\n",
602 (int) (out >> 6) & 0xf, (int) (out >> 4) & 3,
603 (int) (out >> 1) & 7, (int) out & 1 ? "NVMEM" : "DIMM");
604
605 return ret;
606}
607
608int mthca_SYS_DIS(struct mthca_dev *dev, u8 *status)
609{
610 return mthca_cmd(dev, 0, 0, 0, CMD_SYS_DIS, HZ, status);
611}
612
613static int mthca_map_cmd(struct mthca_dev *dev, u16 op, struct mthca_icm *icm,
614 u64 virt, u8 *status)
615{
ed878458 616 struct mthca_mailbox *mailbox;
1da177e4 617 struct mthca_icm_iter iter;
ed878458 618 __be64 *pages;
1da177e4
LT
619 int lg;
620 int nent = 0;
621 int i;
622 int err = 0;
623 int ts = 0, tc = 0;
624
ed878458
RD
625 mailbox = mthca_alloc_mailbox(dev, GFP_KERNEL);
626 if (IS_ERR(mailbox))
627 return PTR_ERR(mailbox);
628 memset(mailbox->buf, 0, MTHCA_MAILBOX_SIZE);
629 pages = mailbox->buf;
1da177e4
LT
630
631 for (mthca_icm_first(icm, &iter);
632 !mthca_icm_last(&iter);
633 mthca_icm_next(&iter)) {
634 /*
635 * We have to pass pages that are aligned to their
636 * size, so find the least significant 1 in the
637 * address or size and use that as our log2 size.
638 */
639 lg = ffs(mthca_icm_addr(&iter) | mthca_icm_size(&iter)) - 1;
8d3ef29d
IR
640 if (lg < MTHCA_ICM_PAGE_SHIFT) {
641 mthca_warn(dev, "Got FW area not aligned to %d (%llx/%lx).\n",
642 MTHCA_ICM_PAGE_SIZE,
1da177e4
LT
643 (unsigned long long) mthca_icm_addr(&iter),
644 mthca_icm_size(&iter));
645 err = -EINVAL;
646 goto out;
647 }
59f174fa 648 for (i = 0; i < mthca_icm_size(&iter) >> lg; ++i) {
1da177e4 649 if (virt != -1) {
ed878458 650 pages[nent * 2] = cpu_to_be64(virt);
1da177e4
LT
651 virt += 1 << lg;
652 }
653
8d3ef29d
IR
654 pages[nent * 2 + 1] =
655 cpu_to_be64((mthca_icm_addr(&iter) + (i << lg)) |
656 (lg - MTHCA_ICM_PAGE_SHIFT));
1da177e4
LT
657 ts += 1 << (lg - 10);
658 ++tc;
659
44dd823b 660 if (++nent == MTHCA_MAILBOX_SIZE / 16) {
ed878458 661 err = mthca_cmd(dev, mailbox->dma, nent, 0, op,
1da177e4
LT
662 CMD_TIME_CLASS_B, status);
663 if (err || *status)
664 goto out;
665 nent = 0;
666 }
667 }
668 }
669
670 if (nent)
ed878458 671 err = mthca_cmd(dev, mailbox->dma, nent, 0, op,
1da177e4
LT
672 CMD_TIME_CLASS_B, status);
673
674 switch (op) {
675 case CMD_MAP_FA:
676 mthca_dbg(dev, "Mapped %d chunks/%d KB for FW.\n", tc, ts);
677 break;
678 case CMD_MAP_ICM_AUX:
679 mthca_dbg(dev, "Mapped %d chunks/%d KB for ICM aux.\n", tc, ts);
680 break;
681 case CMD_MAP_ICM:
682 mthca_dbg(dev, "Mapped %d chunks/%d KB at %llx for ICM.\n",
683 tc, ts, (unsigned long long) virt - (ts << 10));
684 break;
685 }
686
687out:
ed878458 688 mthca_free_mailbox(dev, mailbox);
1da177e4
LT
689 return err;
690}
691
692int mthca_MAP_FA(struct mthca_dev *dev, struct mthca_icm *icm, u8 *status)
693{
694 return mthca_map_cmd(dev, CMD_MAP_FA, icm, -1, status);
695}
696
697int mthca_UNMAP_FA(struct mthca_dev *dev, u8 *status)
698{
699 return mthca_cmd(dev, 0, 0, 0, CMD_UNMAP_FA, CMD_TIME_CLASS_B, status);
700}
701
702int mthca_RUN_FW(struct mthca_dev *dev, u8 *status)
703{
704 return mthca_cmd(dev, 0, 0, 0, CMD_RUN_FW, CMD_TIME_CLASS_A, status);
705}
706
14abdffc
EC
707static void mthca_setup_cmd_doorbells(struct mthca_dev *dev, u64 base)
708{
709 unsigned long addr;
710 u16 max_off = 0;
711 int i;
712
713 for (i = 0; i < 8; ++i)
714 max_off = max(max_off, dev->cmd.dbell_offsets[i]);
715
716 if ((base & PAGE_MASK) != ((base + max_off) & PAGE_MASK)) {
717 mthca_warn(dev, "Firmware doorbell region at 0x%016llx, "
718 "length 0x%x crosses a page boundary\n",
719 (unsigned long long) base, max_off);
720 return;
721 }
722
723 addr = pci_resource_start(dev->pdev, 2) +
724 ((pci_resource_len(dev->pdev, 2) - 1) & base);
725 dev->cmd.dbell_map = ioremap(addr, max_off + sizeof(u32));
726 if (!dev->cmd.dbell_map)
727 return;
728
729 dev->cmd.flags |= MTHCA_CMD_POST_DOORBELLS;
730 mthca_dbg(dev, "Mapped doorbell page for posting FW commands\n");
731}
732
1da177e4
LT
733int mthca_QUERY_FW(struct mthca_dev *dev, u8 *status)
734{
ed878458 735 struct mthca_mailbox *mailbox;
1da177e4 736 u32 *outbox;
14abdffc
EC
737 u64 base;
738 u32 tmp;
1da177e4
LT
739 int err = 0;
740 u8 lg;
14abdffc 741 int i;
1da177e4
LT
742
743#define QUERY_FW_OUT_SIZE 0x100
744#define QUERY_FW_VER_OFFSET 0x00
745#define QUERY_FW_MAX_CMD_OFFSET 0x0f
746#define QUERY_FW_ERR_START_OFFSET 0x30
747#define QUERY_FW_ERR_SIZE_OFFSET 0x38
748
14abdffc
EC
749#define QUERY_FW_CMD_DB_EN_OFFSET 0x10
750#define QUERY_FW_CMD_DB_OFFSET 0x50
751#define QUERY_FW_CMD_DB_BASE 0x60
752
1da177e4
LT
753#define QUERY_FW_START_OFFSET 0x20
754#define QUERY_FW_END_OFFSET 0x28
755
756#define QUERY_FW_SIZE_OFFSET 0x00
757#define QUERY_FW_CLR_INT_BASE_OFFSET 0x20
758#define QUERY_FW_EQ_ARM_BASE_OFFSET 0x40
759#define QUERY_FW_EQ_SET_CI_BASE_OFFSET 0x48
760
ed878458
RD
761 mailbox = mthca_alloc_mailbox(dev, GFP_KERNEL);
762 if (IS_ERR(mailbox))
763 return PTR_ERR(mailbox);
764 outbox = mailbox->buf;
1da177e4 765
ed878458 766 err = mthca_cmd_box(dev, 0, mailbox->dma, 0, 0, CMD_QUERY_FW,
1da177e4
LT
767 CMD_TIME_CLASS_A, status);
768
769 if (err)
770 goto out;
771
772 MTHCA_GET(dev->fw_ver, outbox, QUERY_FW_VER_OFFSET);
773 /*
3e1db334 774 * FW subminor version is at more significant bits than minor
1da177e4
LT
775 * version, so swap here.
776 */
777 dev->fw_ver = (dev->fw_ver & 0xffff00000000ull) |
778 ((dev->fw_ver & 0xffff0000ull) >> 16) |
779 ((dev->fw_ver & 0x0000ffffull) << 16);
780
8fdf679f
RD
781 MTHCA_GET(lg, outbox, QUERY_FW_MAX_CMD_OFFSET);
782 dev->cmd.max_cmds = 1 << lg;
783
14abdffc
EC
784 mthca_dbg(dev, "FW version %012llx, max commands %d\n",
785 (unsigned long long) dev->fw_ver, dev->cmd.max_cmds);
786
3d155f8c
RD
787 MTHCA_GET(dev->catas_err.addr, outbox, QUERY_FW_ERR_START_OFFSET);
788 MTHCA_GET(dev->catas_err.size, outbox, QUERY_FW_ERR_SIZE_OFFSET);
1da177e4 789
3d155f8c
RD
790 mthca_dbg(dev, "Catastrophic error buffer at 0x%llx, size 0x%x\n",
791 (unsigned long long) dev->catas_err.addr, dev->catas_err.size);
1da177e4 792
14abdffc
EC
793 MTHCA_GET(tmp, outbox, QUERY_FW_CMD_DB_EN_OFFSET);
794 if (tmp & 0x1) {
795 mthca_dbg(dev, "FW supports commands through doorbells\n");
796
797 MTHCA_GET(base, outbox, QUERY_FW_CMD_DB_BASE);
798 for (i = 0; i < MTHCA_CMD_NUM_DBELL_DWORDS; ++i)
799 MTHCA_GET(dev->cmd.dbell_offsets[i], outbox,
800 QUERY_FW_CMD_DB_OFFSET + (i << 1));
801
802 mthca_setup_cmd_doorbells(dev, base);
803 }
804
d10ddbf6 805 if (mthca_is_memfree(dev)) {
1da177e4
LT
806 MTHCA_GET(dev->fw.arbel.fw_pages, outbox, QUERY_FW_SIZE_OFFSET);
807 MTHCA_GET(dev->fw.arbel.clr_int_base, outbox, QUERY_FW_CLR_INT_BASE_OFFSET);
808 MTHCA_GET(dev->fw.arbel.eq_arm_base, outbox, QUERY_FW_EQ_ARM_BASE_OFFSET);
809 MTHCA_GET(dev->fw.arbel.eq_set_ci_base, outbox, QUERY_FW_EQ_SET_CI_BASE_OFFSET);
810 mthca_dbg(dev, "FW size %d KB\n", dev->fw.arbel.fw_pages << 2);
811
812 /*
8d3ef29d
IR
813 * Round up number of system pages needed in case
814 * MTHCA_ICM_PAGE_SIZE < PAGE_SIZE.
1da177e4
LT
815 */
816 dev->fw.arbel.fw_pages =
8d3ef29d
IR
817 ALIGN(dev->fw.arbel.fw_pages, PAGE_SIZE / MTHCA_ICM_PAGE_SIZE) >>
818 (PAGE_SHIFT - MTHCA_ICM_PAGE_SHIFT);
1da177e4
LT
819
820 mthca_dbg(dev, "Clear int @ %llx, EQ arm @ %llx, EQ set CI @ %llx\n",
821 (unsigned long long) dev->fw.arbel.clr_int_base,
822 (unsigned long long) dev->fw.arbel.eq_arm_base,
823 (unsigned long long) dev->fw.arbel.eq_set_ci_base);
824 } else {
825 MTHCA_GET(dev->fw.tavor.fw_start, outbox, QUERY_FW_START_OFFSET);
826 MTHCA_GET(dev->fw.tavor.fw_end, outbox, QUERY_FW_END_OFFSET);
827
828 mthca_dbg(dev, "FW size %d KB (start %llx, end %llx)\n",
829 (int) ((dev->fw.tavor.fw_end - dev->fw.tavor.fw_start) >> 10),
830 (unsigned long long) dev->fw.tavor.fw_start,
831 (unsigned long long) dev->fw.tavor.fw_end);
832 }
833
834out:
ed878458 835 mthca_free_mailbox(dev, mailbox);
1da177e4
LT
836 return err;
837}
838
839int mthca_ENABLE_LAM(struct mthca_dev *dev, u8 *status)
840{
ed878458 841 struct mthca_mailbox *mailbox;
1da177e4
LT
842 u8 info;
843 u32 *outbox;
1da177e4
LT
844 int err = 0;
845
846#define ENABLE_LAM_OUT_SIZE 0x100
847#define ENABLE_LAM_START_OFFSET 0x00
848#define ENABLE_LAM_END_OFFSET 0x08
849#define ENABLE_LAM_INFO_OFFSET 0x13
850
851#define ENABLE_LAM_INFO_HIDDEN_FLAG (1 << 4)
852#define ENABLE_LAM_INFO_ECC_MASK 0x3
853
ed878458
RD
854 mailbox = mthca_alloc_mailbox(dev, GFP_KERNEL);
855 if (IS_ERR(mailbox))
856 return PTR_ERR(mailbox);
857 outbox = mailbox->buf;
1da177e4 858
ed878458 859 err = mthca_cmd_box(dev, 0, mailbox->dma, 0, 0, CMD_ENABLE_LAM,
1da177e4
LT
860 CMD_TIME_CLASS_C, status);
861
862 if (err)
863 goto out;
864
865 if (*status == MTHCA_CMD_STAT_LAM_NOT_PRE)
866 goto out;
867
868 MTHCA_GET(dev->ddr_start, outbox, ENABLE_LAM_START_OFFSET);
869 MTHCA_GET(dev->ddr_end, outbox, ENABLE_LAM_END_OFFSET);
870 MTHCA_GET(info, outbox, ENABLE_LAM_INFO_OFFSET);
871
872 if (!!(info & ENABLE_LAM_INFO_HIDDEN_FLAG) !=
873 !!(dev->mthca_flags & MTHCA_FLAG_DDR_HIDDEN)) {
874 mthca_info(dev, "FW reports that HCA-attached memory "
875 "is %s hidden; does not match PCI config\n",
876 (info & ENABLE_LAM_INFO_HIDDEN_FLAG) ?
877 "" : "not");
878 }
879 if (info & ENABLE_LAM_INFO_HIDDEN_FLAG)
880 mthca_dbg(dev, "HCA-attached memory is hidden.\n");
881
882 mthca_dbg(dev, "HCA memory size %d KB (start %llx, end %llx)\n",
883 (int) ((dev->ddr_end - dev->ddr_start) >> 10),
884 (unsigned long long) dev->ddr_start,
885 (unsigned long long) dev->ddr_end);
886
887out:
ed878458 888 mthca_free_mailbox(dev, mailbox);
1da177e4
LT
889 return err;
890}
891
892int mthca_DISABLE_LAM(struct mthca_dev *dev, u8 *status)
893{
894 return mthca_cmd(dev, 0, 0, 0, CMD_SYS_DIS, CMD_TIME_CLASS_C, status);
895}
896
897int mthca_QUERY_DDR(struct mthca_dev *dev, u8 *status)
898{
ed878458 899 struct mthca_mailbox *mailbox;
1da177e4
LT
900 u8 info;
901 u32 *outbox;
1da177e4
LT
902 int err = 0;
903
904#define QUERY_DDR_OUT_SIZE 0x100
905#define QUERY_DDR_START_OFFSET 0x00
906#define QUERY_DDR_END_OFFSET 0x08
907#define QUERY_DDR_INFO_OFFSET 0x13
908
909#define QUERY_DDR_INFO_HIDDEN_FLAG (1 << 4)
910#define QUERY_DDR_INFO_ECC_MASK 0x3
911
ed878458
RD
912 mailbox = mthca_alloc_mailbox(dev, GFP_KERNEL);
913 if (IS_ERR(mailbox))
914 return PTR_ERR(mailbox);
915 outbox = mailbox->buf;
1da177e4 916
ed878458 917 err = mthca_cmd_box(dev, 0, mailbox->dma, 0, 0, CMD_QUERY_DDR,
1da177e4
LT
918 CMD_TIME_CLASS_A, status);
919
920 if (err)
921 goto out;
922
923 MTHCA_GET(dev->ddr_start, outbox, QUERY_DDR_START_OFFSET);
924 MTHCA_GET(dev->ddr_end, outbox, QUERY_DDR_END_OFFSET);
925 MTHCA_GET(info, outbox, QUERY_DDR_INFO_OFFSET);
926
927 if (!!(info & QUERY_DDR_INFO_HIDDEN_FLAG) !=
928 !!(dev->mthca_flags & MTHCA_FLAG_DDR_HIDDEN)) {
929 mthca_info(dev, "FW reports that HCA-attached memory "
930 "is %s hidden; does not match PCI config\n",
931 (info & QUERY_DDR_INFO_HIDDEN_FLAG) ?
932 "" : "not");
933 }
934 if (info & QUERY_DDR_INFO_HIDDEN_FLAG)
935 mthca_dbg(dev, "HCA-attached memory is hidden.\n");
936
937 mthca_dbg(dev, "HCA memory size %d KB (start %llx, end %llx)\n",
938 (int) ((dev->ddr_end - dev->ddr_start) >> 10),
939 (unsigned long long) dev->ddr_start,
940 (unsigned long long) dev->ddr_end);
941
942out:
ed878458 943 mthca_free_mailbox(dev, mailbox);
1da177e4
LT
944 return err;
945}
946
947int mthca_QUERY_DEV_LIM(struct mthca_dev *dev,
948 struct mthca_dev_lim *dev_lim, u8 *status)
949{
ed878458 950 struct mthca_mailbox *mailbox;
1da177e4 951 u32 *outbox;
1da177e4
LT
952 u8 field;
953 u16 size;
bf6a9e31 954 u16 stat_rate;
1da177e4
LT
955 int err;
956
957#define QUERY_DEV_LIM_OUT_SIZE 0x100
958#define QUERY_DEV_LIM_MAX_SRQ_SZ_OFFSET 0x10
959#define QUERY_DEV_LIM_MAX_QP_SZ_OFFSET 0x11
960#define QUERY_DEV_LIM_RSVD_QP_OFFSET 0x12
961#define QUERY_DEV_LIM_MAX_QP_OFFSET 0x13
962#define QUERY_DEV_LIM_RSVD_SRQ_OFFSET 0x14
963#define QUERY_DEV_LIM_MAX_SRQ_OFFSET 0x15
964#define QUERY_DEV_LIM_RSVD_EEC_OFFSET 0x16
965#define QUERY_DEV_LIM_MAX_EEC_OFFSET 0x17
966#define QUERY_DEV_LIM_MAX_CQ_SZ_OFFSET 0x19
967#define QUERY_DEV_LIM_RSVD_CQ_OFFSET 0x1a
968#define QUERY_DEV_LIM_MAX_CQ_OFFSET 0x1b
969#define QUERY_DEV_LIM_MAX_MPT_OFFSET 0x1d
970#define QUERY_DEV_LIM_RSVD_EQ_OFFSET 0x1e
971#define QUERY_DEV_LIM_MAX_EQ_OFFSET 0x1f
972#define QUERY_DEV_LIM_RSVD_MTT_OFFSET 0x20
973#define QUERY_DEV_LIM_MAX_MRW_SZ_OFFSET 0x21
974#define QUERY_DEV_LIM_RSVD_MRW_OFFSET 0x22
975#define QUERY_DEV_LIM_MAX_MTT_SEG_OFFSET 0x23
976#define QUERY_DEV_LIM_MAX_AV_OFFSET 0x27
977#define QUERY_DEV_LIM_MAX_REQ_QP_OFFSET 0x29
978#define QUERY_DEV_LIM_MAX_RES_QP_OFFSET 0x2b
979#define QUERY_DEV_LIM_MAX_RDMA_OFFSET 0x2f
980#define QUERY_DEV_LIM_RSZ_SRQ_OFFSET 0x33
981#define QUERY_DEV_LIM_ACK_DELAY_OFFSET 0x35
982#define QUERY_DEV_LIM_MTU_WIDTH_OFFSET 0x36
983#define QUERY_DEV_LIM_VL_PORT_OFFSET 0x37
984#define QUERY_DEV_LIM_MAX_GID_OFFSET 0x3b
bf6a9e31 985#define QUERY_DEV_LIM_RATE_SUPPORT_OFFSET 0x3c
1da177e4
LT
986#define QUERY_DEV_LIM_MAX_PKEY_OFFSET 0x3f
987#define QUERY_DEV_LIM_FLAGS_OFFSET 0x44
988#define QUERY_DEV_LIM_RSVD_UAR_OFFSET 0x48
989#define QUERY_DEV_LIM_UAR_SZ_OFFSET 0x49
990#define QUERY_DEV_LIM_PAGE_SZ_OFFSET 0x4b
991#define QUERY_DEV_LIM_MAX_SG_OFFSET 0x51
992#define QUERY_DEV_LIM_MAX_DESC_SZ_OFFSET 0x52
993#define QUERY_DEV_LIM_MAX_SG_RQ_OFFSET 0x55
994#define QUERY_DEV_LIM_MAX_DESC_SZ_RQ_OFFSET 0x56
995#define QUERY_DEV_LIM_MAX_QP_MCG_OFFSET 0x61
996#define QUERY_DEV_LIM_RSVD_MCG_OFFSET 0x62
997#define QUERY_DEV_LIM_MAX_MCG_OFFSET 0x63
998#define QUERY_DEV_LIM_RSVD_PD_OFFSET 0x64
999#define QUERY_DEV_LIM_MAX_PD_OFFSET 0x65
1000#define QUERY_DEV_LIM_RSVD_RDD_OFFSET 0x66
1001#define QUERY_DEV_LIM_MAX_RDD_OFFSET 0x67
1002#define QUERY_DEV_LIM_EEC_ENTRY_SZ_OFFSET 0x80
1003#define QUERY_DEV_LIM_QPC_ENTRY_SZ_OFFSET 0x82
1004#define QUERY_DEV_LIM_EEEC_ENTRY_SZ_OFFSET 0x84
1005#define QUERY_DEV_LIM_EQPC_ENTRY_SZ_OFFSET 0x86
1006#define QUERY_DEV_LIM_EQC_ENTRY_SZ_OFFSET 0x88
1007#define QUERY_DEV_LIM_CQC_ENTRY_SZ_OFFSET 0x8a
1008#define QUERY_DEV_LIM_SRQ_ENTRY_SZ_OFFSET 0x8c
1009#define QUERY_DEV_LIM_UAR_ENTRY_SZ_OFFSET 0x8e
1010#define QUERY_DEV_LIM_MTT_ENTRY_SZ_OFFSET 0x90
1011#define QUERY_DEV_LIM_MPT_ENTRY_SZ_OFFSET 0x92
1012#define QUERY_DEV_LIM_PBL_SZ_OFFSET 0x96
1013#define QUERY_DEV_LIM_BMME_FLAGS_OFFSET 0x97
1014#define QUERY_DEV_LIM_RSVD_LKEY_OFFSET 0x98
1015#define QUERY_DEV_LIM_LAMR_OFFSET 0x9f
1016#define QUERY_DEV_LIM_MAX_ICM_SZ_OFFSET 0xa0
1017
ed878458
RD
1018 mailbox = mthca_alloc_mailbox(dev, GFP_KERNEL);
1019 if (IS_ERR(mailbox))
1020 return PTR_ERR(mailbox);
1021 outbox = mailbox->buf;
1da177e4 1022
ed878458 1023 err = mthca_cmd_box(dev, 0, mailbox->dma, 0, 0, CMD_QUERY_DEV_LIM,
1da177e4
LT
1024 CMD_TIME_CLASS_A, status);
1025
1026 if (err)
1027 goto out;
1028
1da177e4
LT
1029 MTHCA_GET(field, outbox, QUERY_DEV_LIM_RSVD_QP_OFFSET);
1030 dev_lim->reserved_qps = 1 << (field & 0xf);
1031 MTHCA_GET(field, outbox, QUERY_DEV_LIM_MAX_QP_OFFSET);
1032 dev_lim->max_qps = 1 << (field & 0x1f);
1033 MTHCA_GET(field, outbox, QUERY_DEV_LIM_RSVD_SRQ_OFFSET);
1034 dev_lim->reserved_srqs = 1 << (field >> 4);
1035 MTHCA_GET(field, outbox, QUERY_DEV_LIM_MAX_SRQ_OFFSET);
1036 dev_lim->max_srqs = 1 << (field & 0x1f);
1037 MTHCA_GET(field, outbox, QUERY_DEV_LIM_RSVD_EEC_OFFSET);
1038 dev_lim->reserved_eecs = 1 << (field & 0xf);
1039 MTHCA_GET(field, outbox, QUERY_DEV_LIM_MAX_EEC_OFFSET);
1040 dev_lim->max_eecs = 1 << (field & 0x1f);
1041 MTHCA_GET(field, outbox, QUERY_DEV_LIM_MAX_CQ_SZ_OFFSET);
1042 dev_lim->max_cq_sz = 1 << field;
1043 MTHCA_GET(field, outbox, QUERY_DEV_LIM_RSVD_CQ_OFFSET);
1044 dev_lim->reserved_cqs = 1 << (field & 0xf);
1045 MTHCA_GET(field, outbox, QUERY_DEV_LIM_MAX_CQ_OFFSET);
1046 dev_lim->max_cqs = 1 << (field & 0x1f);
1047 MTHCA_GET(field, outbox, QUERY_DEV_LIM_MAX_MPT_OFFSET);
1048 dev_lim->max_mpts = 1 << (field & 0x3f);
1049 MTHCA_GET(field, outbox, QUERY_DEV_LIM_RSVD_EQ_OFFSET);
1050 dev_lim->reserved_eqs = 1 << (field & 0xf);
1051 MTHCA_GET(field, outbox, QUERY_DEV_LIM_MAX_EQ_OFFSET);
1052 dev_lim->max_eqs = 1 << (field & 0x7);
1053 MTHCA_GET(field, outbox, QUERY_DEV_LIM_RSVD_MTT_OFFSET);
c7d204e8
MT
1054 if (mthca_is_memfree(dev))
1055 dev_lim->reserved_mtts = ALIGN((1 << (field >> 4)) * sizeof(u64),
1056 MTHCA_MTT_SEG_SIZE) / MTHCA_MTT_SEG_SIZE;
1057 else
1058 dev_lim->reserved_mtts = 1 << (field >> 4);
1da177e4
LT
1059 MTHCA_GET(field, outbox, QUERY_DEV_LIM_MAX_MRW_SZ_OFFSET);
1060 dev_lim->max_mrw_sz = 1 << field;
1061 MTHCA_GET(field, outbox, QUERY_DEV_LIM_RSVD_MRW_OFFSET);
1062 dev_lim->reserved_mrws = 1 << (field & 0xf);
1063 MTHCA_GET(field, outbox, QUERY_DEV_LIM_MAX_MTT_SEG_OFFSET);
1064 dev_lim->max_mtt_seg = 1 << (field & 0x3f);
1065 MTHCA_GET(field, outbox, QUERY_DEV_LIM_MAX_REQ_QP_OFFSET);
1066 dev_lim->max_requester_per_qp = 1 << (field & 0x3f);
1067 MTHCA_GET(field, outbox, QUERY_DEV_LIM_MAX_RES_QP_OFFSET);
1068 dev_lim->max_responder_per_qp = 1 << (field & 0x3f);
1069 MTHCA_GET(field, outbox, QUERY_DEV_LIM_MAX_RDMA_OFFSET);
1070 dev_lim->max_rdma_global = 1 << (field & 0x3f);
1071 MTHCA_GET(field, outbox, QUERY_DEV_LIM_ACK_DELAY_OFFSET);
1072 dev_lim->local_ca_ack_delay = field & 0x1f;
1073 MTHCA_GET(field, outbox, QUERY_DEV_LIM_MTU_WIDTH_OFFSET);
1074 dev_lim->max_mtu = field >> 4;
1075 dev_lim->max_port_width = field & 0xf;
1076 MTHCA_GET(field, outbox, QUERY_DEV_LIM_VL_PORT_OFFSET);
1077 dev_lim->max_vl = field >> 4;
1078 dev_lim->num_ports = field & 0xf;
1079 MTHCA_GET(field, outbox, QUERY_DEV_LIM_MAX_GID_OFFSET);
1080 dev_lim->max_gids = 1 << (field & 0xf);
bf6a9e31
JM
1081 MTHCA_GET(stat_rate, outbox, QUERY_DEV_LIM_RATE_SUPPORT_OFFSET);
1082 dev_lim->stat_rate_support = stat_rate;
1da177e4
LT
1083 MTHCA_GET(field, outbox, QUERY_DEV_LIM_MAX_PKEY_OFFSET);
1084 dev_lim->max_pkeys = 1 << (field & 0xf);
1085 MTHCA_GET(dev_lim->flags, outbox, QUERY_DEV_LIM_FLAGS_OFFSET);
1086 MTHCA_GET(field, outbox, QUERY_DEV_LIM_RSVD_UAR_OFFSET);
1087 dev_lim->reserved_uars = field >> 4;
1088 MTHCA_GET(field, outbox, QUERY_DEV_LIM_UAR_SZ_OFFSET);
1089 dev_lim->uar_size = 1 << ((field & 0x3f) + 20);
1090 MTHCA_GET(field, outbox, QUERY_DEV_LIM_PAGE_SZ_OFFSET);
1091 dev_lim->min_page_sz = 1 << field;
1092 MTHCA_GET(field, outbox, QUERY_DEV_LIM_MAX_SG_OFFSET);
1093 dev_lim->max_sg = field;
1094
1095 MTHCA_GET(size, outbox, QUERY_DEV_LIM_MAX_DESC_SZ_OFFSET);
1096 dev_lim->max_desc_sz = size;
1097
1098 MTHCA_GET(field, outbox, QUERY_DEV_LIM_MAX_QP_MCG_OFFSET);
1099 dev_lim->max_qp_per_mcg = 1 << field;
1100 MTHCA_GET(field, outbox, QUERY_DEV_LIM_RSVD_MCG_OFFSET);
1101 dev_lim->reserved_mgms = field & 0xf;
1102 MTHCA_GET(field, outbox, QUERY_DEV_LIM_MAX_MCG_OFFSET);
1103 dev_lim->max_mcgs = 1 << field;
1104 MTHCA_GET(field, outbox, QUERY_DEV_LIM_RSVD_PD_OFFSET);
1105 dev_lim->reserved_pds = field >> 4;
1106 MTHCA_GET(field, outbox, QUERY_DEV_LIM_MAX_PD_OFFSET);
1107 dev_lim->max_pds = 1 << (field & 0x3f);
1108 MTHCA_GET(field, outbox, QUERY_DEV_LIM_RSVD_RDD_OFFSET);
1109 dev_lim->reserved_rdds = field >> 4;
1110 MTHCA_GET(field, outbox, QUERY_DEV_LIM_MAX_RDD_OFFSET);
1111 dev_lim->max_rdds = 1 << (field & 0x3f);
1112
1113 MTHCA_GET(size, outbox, QUERY_DEV_LIM_EEC_ENTRY_SZ_OFFSET);
1114 dev_lim->eec_entry_sz = size;
1115 MTHCA_GET(size, outbox, QUERY_DEV_LIM_QPC_ENTRY_SZ_OFFSET);
1116 dev_lim->qpc_entry_sz = size;
1117 MTHCA_GET(size, outbox, QUERY_DEV_LIM_EEEC_ENTRY_SZ_OFFSET);
1118 dev_lim->eeec_entry_sz = size;
1119 MTHCA_GET(size, outbox, QUERY_DEV_LIM_EQPC_ENTRY_SZ_OFFSET);
1120 dev_lim->eqpc_entry_sz = size;
1121 MTHCA_GET(size, outbox, QUERY_DEV_LIM_EQC_ENTRY_SZ_OFFSET);
1122 dev_lim->eqc_entry_sz = size;
1123 MTHCA_GET(size, outbox, QUERY_DEV_LIM_CQC_ENTRY_SZ_OFFSET);
1124 dev_lim->cqc_entry_sz = size;
1125 MTHCA_GET(size, outbox, QUERY_DEV_LIM_SRQ_ENTRY_SZ_OFFSET);
1126 dev_lim->srq_entry_sz = size;
1127 MTHCA_GET(size, outbox, QUERY_DEV_LIM_UAR_ENTRY_SZ_OFFSET);
1128 dev_lim->uar_scratch_entry_sz = size;
1129
d10ddbf6 1130 if (mthca_is_memfree(dev)) {
a3c8ab4f
JM
1131 MTHCA_GET(field, outbox, QUERY_DEV_LIM_MAX_SRQ_SZ_OFFSET);
1132 dev_lim->max_srq_sz = 1 << field;
1133 MTHCA_GET(field, outbox, QUERY_DEV_LIM_MAX_QP_SZ_OFFSET);
1134 dev_lim->max_qp_sz = 1 << field;
1da177e4
LT
1135 MTHCA_GET(field, outbox, QUERY_DEV_LIM_RSZ_SRQ_OFFSET);
1136 dev_lim->hca.arbel.resize_srq = field & 1;
8cf2daf3
RD
1137 MTHCA_GET(field, outbox, QUERY_DEV_LIM_MAX_SG_RQ_OFFSET);
1138 dev_lim->max_sg = min_t(int, field, dev_lim->max_sg);
77369ed3
JM
1139 MTHCA_GET(size, outbox, QUERY_DEV_LIM_MAX_DESC_SZ_RQ_OFFSET);
1140 dev_lim->max_desc_sz = min_t(int, size, dev_lim->max_desc_sz);
1da177e4
LT
1141 MTHCA_GET(size, outbox, QUERY_DEV_LIM_MPT_ENTRY_SZ_OFFSET);
1142 dev_lim->mpt_entry_sz = size;
1143 MTHCA_GET(field, outbox, QUERY_DEV_LIM_PBL_SZ_OFFSET);
1144 dev_lim->hca.arbel.max_pbl_sz = 1 << (field & 0x3f);
1145 MTHCA_GET(dev_lim->hca.arbel.bmme_flags, outbox,
1146 QUERY_DEV_LIM_BMME_FLAGS_OFFSET);
1147 MTHCA_GET(dev_lim->hca.arbel.reserved_lkey, outbox,
1148 QUERY_DEV_LIM_RSVD_LKEY_OFFSET);
1149 MTHCA_GET(field, outbox, QUERY_DEV_LIM_LAMR_OFFSET);
1150 dev_lim->hca.arbel.lam_required = field & 1;
1151 MTHCA_GET(dev_lim->hca.arbel.max_icm_sz, outbox,
1152 QUERY_DEV_LIM_MAX_ICM_SZ_OFFSET);
1153
1154 if (dev_lim->hca.arbel.bmme_flags & 1)
1155 mthca_dbg(dev, "Base MM extensions: yes "
1156 "(flags %d, max PBL %d, rsvd L_Key %08x)\n",
1157 dev_lim->hca.arbel.bmme_flags,
1158 dev_lim->hca.arbel.max_pbl_sz,
1159 dev_lim->hca.arbel.reserved_lkey);
1160 else
1161 mthca_dbg(dev, "Base MM extensions: no\n");
1162
1163 mthca_dbg(dev, "Max ICM size %lld MB\n",
1164 (unsigned long long) dev_lim->hca.arbel.max_icm_sz >> 20);
1165 } else {
a3c8ab4f
JM
1166 MTHCA_GET(field, outbox, QUERY_DEV_LIM_MAX_SRQ_SZ_OFFSET);
1167 dev_lim->max_srq_sz = (1 << field) - 1;
1168 MTHCA_GET(field, outbox, QUERY_DEV_LIM_MAX_QP_SZ_OFFSET);
1169 dev_lim->max_qp_sz = (1 << field) - 1;
1da177e4
LT
1170 MTHCA_GET(field, outbox, QUERY_DEV_LIM_MAX_AV_OFFSET);
1171 dev_lim->hca.tavor.max_avs = 1 << (field & 0x3f);
1da177e4
LT
1172 dev_lim->mpt_entry_sz = MTHCA_MPT_ENTRY_SIZE;
1173 }
1174
f295c79b
RD
1175 mthca_dbg(dev, "Max QPs: %d, reserved QPs: %d, entry size: %d\n",
1176 dev_lim->max_qps, dev_lim->reserved_qps, dev_lim->qpc_entry_sz);
1177 mthca_dbg(dev, "Max SRQs: %d, reserved SRQs: %d, entry size: %d\n",
1178 dev_lim->max_srqs, dev_lim->reserved_srqs, dev_lim->srq_entry_sz);
1179 mthca_dbg(dev, "Max CQs: %d, reserved CQs: %d, entry size: %d\n",
1180 dev_lim->max_cqs, dev_lim->reserved_cqs, dev_lim->cqc_entry_sz);
1181 mthca_dbg(dev, "Max EQs: %d, reserved EQs: %d, entry size: %d\n",
1182 dev_lim->max_eqs, dev_lim->reserved_eqs, dev_lim->eqc_entry_sz);
1183 mthca_dbg(dev, "reserved MPTs: %d, reserved MTTs: %d\n",
1184 dev_lim->reserved_mrws, dev_lim->reserved_mtts);
1185 mthca_dbg(dev, "Max PDs: %d, reserved PDs: %d, reserved UARs: %d\n",
1186 dev_lim->max_pds, dev_lim->reserved_pds, dev_lim->reserved_uars);
1187 mthca_dbg(dev, "Max QP/MCG: %d, reserved MGMs: %d\n",
1188 dev_lim->max_pds, dev_lim->reserved_mgms);
1189 mthca_dbg(dev, "Max CQEs: %d, max WQEs: %d, max SRQ WQEs: %d\n",
1190 dev_lim->max_cq_sz, dev_lim->max_qp_sz, dev_lim->max_srq_sz);
1191
1192 mthca_dbg(dev, "Flags: %08x\n", dev_lim->flags);
1193
1da177e4 1194out:
ed878458 1195 mthca_free_mailbox(dev, mailbox);
1da177e4
LT
1196 return err;
1197}
1198
2e8b981c
MT
1199static void get_board_id(void *vsd, char *board_id)
1200{
1201 int i;
1202
1203#define VSD_OFFSET_SIG1 0x00
1204#define VSD_OFFSET_SIG2 0xde
1205#define VSD_OFFSET_MLX_BOARD_ID 0xd0
1206#define VSD_OFFSET_TS_BOARD_ID 0x20
1207
1208#define VSD_SIGNATURE_TOPSPIN 0x5ad
1209
1210 memset(board_id, 0, MTHCA_BOARD_ID_LEN);
1211
1212 if (be16_to_cpup(vsd + VSD_OFFSET_SIG1) == VSD_SIGNATURE_TOPSPIN &&
1213 be16_to_cpup(vsd + VSD_OFFSET_SIG2) == VSD_SIGNATURE_TOPSPIN) {
1214 strlcpy(board_id, vsd + VSD_OFFSET_TS_BOARD_ID, MTHCA_BOARD_ID_LEN);
1215 } else {
1216 /*
1217 * The board ID is a string but the firmware byte
1218 * swaps each 4-byte word before passing it back to
1219 * us. Therefore we need to swab it before printing.
1220 */
1221 for (i = 0; i < 4; ++i)
1222 ((u32 *) board_id)[i] =
1223 swab32(*(u32 *) (vsd + VSD_OFFSET_MLX_BOARD_ID + i * 4));
1224 }
1225}
1226
1da177e4
LT
1227int mthca_QUERY_ADAPTER(struct mthca_dev *dev,
1228 struct mthca_adapter *adapter, u8 *status)
1229{
ed878458 1230 struct mthca_mailbox *mailbox;
1da177e4 1231 u32 *outbox;
1da177e4
LT
1232 int err;
1233
1234#define QUERY_ADAPTER_OUT_SIZE 0x100
1235#define QUERY_ADAPTER_VENDOR_ID_OFFSET 0x00
1236#define QUERY_ADAPTER_DEVICE_ID_OFFSET 0x04
1237#define QUERY_ADAPTER_REVISION_ID_OFFSET 0x08
1238#define QUERY_ADAPTER_INTA_PIN_OFFSET 0x10
2e8b981c 1239#define QUERY_ADAPTER_VSD_OFFSET 0x20
1da177e4 1240
ed878458
RD
1241 mailbox = mthca_alloc_mailbox(dev, GFP_KERNEL);
1242 if (IS_ERR(mailbox))
1243 return PTR_ERR(mailbox);
1244 outbox = mailbox->buf;
1da177e4 1245
ed878458 1246 err = mthca_cmd_box(dev, 0, mailbox->dma, 0, 0, CMD_QUERY_ADAPTER,
1da177e4
LT
1247 CMD_TIME_CLASS_A, status);
1248
1249 if (err)
1250 goto out;
1251
ed878458
RD
1252 MTHCA_GET(adapter->vendor_id, outbox, QUERY_ADAPTER_VENDOR_ID_OFFSET);
1253 MTHCA_GET(adapter->device_id, outbox, QUERY_ADAPTER_DEVICE_ID_OFFSET);
1da177e4 1254 MTHCA_GET(adapter->revision_id, outbox, QUERY_ADAPTER_REVISION_ID_OFFSET);
ed878458 1255 MTHCA_GET(adapter->inta_pin, outbox, QUERY_ADAPTER_INTA_PIN_OFFSET);
1da177e4 1256
2e8b981c
MT
1257 get_board_id(outbox + QUERY_ADAPTER_VSD_OFFSET / 4,
1258 adapter->board_id);
1259
1da177e4 1260out:
ed878458 1261 mthca_free_mailbox(dev, mailbox);
1da177e4
LT
1262 return err;
1263}
1264
1265int mthca_INIT_HCA(struct mthca_dev *dev,
1266 struct mthca_init_hca_param *param,
1267 u8 *status)
1268{
ed878458 1269 struct mthca_mailbox *mailbox;
97f52eb4 1270 __be32 *inbox;
1da177e4
LT
1271 int err;
1272
1273#define INIT_HCA_IN_SIZE 0x200
651eaac9
EC
1274#define INIT_HCA_FLAGS1_OFFSET 0x00c
1275#define INIT_HCA_FLAGS2_OFFSET 0x014
1da177e4
LT
1276#define INIT_HCA_QPC_OFFSET 0x020
1277#define INIT_HCA_QPC_BASE_OFFSET (INIT_HCA_QPC_OFFSET + 0x10)
1278#define INIT_HCA_LOG_QP_OFFSET (INIT_HCA_QPC_OFFSET + 0x17)
1279#define INIT_HCA_EEC_BASE_OFFSET (INIT_HCA_QPC_OFFSET + 0x20)
1280#define INIT_HCA_LOG_EEC_OFFSET (INIT_HCA_QPC_OFFSET + 0x27)
1281#define INIT_HCA_SRQC_BASE_OFFSET (INIT_HCA_QPC_OFFSET + 0x28)
1282#define INIT_HCA_LOG_SRQ_OFFSET (INIT_HCA_QPC_OFFSET + 0x2f)
1283#define INIT_HCA_CQC_BASE_OFFSET (INIT_HCA_QPC_OFFSET + 0x30)
1284#define INIT_HCA_LOG_CQ_OFFSET (INIT_HCA_QPC_OFFSET + 0x37)
1285#define INIT_HCA_EQPC_BASE_OFFSET (INIT_HCA_QPC_OFFSET + 0x40)
1286#define INIT_HCA_EEEC_BASE_OFFSET (INIT_HCA_QPC_OFFSET + 0x50)
1287#define INIT_HCA_EQC_BASE_OFFSET (INIT_HCA_QPC_OFFSET + 0x60)
1288#define INIT_HCA_LOG_EQ_OFFSET (INIT_HCA_QPC_OFFSET + 0x67)
1289#define INIT_HCA_RDB_BASE_OFFSET (INIT_HCA_QPC_OFFSET + 0x70)
1290#define INIT_HCA_UDAV_OFFSET 0x0b0
1291#define INIT_HCA_UDAV_LKEY_OFFSET (INIT_HCA_UDAV_OFFSET + 0x0)
1292#define INIT_HCA_UDAV_PD_OFFSET (INIT_HCA_UDAV_OFFSET + 0x4)
1293#define INIT_HCA_MCAST_OFFSET 0x0c0
1294#define INIT_HCA_MC_BASE_OFFSET (INIT_HCA_MCAST_OFFSET + 0x00)
1295#define INIT_HCA_LOG_MC_ENTRY_SZ_OFFSET (INIT_HCA_MCAST_OFFSET + 0x12)
1296#define INIT_HCA_MC_HASH_SZ_OFFSET (INIT_HCA_MCAST_OFFSET + 0x16)
1297#define INIT_HCA_LOG_MC_TABLE_SZ_OFFSET (INIT_HCA_MCAST_OFFSET + 0x1b)
1298#define INIT_HCA_TPT_OFFSET 0x0f0
1299#define INIT_HCA_MPT_BASE_OFFSET (INIT_HCA_TPT_OFFSET + 0x00)
1300#define INIT_HCA_MTT_SEG_SZ_OFFSET (INIT_HCA_TPT_OFFSET + 0x09)
1301#define INIT_HCA_LOG_MPT_SZ_OFFSET (INIT_HCA_TPT_OFFSET + 0x0b)
1302#define INIT_HCA_MTT_BASE_OFFSET (INIT_HCA_TPT_OFFSET + 0x10)
1303#define INIT_HCA_UAR_OFFSET 0x120
1304#define INIT_HCA_UAR_BASE_OFFSET (INIT_HCA_UAR_OFFSET + 0x00)
1305#define INIT_HCA_UARC_SZ_OFFSET (INIT_HCA_UAR_OFFSET + 0x09)
1306#define INIT_HCA_LOG_UAR_SZ_OFFSET (INIT_HCA_UAR_OFFSET + 0x0a)
1307#define INIT_HCA_UAR_PAGE_SZ_OFFSET (INIT_HCA_UAR_OFFSET + 0x0b)
1308#define INIT_HCA_UAR_SCATCH_BASE_OFFSET (INIT_HCA_UAR_OFFSET + 0x10)
1309#define INIT_HCA_UAR_CTX_BASE_OFFSET (INIT_HCA_UAR_OFFSET + 0x18)
1310
ed878458
RD
1311 mailbox = mthca_alloc_mailbox(dev, GFP_KERNEL);
1312 if (IS_ERR(mailbox))
1313 return PTR_ERR(mailbox);
1314 inbox = mailbox->buf;
1da177e4
LT
1315
1316 memset(inbox, 0, INIT_HCA_IN_SIZE);
1317
651eaac9
EC
1318 if (dev->mthca_flags & MTHCA_FLAG_SINAI_OPT)
1319 MTHCA_PUT(inbox, 0x1, INIT_HCA_FLAGS1_OFFSET);
1320
1da177e4 1321#if defined(__LITTLE_ENDIAN)
651eaac9 1322 *(inbox + INIT_HCA_FLAGS2_OFFSET / 4) &= ~cpu_to_be32(1 << 1);
1da177e4 1323#elif defined(__BIG_ENDIAN)
651eaac9 1324 *(inbox + INIT_HCA_FLAGS2_OFFSET / 4) |= cpu_to_be32(1 << 1);
1da177e4
LT
1325#else
1326#error Host endianness not defined
1327#endif
1328 /* Check port for UD address vector: */
651eaac9 1329 *(inbox + INIT_HCA_FLAGS2_OFFSET / 4) |= cpu_to_be32(1);
1da177e4
LT
1330
1331 /* We leave wqe_quota, responder_exu, etc as 0 (default) */
1332
1333 /* QPC/EEC/CQC/EQC/RDB attributes */
1334
1335 MTHCA_PUT(inbox, param->qpc_base, INIT_HCA_QPC_BASE_OFFSET);
1336 MTHCA_PUT(inbox, param->log_num_qps, INIT_HCA_LOG_QP_OFFSET);
1337 MTHCA_PUT(inbox, param->eec_base, INIT_HCA_EEC_BASE_OFFSET);
1338 MTHCA_PUT(inbox, param->log_num_eecs, INIT_HCA_LOG_EEC_OFFSET);
1339 MTHCA_PUT(inbox, param->srqc_base, INIT_HCA_SRQC_BASE_OFFSET);
1340 MTHCA_PUT(inbox, param->log_num_srqs, INIT_HCA_LOG_SRQ_OFFSET);
1341 MTHCA_PUT(inbox, param->cqc_base, INIT_HCA_CQC_BASE_OFFSET);
1342 MTHCA_PUT(inbox, param->log_num_cqs, INIT_HCA_LOG_CQ_OFFSET);
1343 MTHCA_PUT(inbox, param->eqpc_base, INIT_HCA_EQPC_BASE_OFFSET);
1344 MTHCA_PUT(inbox, param->eeec_base, INIT_HCA_EEEC_BASE_OFFSET);
1345 MTHCA_PUT(inbox, param->eqc_base, INIT_HCA_EQC_BASE_OFFSET);
1346 MTHCA_PUT(inbox, param->log_num_eqs, INIT_HCA_LOG_EQ_OFFSET);
1347 MTHCA_PUT(inbox, param->rdb_base, INIT_HCA_RDB_BASE_OFFSET);
1348
1349 /* UD AV attributes */
1350
1351 /* multicast attributes */
1352
1353 MTHCA_PUT(inbox, param->mc_base, INIT_HCA_MC_BASE_OFFSET);
1354 MTHCA_PUT(inbox, param->log_mc_entry_sz, INIT_HCA_LOG_MC_ENTRY_SZ_OFFSET);
1355 MTHCA_PUT(inbox, param->mc_hash_sz, INIT_HCA_MC_HASH_SZ_OFFSET);
1356 MTHCA_PUT(inbox, param->log_mc_table_sz, INIT_HCA_LOG_MC_TABLE_SZ_OFFSET);
1357
1358 /* TPT attributes */
1359
1360 MTHCA_PUT(inbox, param->mpt_base, INIT_HCA_MPT_BASE_OFFSET);
d10ddbf6 1361 if (!mthca_is_memfree(dev))
1da177e4
LT
1362 MTHCA_PUT(inbox, param->mtt_seg_sz, INIT_HCA_MTT_SEG_SZ_OFFSET);
1363 MTHCA_PUT(inbox, param->log_mpt_sz, INIT_HCA_LOG_MPT_SZ_OFFSET);
1364 MTHCA_PUT(inbox, param->mtt_base, INIT_HCA_MTT_BASE_OFFSET);
1365
1366 /* UAR attributes */
1367 {
1368 u8 uar_page_sz = PAGE_SHIFT - 12;
1369 MTHCA_PUT(inbox, uar_page_sz, INIT_HCA_UAR_PAGE_SZ_OFFSET);
1370 }
1371
1372 MTHCA_PUT(inbox, param->uar_scratch_base, INIT_HCA_UAR_SCATCH_BASE_OFFSET);
1373
d10ddbf6 1374 if (mthca_is_memfree(dev)) {
1da177e4
LT
1375 MTHCA_PUT(inbox, param->log_uarc_sz, INIT_HCA_UARC_SZ_OFFSET);
1376 MTHCA_PUT(inbox, param->log_uar_sz, INIT_HCA_LOG_UAR_SZ_OFFSET);
1377 MTHCA_PUT(inbox, param->uarc_base, INIT_HCA_UAR_CTX_BASE_OFFSET);
1378 }
1379
ed878458 1380 err = mthca_cmd(dev, mailbox->dma, 0, 0, CMD_INIT_HCA, HZ, status);
1da177e4 1381
ed878458 1382 mthca_free_mailbox(dev, mailbox);
1da177e4
LT
1383 return err;
1384}
1385
1386int mthca_INIT_IB(struct mthca_dev *dev,
1387 struct mthca_init_ib_param *param,
1388 int port, u8 *status)
1389{
ed878458 1390 struct mthca_mailbox *mailbox;
1da177e4 1391 u32 *inbox;
1da177e4
LT
1392 int err;
1393 u32 flags;
1394
1395#define INIT_IB_IN_SIZE 56
1396#define INIT_IB_FLAGS_OFFSET 0x00
1397#define INIT_IB_FLAG_SIG (1 << 18)
1398#define INIT_IB_FLAG_NG (1 << 17)
1399#define INIT_IB_FLAG_G0 (1 << 16)
1da177e4 1400#define INIT_IB_VL_SHIFT 4
da6561c2 1401#define INIT_IB_PORT_WIDTH_SHIFT 8
1da177e4
LT
1402#define INIT_IB_MTU_SHIFT 12
1403#define INIT_IB_MAX_GID_OFFSET 0x06
1404#define INIT_IB_MAX_PKEY_OFFSET 0x0a
1405#define INIT_IB_GUID0_OFFSET 0x10
1406#define INIT_IB_NODE_GUID_OFFSET 0x18
1407#define INIT_IB_SI_GUID_OFFSET 0x20
1408
ed878458
RD
1409 mailbox = mthca_alloc_mailbox(dev, GFP_KERNEL);
1410 if (IS_ERR(mailbox))
1411 return PTR_ERR(mailbox);
1412 inbox = mailbox->buf;
1da177e4
LT
1413
1414 memset(inbox, 0, INIT_IB_IN_SIZE);
1415
1416 flags = 0;
1da177e4
LT
1417 flags |= param->set_guid0 ? INIT_IB_FLAG_G0 : 0;
1418 flags |= param->set_node_guid ? INIT_IB_FLAG_NG : 0;
1419 flags |= param->set_si_guid ? INIT_IB_FLAG_SIG : 0;
1420 flags |= param->vl_cap << INIT_IB_VL_SHIFT;
da6561c2 1421 flags |= param->port_width << INIT_IB_PORT_WIDTH_SHIFT;
1da177e4
LT
1422 flags |= param->mtu_cap << INIT_IB_MTU_SHIFT;
1423 MTHCA_PUT(inbox, flags, INIT_IB_FLAGS_OFFSET);
1424
1425 MTHCA_PUT(inbox, param->gid_cap, INIT_IB_MAX_GID_OFFSET);
1426 MTHCA_PUT(inbox, param->pkey_cap, INIT_IB_MAX_PKEY_OFFSET);
1427 MTHCA_PUT(inbox, param->guid0, INIT_IB_GUID0_OFFSET);
1428 MTHCA_PUT(inbox, param->node_guid, INIT_IB_NODE_GUID_OFFSET);
1429 MTHCA_PUT(inbox, param->si_guid, INIT_IB_SI_GUID_OFFSET);
1430
ed878458 1431 err = mthca_cmd(dev, mailbox->dma, port, 0, CMD_INIT_IB,
1da177e4
LT
1432 CMD_TIME_CLASS_A, status);
1433
ed878458 1434 mthca_free_mailbox(dev, mailbox);
1da177e4
LT
1435 return err;
1436}
1437
1438int mthca_CLOSE_IB(struct mthca_dev *dev, int port, u8 *status)
1439{
1440 return mthca_cmd(dev, 0, port, 0, CMD_CLOSE_IB, HZ, status);
1441}
1442
1443int mthca_CLOSE_HCA(struct mthca_dev *dev, int panic, u8 *status)
1444{
1445 return mthca_cmd(dev, 0, 0, panic, CMD_CLOSE_HCA, HZ, status);
1446}
1447
1448int mthca_SET_IB(struct mthca_dev *dev, struct mthca_set_ib_param *param,
1449 int port, u8 *status)
1450{
ed878458 1451 struct mthca_mailbox *mailbox;
1da177e4 1452 u32 *inbox;
1da177e4
LT
1453 int err;
1454 u32 flags = 0;
1455
1456#define SET_IB_IN_SIZE 0x40
1457#define SET_IB_FLAGS_OFFSET 0x00
1458#define SET_IB_FLAG_SIG (1 << 18)
1459#define SET_IB_FLAG_RQK (1 << 0)
1460#define SET_IB_CAP_MASK_OFFSET 0x04
1461#define SET_IB_SI_GUID_OFFSET 0x08
1462
ed878458
RD
1463 mailbox = mthca_alloc_mailbox(dev, GFP_KERNEL);
1464 if (IS_ERR(mailbox))
1465 return PTR_ERR(mailbox);
1466 inbox = mailbox->buf;
1da177e4
LT
1467
1468 memset(inbox, 0, SET_IB_IN_SIZE);
1469
1470 flags |= param->set_si_guid ? SET_IB_FLAG_SIG : 0;
1471 flags |= param->reset_qkey_viol ? SET_IB_FLAG_RQK : 0;
1472 MTHCA_PUT(inbox, flags, SET_IB_FLAGS_OFFSET);
1473
1474 MTHCA_PUT(inbox, param->cap_mask, SET_IB_CAP_MASK_OFFSET);
1475 MTHCA_PUT(inbox, param->si_guid, SET_IB_SI_GUID_OFFSET);
1476
ed878458 1477 err = mthca_cmd(dev, mailbox->dma, port, 0, CMD_SET_IB,
1da177e4
LT
1478 CMD_TIME_CLASS_B, status);
1479
ed878458 1480 mthca_free_mailbox(dev, mailbox);
1da177e4
LT
1481 return err;
1482}
1483
1484int mthca_MAP_ICM(struct mthca_dev *dev, struct mthca_icm *icm, u64 virt, u8 *status)
1485{
1486 return mthca_map_cmd(dev, CMD_MAP_ICM, icm, virt, status);
1487}
1488
1489int mthca_MAP_ICM_page(struct mthca_dev *dev, u64 dma_addr, u64 virt, u8 *status)
1490{
ed878458 1491 struct mthca_mailbox *mailbox;
97f52eb4 1492 __be64 *inbox;
1da177e4
LT
1493 int err;
1494
ed878458
RD
1495 mailbox = mthca_alloc_mailbox(dev, GFP_KERNEL);
1496 if (IS_ERR(mailbox))
1497 return PTR_ERR(mailbox);
1498 inbox = mailbox->buf;
1da177e4
LT
1499
1500 inbox[0] = cpu_to_be64(virt);
1501 inbox[1] = cpu_to_be64(dma_addr);
1502
ed878458
RD
1503 err = mthca_cmd(dev, mailbox->dma, 1, 0, CMD_MAP_ICM,
1504 CMD_TIME_CLASS_B, status);
1da177e4 1505
ed878458 1506 mthca_free_mailbox(dev, mailbox);
1da177e4
LT
1507
1508 if (!err)
6bd6228e
RD
1509 mthca_dbg(dev, "Mapped page at %llx to %llx for ICM.\n",
1510 (unsigned long long) dma_addr, (unsigned long long) virt);
1da177e4
LT
1511
1512 return err;
1513}
1514
1515int mthca_UNMAP_ICM(struct mthca_dev *dev, u64 virt, u32 page_count, u8 *status)
1516{
1517 mthca_dbg(dev, "Unmapping %d pages at %llx from ICM.\n",
1518 page_count, (unsigned long long) virt);
1519
1520 return mthca_cmd(dev, virt, page_count, 0, CMD_UNMAP_ICM, CMD_TIME_CLASS_B, status);
1521}
1522
1523int mthca_MAP_ICM_AUX(struct mthca_dev *dev, struct mthca_icm *icm, u8 *status)
1524{
1525 return mthca_map_cmd(dev, CMD_MAP_ICM_AUX, icm, -1, status);
1526}
1527
1528int mthca_UNMAP_ICM_AUX(struct mthca_dev *dev, u8 *status)
1529{
1530 return mthca_cmd(dev, 0, 0, 0, CMD_UNMAP_ICM_AUX, CMD_TIME_CLASS_B, status);
1531}
1532
1533int mthca_SET_ICM_SIZE(struct mthca_dev *dev, u64 icm_size, u64 *aux_pages,
1534 u8 *status)
1535{
1536 int ret = mthca_cmd_imm(dev, icm_size, aux_pages, 0, 0, CMD_SET_ICM_SIZE,
1537 CMD_TIME_CLASS_A, status);
1538
1539 if (ret || status)
1540 return ret;
1541
1542 /*
8d3ef29d
IR
1543 * Round up number of system pages needed in case
1544 * MTHCA_ICM_PAGE_SIZE < PAGE_SIZE.
1da177e4 1545 */
8d3ef29d
IR
1546 *aux_pages = ALIGN(*aux_pages, PAGE_SIZE / MTHCA_ICM_PAGE_SIZE) >>
1547 (PAGE_SHIFT - MTHCA_ICM_PAGE_SHIFT);
1da177e4
LT
1548
1549 return 0;
1550}
1551
ed878458 1552int mthca_SW2HW_MPT(struct mthca_dev *dev, struct mthca_mailbox *mailbox,
1da177e4
LT
1553 int mpt_index, u8 *status)
1554{
ed878458
RD
1555 return mthca_cmd(dev, mailbox->dma, mpt_index, 0, CMD_SW2HW_MPT,
1556 CMD_TIME_CLASS_B, status);
1da177e4
LT
1557}
1558
ed878458 1559int mthca_HW2SW_MPT(struct mthca_dev *dev, struct mthca_mailbox *mailbox,
1da177e4
LT
1560 int mpt_index, u8 *status)
1561{
ed878458
RD
1562 return mthca_cmd_box(dev, 0, mailbox ? mailbox->dma : 0, mpt_index,
1563 !mailbox, CMD_HW2SW_MPT,
1564 CMD_TIME_CLASS_B, status);
1da177e4
LT
1565}
1566
ed878458 1567int mthca_WRITE_MTT(struct mthca_dev *dev, struct mthca_mailbox *mailbox,
1da177e4
LT
1568 int num_mtt, u8 *status)
1569{
ed878458
RD
1570 return mthca_cmd(dev, mailbox->dma, num_mtt, 0, CMD_WRITE_MTT,
1571 CMD_TIME_CLASS_B, status);
1da177e4
LT
1572}
1573
b8ca06f6
MT
1574int mthca_SYNC_TPT(struct mthca_dev *dev, u8 *status)
1575{
1576 return mthca_cmd(dev, 0, 0, 0, CMD_SYNC_TPT, CMD_TIME_CLASS_B, status);
1577}
1578
1da177e4
LT
1579int mthca_MAP_EQ(struct mthca_dev *dev, u64 event_mask, int unmap,
1580 int eq_num, u8 *status)
1581{
1582 mthca_dbg(dev, "%s mask %016llx for eqn %d\n",
1583 unmap ? "Clearing" : "Setting",
1584 (unsigned long long) event_mask, eq_num);
1585 return mthca_cmd(dev, event_mask, (unmap << 31) | eq_num,
1586 0, CMD_MAP_EQ, CMD_TIME_CLASS_B, status);
1587}
1588
ed878458 1589int mthca_SW2HW_EQ(struct mthca_dev *dev, struct mthca_mailbox *mailbox,
1da177e4
LT
1590 int eq_num, u8 *status)
1591{
ed878458
RD
1592 return mthca_cmd(dev, mailbox->dma, eq_num, 0, CMD_SW2HW_EQ,
1593 CMD_TIME_CLASS_A, status);
1da177e4
LT
1594}
1595
ed878458 1596int mthca_HW2SW_EQ(struct mthca_dev *dev, struct mthca_mailbox *mailbox,
1da177e4
LT
1597 int eq_num, u8 *status)
1598{
ed878458
RD
1599 return mthca_cmd_box(dev, 0, mailbox->dma, eq_num, 0,
1600 CMD_HW2SW_EQ,
1601 CMD_TIME_CLASS_A, status);
1da177e4
LT
1602}
1603
ed878458 1604int mthca_SW2HW_CQ(struct mthca_dev *dev, struct mthca_mailbox *mailbox,
1da177e4
LT
1605 int cq_num, u8 *status)
1606{
ed878458 1607 return mthca_cmd(dev, mailbox->dma, cq_num, 0, CMD_SW2HW_CQ,
1da177e4 1608 CMD_TIME_CLASS_A, status);
1da177e4
LT
1609}
1610
ed878458 1611int mthca_HW2SW_CQ(struct mthca_dev *dev, struct mthca_mailbox *mailbox,
1da177e4
LT
1612 int cq_num, u8 *status)
1613{
ed878458
RD
1614 return mthca_cmd_box(dev, 0, mailbox->dma, cq_num, 0,
1615 CMD_HW2SW_CQ,
1616 CMD_TIME_CLASS_A, status);
1da177e4
LT
1617}
1618
4885bf64
RD
1619int mthca_RESIZE_CQ(struct mthca_dev *dev, int cq_num, u32 lkey, u8 log_size,
1620 u8 *status)
1621{
1622 struct mthca_mailbox *mailbox;
1623 __be32 *inbox;
1624 int err;
1625
1626#define RESIZE_CQ_IN_SIZE 0x40
1627#define RESIZE_CQ_LOG_SIZE_OFFSET 0x0c
1628#define RESIZE_CQ_LKEY_OFFSET 0x1c
1629
1630 mailbox = mthca_alloc_mailbox(dev, GFP_KERNEL);
1631 if (IS_ERR(mailbox))
1632 return PTR_ERR(mailbox);
1633 inbox = mailbox->buf;
1634
1635 memset(inbox, 0, RESIZE_CQ_IN_SIZE);
1636 /*
1637 * Leave start address fields zeroed out -- mthca assumes that
1638 * MRs for CQs always start at virtual address 0.
1639 */
1640 MTHCA_PUT(inbox, log_size, RESIZE_CQ_LOG_SIZE_OFFSET);
1641 MTHCA_PUT(inbox, lkey, RESIZE_CQ_LKEY_OFFSET);
1642
1643 err = mthca_cmd(dev, mailbox->dma, cq_num, 1, CMD_RESIZE_CQ,
1644 CMD_TIME_CLASS_B, status);
1645
1646 mthca_free_mailbox(dev, mailbox);
1647 return err;
1648}
1649
ec34a922
RD
1650int mthca_SW2HW_SRQ(struct mthca_dev *dev, struct mthca_mailbox *mailbox,
1651 int srq_num, u8 *status)
1652{
1653 return mthca_cmd(dev, mailbox->dma, srq_num, 0, CMD_SW2HW_SRQ,
1654 CMD_TIME_CLASS_A, status);
1655}
1656
1657int mthca_HW2SW_SRQ(struct mthca_dev *dev, struct mthca_mailbox *mailbox,
1658 int srq_num, u8 *status)
1659{
1660 return mthca_cmd_box(dev, 0, mailbox->dma, srq_num, 0,
1661 CMD_HW2SW_SRQ,
1662 CMD_TIME_CLASS_A, status);
1663}
1664
8ebe5077
EC
1665int mthca_QUERY_SRQ(struct mthca_dev *dev, u32 num,
1666 struct mthca_mailbox *mailbox, u8 *status)
1667{
1668 return mthca_cmd_box(dev, 0, mailbox->dma, num, 0,
1669 CMD_QUERY_SRQ, CMD_TIME_CLASS_A, status);
1670}
1671
ec34a922
RD
1672int mthca_ARM_SRQ(struct mthca_dev *dev, int srq_num, int limit, u8 *status)
1673{
1674 return mthca_cmd(dev, limit, srq_num, 0, CMD_ARM_SRQ,
1675 CMD_TIME_CLASS_B, status);
1676}
1677
d844183d
RD
1678int mthca_MODIFY_QP(struct mthca_dev *dev, enum ib_qp_state cur,
1679 enum ib_qp_state next, u32 num, int is_ee,
1680 struct mthca_mailbox *mailbox, u32 optmask,
1da177e4
LT
1681 u8 *status)
1682{
d844183d
RD
1683 static const u16 op[IB_QPS_ERR + 1][IB_QPS_ERR + 1] = {
1684 [IB_QPS_RESET] = {
1685 [IB_QPS_RESET] = CMD_ERR2RST_QPEE,
1686 [IB_QPS_ERR] = CMD_2ERR_QPEE,
1687 [IB_QPS_INIT] = CMD_RST2INIT_QPEE,
1688 },
1689 [IB_QPS_INIT] = {
1690 [IB_QPS_RESET] = CMD_ERR2RST_QPEE,
1691 [IB_QPS_ERR] = CMD_2ERR_QPEE,
1692 [IB_QPS_INIT] = CMD_INIT2INIT_QPEE,
1693 [IB_QPS_RTR] = CMD_INIT2RTR_QPEE,
1694 },
1695 [IB_QPS_RTR] = {
1696 [IB_QPS_RESET] = CMD_ERR2RST_QPEE,
1697 [IB_QPS_ERR] = CMD_2ERR_QPEE,
1698 [IB_QPS_RTS] = CMD_RTR2RTS_QPEE,
1699 },
1700 [IB_QPS_RTS] = {
1701 [IB_QPS_RESET] = CMD_ERR2RST_QPEE,
1702 [IB_QPS_ERR] = CMD_2ERR_QPEE,
1703 [IB_QPS_RTS] = CMD_RTS2RTS_QPEE,
1704 [IB_QPS_SQD] = CMD_RTS2SQD_QPEE,
1705 },
1706 [IB_QPS_SQD] = {
1707 [IB_QPS_RESET] = CMD_ERR2RST_QPEE,
1708 [IB_QPS_ERR] = CMD_2ERR_QPEE,
1709 [IB_QPS_RTS] = CMD_SQD2RTS_QPEE,
1710 [IB_QPS_SQD] = CMD_SQD2SQD_QPEE,
1711 },
1712 [IB_QPS_SQE] = {
1713 [IB_QPS_RESET] = CMD_ERR2RST_QPEE,
1714 [IB_QPS_ERR] = CMD_2ERR_QPEE,
1715 [IB_QPS_RTS] = CMD_SQERR2RTS_QPEE,
1716 },
1717 [IB_QPS_ERR] = {
1718 [IB_QPS_RESET] = CMD_ERR2RST_QPEE,
1719 [IB_QPS_ERR] = CMD_2ERR_QPEE,
1720 }
1da177e4 1721 };
d844183d 1722
1da177e4 1723 u8 op_mod = 0;
ed878458 1724 int my_mailbox = 0;
1da177e4
LT
1725 int err;
1726
d844183d 1727 if (op[cur][next] == CMD_ERR2RST_QPEE) {
1da177e4
LT
1728 op_mod = 3; /* don't write outbox, any->reset */
1729
1730 /* For debugging */
ed878458
RD
1731 if (!mailbox) {
1732 mailbox = mthca_alloc_mailbox(dev, GFP_KERNEL);
1733 if (!IS_ERR(mailbox)) {
1734 my_mailbox = 1;
1735 op_mod = 2; /* write outbox, any->reset */
1736 } else
1737 mailbox = NULL;
1738 }
d844183d
RD
1739
1740 err = mthca_cmd_box(dev, 0, mailbox ? mailbox->dma : 0,
1741 (!!is_ee << 24) | num, op_mod,
1742 op[cur][next], CMD_TIME_CLASS_C, status);
1743
1744 if (0 && mailbox) {
1da177e4
LT
1745 int i;
1746 mthca_dbg(dev, "Dumping QP context:\n");
d844183d 1747 printk(" %08x\n", be32_to_cpup(mailbox->buf));
1da177e4
LT
1748 for (i = 0; i < 0x100 / 4; ++i) {
1749 if (i % 8 == 0)
d844183d 1750 printk("[%02x] ", i * 4);
ed878458 1751 printk(" %08x",
97f52eb4 1752 be32_to_cpu(((__be32 *) mailbox->buf)[i + 2]));
1da177e4
LT
1753 if ((i + 1) % 8 == 0)
1754 printk("\n");
1755 }
1756 }
1da177e4 1757
d844183d
RD
1758 if (my_mailbox)
1759 mthca_free_mailbox(dev, mailbox);
1760 } else {
1761 if (0) {
1da177e4
LT
1762 int i;
1763 mthca_dbg(dev, "Dumping QP context:\n");
d844183d 1764 printk(" opt param mask: %08x\n", be32_to_cpup(mailbox->buf));
1da177e4
LT
1765 for (i = 0; i < 0x100 / 4; ++i) {
1766 if (i % 8 == 0)
d844183d 1767 printk(" [%02x] ", i * 4);
ed878458 1768 printk(" %08x",
97f52eb4 1769 be32_to_cpu(((__be32 *) mailbox->buf)[i + 2]));
1da177e4
LT
1770 if ((i + 1) % 8 == 0)
1771 printk("\n");
1772 }
1773 }
1774
d844183d
RD
1775 err = mthca_cmd(dev, mailbox->dma, optmask | (!!is_ee << 24) | num,
1776 op_mod, op[cur][next], CMD_TIME_CLASS_C, status);
1777 }
ed878458 1778
1da177e4
LT
1779 return err;
1780}
1781
1782int mthca_QUERY_QP(struct mthca_dev *dev, u32 num, int is_ee,
ed878458 1783 struct mthca_mailbox *mailbox, u8 *status)
1da177e4 1784{
ed878458
RD
1785 return mthca_cmd_box(dev, 0, mailbox->dma, (!!is_ee << 24) | num, 0,
1786 CMD_QUERY_QPEE, CMD_TIME_CLASS_A, status);
1da177e4
LT
1787}
1788
1789int mthca_CONF_SPECIAL_QP(struct mthca_dev *dev, int type, u32 qpn,
1790 u8 *status)
1791{
1792 u8 op_mod;
1793
1794 switch (type) {
1795 case IB_QPT_SMI:
1796 op_mod = 0;
1797 break;
1798 case IB_QPT_GSI:
1799 op_mod = 1;
1800 break;
1801 case IB_QPT_RAW_IPV6:
1802 op_mod = 2;
1803 break;
1804 case IB_QPT_RAW_ETY:
1805 op_mod = 3;
1806 break;
1807 default:
1808 return -EINVAL;
1809 }
1810
1811 return mthca_cmd(dev, 0, qpn, op_mod, CMD_CONF_SPECIAL_QP,
1812 CMD_TIME_CLASS_B, status);
1813}
1814
1815int mthca_MAD_IFC(struct mthca_dev *dev, int ignore_mkey, int ignore_bkey,
ed878458 1816 int port, struct ib_wc *in_wc, struct ib_grh *in_grh,
1da177e4
LT
1817 void *in_mad, void *response_mad, u8 *status)
1818{
ed878458
RD
1819 struct mthca_mailbox *inmailbox, *outmailbox;
1820 void *inbox;
1da177e4
LT
1821 int err;
1822 u32 in_modifier = port;
1823 u8 op_modifier = 0;
1824
1825#define MAD_IFC_BOX_SIZE 0x400
1826#define MAD_IFC_MY_QPN_OFFSET 0x100
68586b67
MT
1827#define MAD_IFC_RQPN_OFFSET 0x108
1828#define MAD_IFC_SL_OFFSET 0x10c
1829#define MAD_IFC_G_PATH_OFFSET 0x10d
1830#define MAD_IFC_RLID_OFFSET 0x10e
1831#define MAD_IFC_PKEY_OFFSET 0x112
1da177e4
LT
1832#define MAD_IFC_GRH_OFFSET 0x140
1833
ed878458
RD
1834 inmailbox = mthca_alloc_mailbox(dev, GFP_KERNEL);
1835 if (IS_ERR(inmailbox))
1836 return PTR_ERR(inmailbox);
1837 inbox = inmailbox->buf;
1838
1839 outmailbox = mthca_alloc_mailbox(dev, GFP_KERNEL);
1840 if (IS_ERR(outmailbox)) {
1841 mthca_free_mailbox(dev, inmailbox);
1842 return PTR_ERR(outmailbox);
1843 }
1da177e4 1844
ed878458 1845 memcpy(inbox, in_mad, 256);
1da177e4
LT
1846
1847 /*
1848 * Key check traps can't be generated unless we have in_wc to
1849 * tell us where to send the trap.
1850 */
1851 if (ignore_mkey || !in_wc)
1852 op_modifier |= 0x1;
1853 if (ignore_bkey || !in_wc)
1854 op_modifier |= 0x2;
1855
1856 if (in_wc) {
1857 u8 val;
1858
ed878458 1859 memset(inbox + 256, 0, 256);
1da177e4 1860
062dbb69 1861 MTHCA_PUT(inbox, in_wc->qp->qp_num, MAD_IFC_MY_QPN_OFFSET);
ed878458 1862 MTHCA_PUT(inbox, in_wc->src_qp, MAD_IFC_RQPN_OFFSET);
1da177e4
LT
1863
1864 val = in_wc->sl << 4;
ed878458 1865 MTHCA_PUT(inbox, val, MAD_IFC_SL_OFFSET);
1da177e4
LT
1866
1867 val = in_wc->dlid_path_bits |
1868 (in_wc->wc_flags & IB_WC_GRH ? 0x80 : 0);
68586b67 1869 MTHCA_PUT(inbox, val, MAD_IFC_G_PATH_OFFSET);
1da177e4 1870
ed878458
RD
1871 MTHCA_PUT(inbox, in_wc->slid, MAD_IFC_RLID_OFFSET);
1872 MTHCA_PUT(inbox, in_wc->pkey_index, MAD_IFC_PKEY_OFFSET);
1da177e4
LT
1873
1874 if (in_grh)
ed878458 1875 memcpy(inbox + MAD_IFC_GRH_OFFSET, in_grh, 40);
1da177e4 1876
68586b67 1877 op_modifier |= 0x4;
1da177e4
LT
1878
1879 in_modifier |= in_wc->slid << 16;
1880 }
1881
ed878458
RD
1882 err = mthca_cmd_box(dev, inmailbox->dma, outmailbox->dma,
1883 in_modifier, op_modifier,
1da177e4
LT
1884 CMD_MAD_IFC, CMD_TIME_CLASS_C, status);
1885
1886 if (!err && !*status)
ed878458 1887 memcpy(response_mad, outmailbox->buf, 256);
1da177e4 1888
ed878458
RD
1889 mthca_free_mailbox(dev, inmailbox);
1890 mthca_free_mailbox(dev, outmailbox);
1da177e4
LT
1891 return err;
1892}
1893
ed878458
RD
1894int mthca_READ_MGM(struct mthca_dev *dev, int index,
1895 struct mthca_mailbox *mailbox, u8 *status)
1da177e4 1896{
ed878458
RD
1897 return mthca_cmd_box(dev, 0, mailbox->dma, index, 0,
1898 CMD_READ_MGM, CMD_TIME_CLASS_A, status);
1da177e4
LT
1899}
1900
ed878458
RD
1901int mthca_WRITE_MGM(struct mthca_dev *dev, int index,
1902 struct mthca_mailbox *mailbox, u8 *status)
1da177e4 1903{
ed878458
RD
1904 return mthca_cmd(dev, mailbox->dma, index, 0, CMD_WRITE_MGM,
1905 CMD_TIME_CLASS_A, status);
1da177e4
LT
1906}
1907
ed878458
RD
1908int mthca_MGID_HASH(struct mthca_dev *dev, struct mthca_mailbox *mailbox,
1909 u16 *hash, u8 *status)
1da177e4 1910{
1da177e4
LT
1911 u64 imm;
1912 int err;
1913
ed878458 1914 err = mthca_cmd_imm(dev, mailbox->dma, &imm, 0, 0, CMD_MGID_HASH,
1da177e4 1915 CMD_TIME_CLASS_A, status);
1da177e4 1916
ed878458 1917 *hash = imm;
1da177e4
LT
1918 return err;
1919}
1920
1921int mthca_NOP(struct mthca_dev *dev, u8 *status)
1922{
1923 return mthca_cmd(dev, 0, 0x1f, 0, CMD_NOP, msecs_to_jiffies(100), status);
1924}