diff options
Diffstat (limited to 'drivers/infiniband/hw/mthca/mthca_cmd.c')
-rw-r--r-- | drivers/infiniband/hw/mthca/mthca_cmd.c | 323 |
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 | ||
185 | static int fw_cmd_doorbell = 1; | ||
186 | module_param(fw_cmd_doorbell, int, 0644); | ||
187 | MODULE_PARM_DESC(fw_cmd_doorbell, "post FW commands through doorbell page if nonzero " | ||
188 | "(and supported by FW)"); | ||
189 | |||
185 | static inline int go_bit(struct mthca_dev *dev) | 190 | static 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 | ||
191 | static int mthca_cmd_post(struct mthca_dev *dev, | 196 | static 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 | ||
228 | static 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 | ||
239 | out: | 270 | return 0; |
271 | } | ||
272 | |||
273 | static 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 | ||
722 | static 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 | |||
664 | int mthca_QUERY_FW(struct mthca_dev *dev, u8 *status) | 748 | int 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 | ||
1625 | int 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 | |||
1517 | int mthca_SW2HW_SRQ(struct mthca_dev *dev, struct mthca_mailbox *mailbox, | 1656 | int 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 | ||
1671 | int 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 | |||
1532 | int mthca_ARM_SRQ(struct mthca_dev *dev, int srq_num, int limit, u8 *status) | 1678 | int 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 | ||
1538 | int mthca_MODIFY_QP(struct mthca_dev *dev, int trans, u32 num, | 1684 | int 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 | } |