aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/infiniband/hw/mthca/mthca_cmd.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/infiniband/hw/mthca/mthca_cmd.c')
-rw-r--r--drivers/infiniband/hw/mthca/mthca_cmd.c323
1 files changed, 246 insertions, 77 deletions
diff --git a/drivers/infiniband/hw/mthca/mthca_cmd.c b/drivers/infiniband/hw/mthca/mthca_cmd.c
index 2825615ce81c..343eca507870 100644
--- a/drivers/infiniband/hw/mthca/mthca_cmd.c
+++ b/drivers/infiniband/hw/mthca/mthca_cmd.c
@@ -1,7 +1,7 @@
1/* 1/*
2 * Copyright (c) 2004, 2005 Topspin Communications. All rights reserved. 2 * Copyright (c) 2004, 2005 Topspin Communications. All rights reserved.
3 * Copyright (c) 2005 Mellanox Technologies. All rights reserved. 3 * Copyright (c) 2005 Mellanox Technologies. All rights reserved.
4 * Copyright (c) 2005 Cisco Systems. All rights reserved. 4 * Copyright (c) 2005, 2006 Cisco Systems. All rights reserved.
5 * 5 *
6 * This software is available to you under a choice of one of two 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 7 * licenses. You may choose to be licensed under the terms of the GNU
@@ -182,25 +182,58 @@ struct mthca_cmd_context {
182 u8 status; 182 u8 status;
183}; 183};
184 184
185static int fw_cmd_doorbell = 1;
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
185static inline int go_bit(struct mthca_dev *dev) 190static inline int go_bit(struct mthca_dev *dev)
186{ 191{
187 return readl(dev->hcr + HCR_STATUS_OFFSET) & 192 return readl(dev->hcr + HCR_STATUS_OFFSET) &
188 swab32(1 << HCR_GO_BIT); 193 swab32(1 << HCR_GO_BIT);
189} 194}
190 195
191static int mthca_cmd_post(struct mthca_dev *dev, 196static void mthca_cmd_post_dbell(struct mthca_dev *dev,
192 u64 in_param, 197 u64 in_param,
193 u64 out_param, 198 u64 out_param,
194 u32 in_modifier, 199 u32 in_modifier,
195 u8 op_modifier, 200 u8 op_modifier,
196 u16 op, 201 u16 op,
197 u16 token, 202 u16 token)
198 int event)
199{ 203{
200 int err = 0; 204 void __iomem *ptr = dev->cmd.dbell_map;
205 u16 *offs = dev->cmd.dbell_offsets;
201 206
202 mutex_lock(&dev->cmd.hcr_mutex); 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}
203 227
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{
204 if (event) { 237 if (event) {
205 unsigned long end = jiffies + GO_BIT_TIMEOUT; 238 unsigned long end = jiffies + GO_BIT_TIMEOUT;
206 239
@@ -210,10 +243,8 @@ static int mthca_cmd_post(struct mthca_dev *dev,
210 } 243 }
211 } 244 }
212 245
213 if (go_bit(dev)) { 246 if (go_bit(dev))
214 err = -EAGAIN; 247 return -EAGAIN;
215 goto out;
216 }
217 248
218 /* 249 /*
219 * We use writel (instead of something like memcpy_toio) 250 * We use writel (instead of something like memcpy_toio)
@@ -236,7 +267,29 @@ static int mthca_cmd_post(struct mthca_dev *dev,
236 (op_modifier << HCR_OPMOD_SHIFT) | 267 (op_modifier << HCR_OPMOD_SHIFT) |
237 op), dev->hcr + 6 * 4); 268 op), dev->hcr + 6 * 4);
238 269
239out: 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
240 mutex_unlock(&dev->cmd.hcr_mutex); 293 mutex_unlock(&dev->cmd.hcr_mutex);
241 return err; 294 return err;
242} 295}
@@ -275,7 +328,7 @@ static int mthca_cmd_poll(struct mthca_dev *dev,
275 } 328 }
276 329
277 if (out_is_imm) 330 if (out_is_imm)
278 *out_param = 331 *out_param =
279 (u64) be32_to_cpu((__force __be32) 332 (u64) be32_to_cpu((__force __be32)
280 __raw_readl(dev->hcr + HCR_OUT_PARAM_OFFSET)) << 32 | 333 __raw_readl(dev->hcr + HCR_OUT_PARAM_OFFSET)) << 32 |
281 (u64) be32_to_cpu((__force __be32) 334 (u64) be32_to_cpu((__force __be32)
@@ -386,7 +439,7 @@ static int mthca_cmd_box(struct mthca_dev *dev,
386 unsigned long timeout, 439 unsigned long timeout,
387 u8 *status) 440 u8 *status)
388{ 441{
389 if (dev->cmd.use_events) 442 if (dev->cmd.flags & MTHCA_CMD_USE_EVENTS)
390 return mthca_cmd_wait(dev, in_param, &out_param, 0, 443 return mthca_cmd_wait(dev, in_param, &out_param, 0,
391 in_modifier, op_modifier, op, 444 in_modifier, op_modifier, op,
392 timeout, status); 445 timeout, status);
@@ -423,7 +476,7 @@ static int mthca_cmd_imm(struct mthca_dev *dev,
423 unsigned long timeout, 476 unsigned long timeout,
424 u8 *status) 477 u8 *status)
425{ 478{
426 if (dev->cmd.use_events) 479 if (dev->cmd.flags & MTHCA_CMD_USE_EVENTS)
427 return mthca_cmd_wait(dev, in_param, out_param, 1, 480 return mthca_cmd_wait(dev, in_param, out_param, 1,
428 in_modifier, op_modifier, op, 481 in_modifier, op_modifier, op,
429 timeout, status); 482 timeout, status);
@@ -437,7 +490,7 @@ int mthca_cmd_init(struct mthca_dev *dev)
437{ 490{
438 mutex_init(&dev->cmd.hcr_mutex); 491 mutex_init(&dev->cmd.hcr_mutex);
439 sema_init(&dev->cmd.poll_sem, 1); 492 sema_init(&dev->cmd.poll_sem, 1);
440 dev->cmd.use_events = 0; 493 dev->cmd.flags = 0;
441 494
442 dev->hcr = ioremap(pci_resource_start(dev->pdev, 0) + MTHCA_HCR_BASE, 495 dev->hcr = ioremap(pci_resource_start(dev->pdev, 0) + MTHCA_HCR_BASE,
443 MTHCA_HCR_SIZE); 496 MTHCA_HCR_SIZE);
@@ -461,6 +514,8 @@ void mthca_cmd_cleanup(struct mthca_dev *dev)
461{ 514{
462 pci_pool_destroy(dev->cmd.pool); 515 pci_pool_destroy(dev->cmd.pool);
463 iounmap(dev->hcr); 516 iounmap(dev->hcr);
517 if (dev->cmd.flags & MTHCA_CMD_POST_DOORBELLS)
518 iounmap(dev->cmd.dbell_map);
464} 519}
465 520
466/* 521/*
@@ -498,7 +553,8 @@ int mthca_cmd_use_events(struct mthca_dev *dev)
498 ; /* nothing */ 553 ; /* nothing */
499 --dev->cmd.token_mask; 554 --dev->cmd.token_mask;
500 555
501 dev->cmd.use_events = 1; 556 dev->cmd.flags |= MTHCA_CMD_USE_EVENTS;
557
502 down(&dev->cmd.poll_sem); 558 down(&dev->cmd.poll_sem);
503 559
504 return 0; 560 return 0;
@@ -511,7 +567,7 @@ void mthca_cmd_use_polling(struct mthca_dev *dev)
511{ 567{
512 int i; 568 int i;
513 569
514 dev->cmd.use_events = 0; 570 dev->cmd.flags &= ~MTHCA_CMD_USE_EVENTS;
515 571
516 for (i = 0; i < dev->cmd.max_cmds; ++i) 572 for (i = 0; i < dev->cmd.max_cmds; ++i)
517 down(&dev->cmd.event_sem); 573 down(&dev->cmd.event_sem);
@@ -596,8 +652,9 @@ static int mthca_map_cmd(struct mthca_dev *dev, u16 op, struct mthca_icm *icm,
596 * address or size and use that as our log2 size. 652 * address or size and use that as our log2 size.
597 */ 653 */
598 lg = ffs(mthca_icm_addr(&iter) | mthca_icm_size(&iter)) - 1; 654 lg = ffs(mthca_icm_addr(&iter) | mthca_icm_size(&iter)) - 1;
599 if (lg < 12) { 655 if (lg < MTHCA_ICM_PAGE_SHIFT) {
600 mthca_warn(dev, "Got FW area not aligned to 4K (%llx/%lx).\n", 656 mthca_warn(dev, "Got FW area not aligned to %d (%llx/%lx).\n",
657 MTHCA_ICM_PAGE_SIZE,
601 (unsigned long long) mthca_icm_addr(&iter), 658 (unsigned long long) mthca_icm_addr(&iter),
602 mthca_icm_size(&iter)); 659 mthca_icm_size(&iter));
603 err = -EINVAL; 660 err = -EINVAL;
@@ -609,8 +666,9 @@ static int mthca_map_cmd(struct mthca_dev *dev, u16 op, struct mthca_icm *icm,
609 virt += 1 << lg; 666 virt += 1 << lg;
610 } 667 }
611 668
612 pages[nent * 2 + 1] = cpu_to_be64((mthca_icm_addr(&iter) + 669 pages[nent * 2 + 1] =
613 (i << lg)) | (lg - 12)); 670 cpu_to_be64((mthca_icm_addr(&iter) + (i << lg)) |
671 (lg - MTHCA_ICM_PAGE_SHIFT));
614 ts += 1 << (lg - 10); 672 ts += 1 << (lg - 10);
615 ++tc; 673 ++tc;
616 674
@@ -661,12 +719,41 @@ int mthca_RUN_FW(struct mthca_dev *dev, u8 *status)
661 return mthca_cmd(dev, 0, 0, 0, CMD_RUN_FW, CMD_TIME_CLASS_A, status); 719 return mthca_cmd(dev, 0, 0, 0, CMD_RUN_FW, CMD_TIME_CLASS_A, status);
662} 720}
663 721
722static void mthca_setup_cmd_doorbells(struct mthca_dev *dev, u64 base)
723{
724 unsigned long addr;
725 u16 max_off = 0;
726 int i;
727
728 for (i = 0; i < 8; ++i)
729 max_off = max(max_off, dev->cmd.dbell_offsets[i]);
730
731 if ((base & PAGE_MASK) != ((base + max_off) & PAGE_MASK)) {
732 mthca_warn(dev, "Firmware doorbell region at 0x%016llx, "
733 "length 0x%x crosses a page boundary\n",
734 (unsigned long long) base, max_off);
735 return;
736 }
737
738 addr = pci_resource_start(dev->pdev, 2) +
739 ((pci_resource_len(dev->pdev, 2) - 1) & base);
740 dev->cmd.dbell_map = ioremap(addr, max_off + sizeof(u32));
741 if (!dev->cmd.dbell_map)
742 return;
743
744 dev->cmd.flags |= MTHCA_CMD_POST_DOORBELLS;
745 mthca_dbg(dev, "Mapped doorbell page for posting FW commands\n");
746}
747
664int mthca_QUERY_FW(struct mthca_dev *dev, u8 *status) 748int mthca_QUERY_FW(struct mthca_dev *dev, u8 *status)
665{ 749{
666 struct mthca_mailbox *mailbox; 750 struct mthca_mailbox *mailbox;
667 u32 *outbox; 751 u32 *outbox;
752 u64 base;
753 u32 tmp;
668 int err = 0; 754 int err = 0;
669 u8 lg; 755 u8 lg;
756 int i;
670 757
671#define QUERY_FW_OUT_SIZE 0x100 758#define QUERY_FW_OUT_SIZE 0x100
672#define QUERY_FW_VER_OFFSET 0x00 759#define QUERY_FW_VER_OFFSET 0x00
@@ -674,6 +761,10 @@ int mthca_QUERY_FW(struct mthca_dev *dev, u8 *status)
674#define QUERY_FW_ERR_START_OFFSET 0x30 761#define QUERY_FW_ERR_START_OFFSET 0x30
675#define QUERY_FW_ERR_SIZE_OFFSET 0x38 762#define QUERY_FW_ERR_SIZE_OFFSET 0x38
676 763
764#define QUERY_FW_CMD_DB_EN_OFFSET 0x10
765#define QUERY_FW_CMD_DB_OFFSET 0x50
766#define QUERY_FW_CMD_DB_BASE 0x60
767
677#define QUERY_FW_START_OFFSET 0x20 768#define QUERY_FW_START_OFFSET 0x20
678#define QUERY_FW_END_OFFSET 0x28 769#define QUERY_FW_END_OFFSET 0x28
679 770
@@ -702,16 +793,29 @@ int mthca_QUERY_FW(struct mthca_dev *dev, u8 *status)
702 ((dev->fw_ver & 0xffff0000ull) >> 16) | 793 ((dev->fw_ver & 0xffff0000ull) >> 16) |
703 ((dev->fw_ver & 0x0000ffffull) << 16); 794 ((dev->fw_ver & 0x0000ffffull) << 16);
704 795
796 mthca_dbg(dev, "FW version %012llx, max commands %d\n",
797 (unsigned long long) dev->fw_ver, dev->cmd.max_cmds);
798
705 MTHCA_GET(lg, outbox, QUERY_FW_MAX_CMD_OFFSET); 799 MTHCA_GET(lg, outbox, QUERY_FW_MAX_CMD_OFFSET);
706 dev->cmd.max_cmds = 1 << lg; 800 dev->cmd.max_cmds = 1 << lg;
707 MTHCA_GET(dev->catas_err.addr, outbox, QUERY_FW_ERR_START_OFFSET); 801 MTHCA_GET(dev->catas_err.addr, outbox, QUERY_FW_ERR_START_OFFSET);
708 MTHCA_GET(dev->catas_err.size, outbox, QUERY_FW_ERR_SIZE_OFFSET); 802 MTHCA_GET(dev->catas_err.size, outbox, QUERY_FW_ERR_SIZE_OFFSET);
709 803
710 mthca_dbg(dev, "FW version %012llx, max commands %d\n",
711 (unsigned long long) dev->fw_ver, dev->cmd.max_cmds);
712 mthca_dbg(dev, "Catastrophic error buffer at 0x%llx, size 0x%x\n", 804 mthca_dbg(dev, "Catastrophic error buffer at 0x%llx, size 0x%x\n",
713 (unsigned long long) dev->catas_err.addr, dev->catas_err.size); 805 (unsigned long long) dev->catas_err.addr, dev->catas_err.size);
714 806
807 MTHCA_GET(tmp, outbox, QUERY_FW_CMD_DB_EN_OFFSET);
808 if (tmp & 0x1) {
809 mthca_dbg(dev, "FW supports commands through doorbells\n");
810
811 MTHCA_GET(base, outbox, QUERY_FW_CMD_DB_BASE);
812 for (i = 0; i < MTHCA_CMD_NUM_DBELL_DWORDS; ++i)
813 MTHCA_GET(dev->cmd.dbell_offsets[i], outbox,
814 QUERY_FW_CMD_DB_OFFSET + (i << 1));
815
816 mthca_setup_cmd_doorbells(dev, base);
817 }
818
715 if (mthca_is_memfree(dev)) { 819 if (mthca_is_memfree(dev)) {
716 MTHCA_GET(dev->fw.arbel.fw_pages, outbox, QUERY_FW_SIZE_OFFSET); 820 MTHCA_GET(dev->fw.arbel.fw_pages, outbox, QUERY_FW_SIZE_OFFSET);
717 MTHCA_GET(dev->fw.arbel.clr_int_base, outbox, QUERY_FW_CLR_INT_BASE_OFFSET); 821 MTHCA_GET(dev->fw.arbel.clr_int_base, outbox, QUERY_FW_CLR_INT_BASE_OFFSET);
@@ -720,12 +824,12 @@ int mthca_QUERY_FW(struct mthca_dev *dev, u8 *status)
720 mthca_dbg(dev, "FW size %d KB\n", dev->fw.arbel.fw_pages << 2); 824 mthca_dbg(dev, "FW size %d KB\n", dev->fw.arbel.fw_pages << 2);
721 825
722 /* 826 /*
723 * Arbel page size is always 4 KB; round up number of 827 * Round up number of system pages needed in case
724 * system pages needed. 828 * MTHCA_ICM_PAGE_SIZE < PAGE_SIZE.
725 */ 829 */
726 dev->fw.arbel.fw_pages = 830 dev->fw.arbel.fw_pages =
727 ALIGN(dev->fw.arbel.fw_pages, PAGE_SIZE >> 12) >> 831 ALIGN(dev->fw.arbel.fw_pages, PAGE_SIZE / MTHCA_ICM_PAGE_SIZE) >>
728 (PAGE_SHIFT - 12); 832 (PAGE_SHIFT - MTHCA_ICM_PAGE_SHIFT);
729 833
730 mthca_dbg(dev, "Clear int @ %llx, EQ arm @ %llx, EQ set CI @ %llx\n", 834 mthca_dbg(dev, "Clear int @ %llx, EQ arm @ %llx, EQ set CI @ %llx\n",
731 (unsigned long long) dev->fw.arbel.clr_int_base, 835 (unsigned long long) dev->fw.arbel.clr_int_base,
@@ -1173,7 +1277,8 @@ int mthca_INIT_HCA(struct mthca_dev *dev,
1173 int err; 1277 int err;
1174 1278
1175#define INIT_HCA_IN_SIZE 0x200 1279#define INIT_HCA_IN_SIZE 0x200
1176#define INIT_HCA_FLAGS_OFFSET 0x014 1280#define INIT_HCA_FLAGS1_OFFSET 0x00c
1281#define INIT_HCA_FLAGS2_OFFSET 0x014
1177#define INIT_HCA_QPC_OFFSET 0x020 1282#define INIT_HCA_QPC_OFFSET 0x020
1178#define INIT_HCA_QPC_BASE_OFFSET (INIT_HCA_QPC_OFFSET + 0x10) 1283#define INIT_HCA_QPC_BASE_OFFSET (INIT_HCA_QPC_OFFSET + 0x10)
1179#define INIT_HCA_LOG_QP_OFFSET (INIT_HCA_QPC_OFFSET + 0x17) 1284#define INIT_HCA_LOG_QP_OFFSET (INIT_HCA_QPC_OFFSET + 0x17)
@@ -1216,15 +1321,18 @@ int mthca_INIT_HCA(struct mthca_dev *dev,
1216 1321
1217 memset(inbox, 0, INIT_HCA_IN_SIZE); 1322 memset(inbox, 0, INIT_HCA_IN_SIZE);
1218 1323
1324 if (dev->mthca_flags & MTHCA_FLAG_SINAI_OPT)
1325 MTHCA_PUT(inbox, 0x1, INIT_HCA_FLAGS1_OFFSET);
1326
1219#if defined(__LITTLE_ENDIAN) 1327#if defined(__LITTLE_ENDIAN)
1220 *(inbox + INIT_HCA_FLAGS_OFFSET / 4) &= ~cpu_to_be32(1 << 1); 1328 *(inbox + INIT_HCA_FLAGS2_OFFSET / 4) &= ~cpu_to_be32(1 << 1);
1221#elif defined(__BIG_ENDIAN) 1329#elif defined(__BIG_ENDIAN)
1222 *(inbox + INIT_HCA_FLAGS_OFFSET / 4) |= cpu_to_be32(1 << 1); 1330 *(inbox + INIT_HCA_FLAGS2_OFFSET / 4) |= cpu_to_be32(1 << 1);
1223#else 1331#else
1224#error Host endianness not defined 1332#error Host endianness not defined
1225#endif 1333#endif
1226 /* Check port for UD address vector: */ 1334 /* Check port for UD address vector: */
1227 *(inbox + INIT_HCA_FLAGS_OFFSET / 4) |= cpu_to_be32(1); 1335 *(inbox + INIT_HCA_FLAGS2_OFFSET / 4) |= cpu_to_be32(1);
1228 1336
1229 /* We leave wqe_quota, responder_exu, etc as 0 (default) */ 1337 /* We leave wqe_quota, responder_exu, etc as 0 (default) */
1230 1338
@@ -1438,11 +1546,11 @@ int mthca_SET_ICM_SIZE(struct mthca_dev *dev, u64 icm_size, u64 *aux_pages,
1438 return ret; 1546 return ret;
1439 1547
1440 /* 1548 /*
1441 * Arbel page size is always 4 KB; round up number of system 1549 * Round up number of system pages needed in case
1442 * pages needed. 1550 * MTHCA_ICM_PAGE_SIZE < PAGE_SIZE.
1443 */ 1551 */
1444 *aux_pages = (*aux_pages + (1 << (PAGE_SHIFT - 12)) - 1) >> (PAGE_SHIFT - 12); 1552 *aux_pages = ALIGN(*aux_pages, PAGE_SIZE / MTHCA_ICM_PAGE_SIZE) >>
1445 *aux_pages = ALIGN(*aux_pages, PAGE_SIZE >> 12) >> (PAGE_SHIFT - 12); 1553 (PAGE_SHIFT - MTHCA_ICM_PAGE_SHIFT);
1446 1554
1447 return 0; 1555 return 0;
1448} 1556}
@@ -1514,6 +1622,37 @@ int mthca_HW2SW_CQ(struct mthca_dev *dev, struct mthca_mailbox *mailbox,
1514 CMD_TIME_CLASS_A, status); 1622 CMD_TIME_CLASS_A, status);
1515} 1623}
1516 1624
1625int mthca_RESIZE_CQ(struct mthca_dev *dev, int cq_num, u32 lkey, u8 log_size,
1626 u8 *status)
1627{
1628 struct mthca_mailbox *mailbox;
1629 __be32 *inbox;
1630 int err;
1631
1632#define RESIZE_CQ_IN_SIZE 0x40
1633#define RESIZE_CQ_LOG_SIZE_OFFSET 0x0c
1634#define RESIZE_CQ_LKEY_OFFSET 0x1c
1635
1636 mailbox = mthca_alloc_mailbox(dev, GFP_KERNEL);
1637 if (IS_ERR(mailbox))
1638 return PTR_ERR(mailbox);
1639 inbox = mailbox->buf;
1640
1641 memset(inbox, 0, RESIZE_CQ_IN_SIZE);
1642 /*
1643 * Leave start address fields zeroed out -- mthca assumes that
1644 * MRs for CQs always start at virtual address 0.
1645 */
1646 MTHCA_PUT(inbox, log_size, RESIZE_CQ_LOG_SIZE_OFFSET);
1647 MTHCA_PUT(inbox, lkey, RESIZE_CQ_LKEY_OFFSET);
1648
1649 err = mthca_cmd(dev, mailbox->dma, cq_num, 1, CMD_RESIZE_CQ,
1650 CMD_TIME_CLASS_B, status);
1651
1652 mthca_free_mailbox(dev, mailbox);
1653 return err;
1654}
1655
1517int mthca_SW2HW_SRQ(struct mthca_dev *dev, struct mthca_mailbox *mailbox, 1656int mthca_SW2HW_SRQ(struct mthca_dev *dev, struct mthca_mailbox *mailbox,
1518 int srq_num, u8 *status) 1657 int srq_num, u8 *status)
1519{ 1658{
@@ -1529,37 +1668,69 @@ int mthca_HW2SW_SRQ(struct mthca_dev *dev, struct mthca_mailbox *mailbox,
1529 CMD_TIME_CLASS_A, status); 1668 CMD_TIME_CLASS_A, status);
1530} 1669}
1531 1670
1671int mthca_QUERY_SRQ(struct mthca_dev *dev, u32 num,
1672 struct mthca_mailbox *mailbox, u8 *status)
1673{
1674 return mthca_cmd_box(dev, 0, mailbox->dma, num, 0,
1675 CMD_QUERY_SRQ, CMD_TIME_CLASS_A, status);
1676}
1677
1532int mthca_ARM_SRQ(struct mthca_dev *dev, int srq_num, int limit, u8 *status) 1678int mthca_ARM_SRQ(struct mthca_dev *dev, int srq_num, int limit, u8 *status)
1533{ 1679{
1534 return mthca_cmd(dev, limit, srq_num, 0, CMD_ARM_SRQ, 1680 return mthca_cmd(dev, limit, srq_num, 0, CMD_ARM_SRQ,
1535 CMD_TIME_CLASS_B, status); 1681 CMD_TIME_CLASS_B, status);
1536} 1682}
1537 1683
1538int mthca_MODIFY_QP(struct mthca_dev *dev, int trans, u32 num, 1684int mthca_MODIFY_QP(struct mthca_dev *dev, enum ib_qp_state cur,
1539 int is_ee, struct mthca_mailbox *mailbox, u32 optmask, 1685 enum ib_qp_state next, u32 num, int is_ee,
1686 struct mthca_mailbox *mailbox, u32 optmask,
1540 u8 *status) 1687 u8 *status)
1541{ 1688{
1542 static const u16 op[] = { 1689 static const u16 op[IB_QPS_ERR + 1][IB_QPS_ERR + 1] = {
1543 [MTHCA_TRANS_RST2INIT] = CMD_RST2INIT_QPEE, 1690 [IB_QPS_RESET] = {
1544 [MTHCA_TRANS_INIT2INIT] = CMD_INIT2INIT_QPEE, 1691 [IB_QPS_RESET] = CMD_ERR2RST_QPEE,
1545 [MTHCA_TRANS_INIT2RTR] = CMD_INIT2RTR_QPEE, 1692 [IB_QPS_ERR] = CMD_2ERR_QPEE,
1546 [MTHCA_TRANS_RTR2RTS] = CMD_RTR2RTS_QPEE, 1693 [IB_QPS_INIT] = CMD_RST2INIT_QPEE,
1547 [MTHCA_TRANS_RTS2RTS] = CMD_RTS2RTS_QPEE, 1694 },
1548 [MTHCA_TRANS_SQERR2RTS] = CMD_SQERR2RTS_QPEE, 1695 [IB_QPS_INIT] = {
1549 [MTHCA_TRANS_ANY2ERR] = CMD_2ERR_QPEE, 1696 [IB_QPS_RESET] = CMD_ERR2RST_QPEE,
1550 [MTHCA_TRANS_RTS2SQD] = CMD_RTS2SQD_QPEE, 1697 [IB_QPS_ERR] = CMD_2ERR_QPEE,
1551 [MTHCA_TRANS_SQD2SQD] = CMD_SQD2SQD_QPEE, 1698 [IB_QPS_INIT] = CMD_INIT2INIT_QPEE,
1552 [MTHCA_TRANS_SQD2RTS] = CMD_SQD2RTS_QPEE, 1699 [IB_QPS_RTR] = CMD_INIT2RTR_QPEE,
1553 [MTHCA_TRANS_ANY2RST] = CMD_ERR2RST_QPEE 1700 },
1701 [IB_QPS_RTR] = {
1702 [IB_QPS_RESET] = CMD_ERR2RST_QPEE,
1703 [IB_QPS_ERR] = CMD_2ERR_QPEE,
1704 [IB_QPS_RTS] = CMD_RTR2RTS_QPEE,
1705 },
1706 [IB_QPS_RTS] = {
1707 [IB_QPS_RESET] = CMD_ERR2RST_QPEE,
1708 [IB_QPS_ERR] = CMD_2ERR_QPEE,
1709 [IB_QPS_RTS] = CMD_RTS2RTS_QPEE,
1710 [IB_QPS_SQD] = CMD_RTS2SQD_QPEE,
1711 },
1712 [IB_QPS_SQD] = {
1713 [IB_QPS_RESET] = CMD_ERR2RST_QPEE,
1714 [IB_QPS_ERR] = CMD_2ERR_QPEE,
1715 [IB_QPS_RTS] = CMD_SQD2RTS_QPEE,
1716 [IB_QPS_SQD] = CMD_SQD2SQD_QPEE,
1717 },
1718 [IB_QPS_SQE] = {
1719 [IB_QPS_RESET] = CMD_ERR2RST_QPEE,
1720 [IB_QPS_ERR] = CMD_2ERR_QPEE,
1721 [IB_QPS_RTS] = CMD_SQERR2RTS_QPEE,
1722 },
1723 [IB_QPS_ERR] = {
1724 [IB_QPS_RESET] = CMD_ERR2RST_QPEE,
1725 [IB_QPS_ERR] = CMD_2ERR_QPEE,
1726 }
1554 }; 1727 };
1728
1555 u8 op_mod = 0; 1729 u8 op_mod = 0;
1556 int my_mailbox = 0; 1730 int my_mailbox = 0;
1557 int err; 1731 int err;
1558 1732
1559 if (trans < 0 || trans >= ARRAY_SIZE(op)) 1733 if (op[cur][next] == CMD_ERR2RST_QPEE) {
1560 return -EINVAL;
1561
1562 if (trans == MTHCA_TRANS_ANY2RST) {
1563 op_mod = 3; /* don't write outbox, any->reset */ 1734 op_mod = 3; /* don't write outbox, any->reset */
1564 1735
1565 /* For debugging */ 1736 /* For debugging */
@@ -1571,34 +1742,35 @@ int mthca_MODIFY_QP(struct mthca_dev *dev, int trans, u32 num,
1571 } else 1742 } else
1572 mailbox = NULL; 1743 mailbox = NULL;
1573 } 1744 }
1574 } else { 1745
1575 if (0) { 1746 err = mthca_cmd_box(dev, 0, mailbox ? mailbox->dma : 0,
1747 (!!is_ee << 24) | num, op_mod,
1748 op[cur][next], CMD_TIME_CLASS_C, status);
1749
1750 if (0 && mailbox) {
1576 int i; 1751 int i;
1577 mthca_dbg(dev, "Dumping QP context:\n"); 1752 mthca_dbg(dev, "Dumping QP context:\n");
1578 printk(" opt param mask: %08x\n", be32_to_cpup(mailbox->buf)); 1753 printk(" %08x\n", be32_to_cpup(mailbox->buf));
1579 for (i = 0; i < 0x100 / 4; ++i) { 1754 for (i = 0; i < 0x100 / 4; ++i) {
1580 if (i % 8 == 0) 1755 if (i % 8 == 0)
1581 printk(" [%02x] ", i * 4); 1756 printk("[%02x] ", i * 4);
1582 printk(" %08x", 1757 printk(" %08x",
1583 be32_to_cpu(((__be32 *) mailbox->buf)[i + 2])); 1758 be32_to_cpu(((__be32 *) mailbox->buf)[i + 2]));
1584 if ((i + 1) % 8 == 0) 1759 if ((i + 1) % 8 == 0)
1585 printk("\n"); 1760 printk("\n");
1586 } 1761 }
1587 } 1762 }
1588 }
1589
1590 if (trans == MTHCA_TRANS_ANY2RST) {
1591 err = mthca_cmd_box(dev, 0, mailbox ? mailbox->dma : 0,
1592 (!!is_ee << 24) | num, op_mod,
1593 op[trans], CMD_TIME_CLASS_C, status);
1594 1763
1595 if (0 && mailbox) { 1764 if (my_mailbox)
1765 mthca_free_mailbox(dev, mailbox);
1766 } else {
1767 if (0) {
1596 int i; 1768 int i;
1597 mthca_dbg(dev, "Dumping QP context:\n"); 1769 mthca_dbg(dev, "Dumping QP context:\n");
1598 printk(" %08x\n", be32_to_cpup(mailbox->buf)); 1770 printk(" opt param mask: %08x\n", be32_to_cpup(mailbox->buf));
1599 for (i = 0; i < 0x100 / 4; ++i) { 1771 for (i = 0; i < 0x100 / 4; ++i) {
1600 if (i % 8 == 0) 1772 if (i % 8 == 0)
1601 printk("[%02x] ", i * 4); 1773 printk(" [%02x] ", i * 4);
1602 printk(" %08x", 1774 printk(" %08x",
1603 be32_to_cpu(((__be32 *) mailbox->buf)[i + 2])); 1775 be32_to_cpu(((__be32 *) mailbox->buf)[i + 2]));
1604 if ((i + 1) % 8 == 0) 1776 if ((i + 1) % 8 == 0)
@@ -1606,12 +1778,9 @@ int mthca_MODIFY_QP(struct mthca_dev *dev, int trans, u32 num,
1606 } 1778 }
1607 } 1779 }
1608 1780
1609 } else 1781 err = mthca_cmd(dev, mailbox->dma, optmask | (!!is_ee << 24) | num,
1610 err = mthca_cmd(dev, mailbox->dma, (!!is_ee << 24) | num, 1782 op_mod, op[cur][next], CMD_TIME_CLASS_C, status);
1611 op_mod, op[trans], CMD_TIME_CLASS_C, status); 1783 }
1612
1613 if (my_mailbox)
1614 mthca_free_mailbox(dev, mailbox);
1615 1784
1616 return err; 1785 return err;
1617} 1786}