2 * Copyright (c) 2004 Topspin Communications. All rights reserved.
3 * Copyright (c) 2005 Mellanox Technologies. All rights reserved.
5 * This software is available to you under a choice of one of two
6 * licenses. You may choose to be licensed under the terms of the GNU
7 * General Public License (GPL) Version 2, available from the file
8 * COPYING in the main directory of this source tree, or the
9 * OpenIB.org BSD license below:
11 * Redistribution and use in source and binary forms, with or
12 * without modification, are permitted provided that the following
15 * - Redistributions of source code must retain the above
16 * copyright notice, this list of conditions and the following
19 * - Redistributions in binary form must reproduce the above
20 * copyright notice, this list of conditions and the following
21 * disclaimer in the documentation and/or other materials
22 * provided with the distribution.
24 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
25 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
26 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
27 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
28 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
29 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
30 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
33 * $Id: mthca_mr.c 2905 2005-07-25 18:26:52Z roland $
36 #include "mthca_dev.h"
37 #if defined(EVENT_TRACING)
41 #include "mthca_mr.tmh"
43 #include "mthca_cmd.h"
44 #include "mthca_memfree.h"
46 static int mthca_buddy_init(struct mthca_buddy *buddy, int max_order);
47 static void mthca_buddy_cleanup(struct mthca_buddy *buddy);
50 #pragma alloc_text (PAGE, mthca_buddy_init)
51 #pragma alloc_text (PAGE, mthca_buddy_cleanup)
52 #pragma alloc_text (PAGE, mthca_init_mr_table)
53 #pragma alloc_text (PAGE, mthca_cleanup_mr_table)
57 struct mthca_buddy *buddy;
63 * Must be packed because mtt_seg is 64 bits but only aligned to 32 bits.
66 struct mthca_mpt_entry {
75 __be32 window_count_limit;
77 __be32 mtt_sz; /* Arbel only */
82 #define MTHCA_MPT_FLAG_SW_OWNS (0xfUL << 28)
83 #define MTHCA_MPT_FLAG_MIO (1 << 17)
84 #define MTHCA_MPT_FLAG_BIND_ENABLE (1 << 15)
85 #define MTHCA_MPT_FLAG_PHYSICAL (1 << 9)
86 #define MTHCA_MPT_FLAG_REGION (1 << 8)
88 #define MTHCA_MTT_FLAG_PRESENT 1
90 #define MTHCA_MPT_STATUS_SW 0xF0
91 #define MTHCA_MPT_STATUS_HW 0x00
93 #define SINAI_FMR_KEY_INC 0x1000000
95 static void dump_mtt(u32 print_lvl, __be64 *mtt_entry ,int list_len)
98 UNREFERENCED_PARAMETER(mtt_entry); // for release version
99 HCA_PRINT(print_lvl ,HCA_DBG_MEMORY ,("Dumping MTT entry len %d :\n",list_len));
100 for (i = 0; i < list_len && i < MTHCA_MAILBOX_SIZE / 8 - 2; i=i+4) {
101 HCA_PRINT(print_lvl ,HCA_DBG_MEMORY ,("[%02x] %016I64x %016I64x %016I64x %016I64x\n",i,
102 cl_ntoh64(mtt_entry[i]),
103 cl_ntoh64(mtt_entry[i+1]),
104 cl_ntoh64(mtt_entry[i+2]),
105 cl_ntoh64(mtt_entry[i+3])));
110 static void dump_mpt(u32 print_lvl, struct mthca_mpt_entry *mpt_entry )
113 UNREFERENCED_PARAMETER(mpt_entry); // for release version
114 HCA_PRINT(print_lvl ,HCA_DBG_MEMORY ,("Dumping MPT entry %08x :\n", mpt_entry->key));
115 for (i = 0; i < sizeof (struct mthca_mpt_entry) / 4; i=i+4) {
116 HCA_PRINT(print_lvl ,HCA_DBG_MEMORY ,("[%02x] %08x %08x %08x %08x \n",i,
117 cl_ntoh32(((__be32 *) mpt_entry)[i]),
118 cl_ntoh32(((__be32 *) mpt_entry)[i+1]),
119 cl_ntoh32(((__be32 *) mpt_entry)[i+2]),
120 cl_ntoh32(((__be32 *) mpt_entry)[i+3])));
132 * Buddy allocator for MTT segments (currently not very efficient
133 * since it doesn't keep a free list and just searches linearly
134 * through the bitmaps)
137 static u32 mthca_buddy_alloc(struct mthca_buddy *buddy, int order)
144 spin_lock(&buddy->lock, &lh);
146 for (o = order; o <= buddy->max_order; ++o) {
147 m = 1 << (buddy->max_order - o);
148 seg = find_first_bit(buddy->bits[o], m);
157 clear_bit(seg, (long*)buddy->bits[o]);
162 set_bit(seg ^ 1, (long*)buddy->bits[o]);
172 static void mthca_buddy_free(struct mthca_buddy *buddy, u32 seg, int order)
178 spin_lock(&buddy->lock, &lh);
180 while (test_bit(seg ^ 1, buddy->bits[order])) {
181 clear_bit(seg ^ 1, (long*)buddy->bits[order]);
186 set_bit(seg, (long*)buddy->bits[order]);
191 static int mthca_buddy_init(struct mthca_buddy *buddy, int max_order)
195 buddy->max_order = max_order;
196 spin_lock_init(&buddy->lock);
198 buddy->bits = kmalloc((buddy->max_order + 1) * sizeof (long *),
203 RtlZeroMemory(buddy->bits, (buddy->max_order + 1) * sizeof (long *));
205 for (i = 0; i <= buddy->max_order; ++i) {
206 s = BITS_TO_LONGS(1 << (buddy->max_order - i));
207 buddy->bits[i] = kmalloc(s * sizeof (long), GFP_KERNEL);
210 bitmap_zero(buddy->bits[i],
211 1 << (buddy->max_order - i));
214 set_bit(0, (long*)buddy->bits[buddy->max_order]);
219 for (i = 0; i <= buddy->max_order; ++i)
220 kfree(buddy->bits[i]);
228 static void mthca_buddy_cleanup(struct mthca_buddy *buddy)
232 for (i = 0; i <= buddy->max_order; ++i)
233 kfree(buddy->bits[i]);
238 static u32 mthca_alloc_mtt_range(struct mthca_dev *dev, int order,
239 struct mthca_buddy *buddy)
241 u32 seg = mthca_buddy_alloc(buddy, order);
246 if (mthca_is_memfree(dev))
247 if (mthca_table_get_range(dev, dev->mr_table.mtt_table, seg,
248 seg + (1 << order) - 1)) {
249 mthca_buddy_free(buddy, seg, order);
256 static struct mthca_mtt *__mthca_alloc_mtt(struct mthca_dev *dev, int size,
257 struct mthca_buddy *buddy)
259 struct mthca_mtt *mtt;
261 HCA_ENTER(HCA_DBG_MEMORY);
263 return ERR_PTR(-EINVAL);
265 mtt = kmalloc(sizeof *mtt, GFP_KERNEL);
267 return ERR_PTR(-ENOMEM);
271 for (i = MTHCA_MTT_SEG_SIZE / 8; i < size; i <<= 1)
274 mtt->first_seg = mthca_alloc_mtt_range(dev, mtt->order, buddy);
275 if (mtt->first_seg == -1) {
277 return ERR_PTR(-ENOMEM);
279 HCA_EXIT(HCA_DBG_MEMORY);
283 struct mthca_mtt *mthca_alloc_mtt(struct mthca_dev *dev, int size)
285 return __mthca_alloc_mtt(dev, size, &dev->mr_table.mtt_buddy);
288 void mthca_free_mtt(struct mthca_dev *dev, struct mthca_mtt *mtt)
293 mthca_buddy_free(mtt->buddy, mtt->first_seg, mtt->order);
295 mthca_table_put_range(dev, dev->mr_table.mtt_table,
297 mtt->first_seg + (1 << mtt->order) - 1);
302 int mthca_write_mtt(struct mthca_dev *dev, struct mthca_mtt *mtt,
303 int start_index, u64 *buffer_list, int list_len)
305 struct mthca_mailbox *mailbox;
312 mailbox = mthca_alloc_mailbox(dev, GFP_KERNEL);
314 return PTR_ERR(mailbox);
315 mtt_entry = mailbox->buf;
317 while (list_len > 0) {
318 val = dev->mr_table.mtt_base +
319 mtt->first_seg * MTHCA_MTT_SEG_SIZE + start_index * 8;
320 //TODO: a workaround of bug in _byteswap_uint64
321 // in release version optimizer puts the above expression into the function call and generates incorrect code
322 // so we call the macro to work around that
323 mtt_entry[0] = CL_HTON64(val);
325 for (i = 0; i < list_len && i < MTHCA_MAILBOX_SIZE / 8 - 2; ++i) {
326 val = buffer_list[i];
327 // BUG in compiler: it can't perform OR on u64 !!! We perform OR on the low dword
328 *(PULONG)&val |= MTHCA_MTT_FLAG_PRESENT;
329 mtt_entry[i + 2] = cl_hton64(val);
333 * If we have an odd number of entries to write, add
334 * one more dummy entry for firmware efficiency.
337 mtt_entry[i + 2] = 0;
339 dump_mtt(TRACE_LEVEL_VERBOSE, mtt_entry ,i);
341 err = mthca_WRITE_MTT(dev, mailbox, (i + 1) & ~1, &status);
343 HCA_PRINT(TRACE_LEVEL_WARNING ,HCA_DBG_MEMORY ,("WRITE_MTT failed (%d)\n", err));
347 HCA_PRINT(TRACE_LEVEL_WARNING,HCA_DBG_MEMORY,("WRITE_MTT returned status 0x%02x\n",
359 mthca_free_mailbox(dev, mailbox);
363 static inline u32 tavor_hw_index_to_key(u32 ind)
368 static inline u32 tavor_key_to_hw_index(u32 key)
373 static inline u32 arbel_hw_index_to_key(u32 ind)
375 return (ind >> 24) | (ind << 8);
378 static inline u32 arbel_key_to_hw_index(u32 key)
380 return (key << 24) | (key >> 8);
383 static inline u32 hw_index_to_key(struct mthca_dev *dev, u32 ind)
385 if (mthca_is_memfree(dev))
386 return arbel_hw_index_to_key(ind);
388 return tavor_hw_index_to_key(ind);
391 static inline u32 key_to_hw_index(struct mthca_dev *dev, u32 key)
393 if (mthca_is_memfree(dev))
394 return arbel_key_to_hw_index(key);
396 return tavor_key_to_hw_index(key);
400 static inline u32 adjust_key(struct mthca_dev *dev, u32 key)
402 if (dev->mthca_flags & MTHCA_FLAG_SINAI_OPT)
403 return ((key << 20) & 0x800000) | (key & 0x7fffff);
408 int mthca_mr_alloc(struct mthca_dev *dev, u32 pd, int buffer_size_shift,
409 u64 iova, u64 total_size, mthca_mpt_access_t access, struct mthca_mr *mr)
411 struct mthca_mailbox *mailbox;
412 struct mthca_mpt_entry *mpt_entry;
418 WARN_ON(buffer_size_shift >= 32);
420 key = mthca_alloc(&dev->mr_table.mpt_alloc);
423 mr->ibmr.rkey = mr->ibmr.lkey = hw_index_to_key(dev, key);
425 if (mthca_is_memfree(dev)) {
426 err = mthca_table_get(dev, dev->mr_table.mpt_table, key);
428 goto err_out_mpt_free;
431 mailbox = mthca_alloc_mailbox(dev, GFP_KERNEL);
432 if (IS_ERR(mailbox)) {
433 err = PTR_ERR(mailbox);
436 mpt_entry = mailbox->buf;
438 mpt_entry->flags = cl_hton32(MTHCA_MPT_FLAG_SW_OWNS |
440 MTHCA_MPT_FLAG_REGION |
443 mpt_entry->flags |= cl_hton32(MTHCA_MPT_FLAG_PHYSICAL);
445 mpt_entry->page_size = cl_hton32(buffer_size_shift - 12);
446 mpt_entry->key = cl_hton32(key);
447 mpt_entry->pd = cl_hton32(pd);
448 mpt_entry->start = cl_hton64(iova);
449 mpt_entry->length = cl_hton64(total_size);
451 RtlZeroMemory(&mpt_entry->lkey,
452 sizeof *mpt_entry - offsetof(struct mthca_mpt_entry, lkey));
456 CPU_2_BE64(dev->mr_table.mtt_base +
457 mr->mtt->first_seg * MTHCA_MTT_SEG_SIZE);
460 dump_mpt(TRACE_LEVEL_VERBOSE, mpt_entry);
463 err = mthca_SW2HW_MPT(dev, mailbox,
464 key & (dev->limits.num_mpts - 1),
467 HCA_PRINT(TRACE_LEVEL_WARNING ,HCA_DBG_MEMORY ,("SW2HW_MPT failed (%d)\n", err));
468 goto err_out_mailbox;
470 HCA_PRINT(TRACE_LEVEL_WARNING,HCA_DBG_MEMORY,("SW2HW_MPT returned status 0x%02x\n",
473 goto err_out_mailbox;
476 mthca_free_mailbox(dev, mailbox);
480 mthca_free_mailbox(dev, mailbox);
483 mthca_table_put(dev, dev->mr_table.mpt_table, key);
486 mthca_free(&dev->mr_table.mpt_alloc, key);
490 int mthca_mr_alloc_notrans(struct mthca_dev *dev, u32 pd,
491 mthca_mpt_access_t access, struct mthca_mr *mr)
494 return mthca_mr_alloc(dev, pd, 12, 0, ~0Ui64, access, mr);
497 int mthca_mr_alloc_phys(struct mthca_dev *dev, u32 pd,
498 u64 *buffer_list, int buffer_size_shift,
499 int list_len, u64 iova, u64 total_size,
500 mthca_mpt_access_t access, struct mthca_mr *mr)
503 HCA_ENTER(HCA_DBG_MEMORY);
504 mr->mtt = mthca_alloc_mtt(dev, list_len);
505 if (IS_ERR(mr->mtt)){
506 err= PTR_ERR(mr->mtt);
510 err = mthca_write_mtt(dev, mr->mtt, 0, buffer_list, list_len);
512 mthca_free_mtt(dev, mr->mtt);
516 err = mthca_mr_alloc(dev, pd, buffer_size_shift, iova,
517 total_size, access, mr);
519 mthca_free_mtt(dev, mr->mtt);
522 HCA_EXIT(HCA_DBG_MEMORY);
527 static void mthca_free_region(struct mthca_dev *dev, u32 lkey)
529 mthca_table_put(dev, dev->mr_table.mpt_table, key_to_hw_index(dev, lkey));
530 mthca_free(&dev->mr_table.mpt_alloc, key_to_hw_index(dev, lkey));
533 void mthca_free_mr(struct mthca_dev *dev, struct mthca_mr *mr)
538 err = mthca_HW2SW_MPT(dev, NULL,
539 key_to_hw_index(dev, mr->ibmr.lkey) &
540 (dev->limits.num_mpts - 1),
543 HCA_PRINT(TRACE_LEVEL_WARNING ,HCA_DBG_MEMORY ,("HW2SW_MPT failed (%d)\n", err));
545 HCA_PRINT(TRACE_LEVEL_WARNING,HCA_DBG_MEMORY,("HW2SW_MPT returned status 0x%02x\n",
549 mthca_free_region(dev, mr->ibmr.lkey);
550 mthca_free_mtt(dev, mr->mtt);
553 int mthca_fmr_alloc(struct mthca_dev *dev, u32 pd,
554 mthca_mpt_access_t access, struct mthca_fmr *mr)
556 struct mthca_mpt_entry *mpt_entry;
557 struct mthca_mailbox *mailbox;
561 int list_len = mr->attr.max_pages;
566 if (mr->attr.page_shift < 12 || mr->attr.page_shift >= 32)
569 /* For Arbel, all MTTs must fit in the same page. */
570 if (mthca_is_memfree(dev) &&
571 mr->attr.max_pages * sizeof *mr->mem.arbel.mtts > PAGE_SIZE)
576 key = mthca_alloc(&dev->mr_table.mpt_alloc);
579 key = adjust_key(dev, key);
581 idx = key & (dev->limits.num_mpts - 1);
582 mr->ibmr.rkey = mr->ibmr.lkey = hw_index_to_key(dev, key);
584 if (mthca_is_memfree(dev)) {
585 err = mthca_table_get(dev, dev->mr_table.mpt_table, key);
587 goto err_out_mpt_free;
589 mr->mem.arbel.mpt = mthca_table_find(dev->mr_table.mpt_table, key);
590 BUG_ON(!mr->mem.arbel.mpt);
592 mr->mem.tavor.mpt = (struct mthca_mpt_entry*)((u8*)dev->mr_table.tavor_fmr.mpt_base +
593 sizeof *(mr->mem.tavor.mpt) * idx);
595 mr->mtt = __mthca_alloc_mtt(dev, list_len, dev->mr_table.fmr_mtt_buddy);
599 mtt_seg = mr->mtt->first_seg * MTHCA_MTT_SEG_SIZE;
601 if (mthca_is_memfree(dev)) {
602 mr->mem.arbel.mtts = mthca_table_find(dev->mr_table.mtt_table,
604 BUG_ON(!mr->mem.arbel.mtts);
606 mr->mem.tavor.mtts = (u64*)((u8*)dev->mr_table.tavor_fmr.mtt_base + mtt_seg);
608 mailbox = mthca_alloc_mailbox(dev, GFP_KERNEL);
610 goto err_out_free_mtt;
612 mpt_entry = mailbox->buf;
614 mpt_entry->flags = cl_hton32(MTHCA_MPT_FLAG_SW_OWNS |
616 MTHCA_MPT_FLAG_REGION |
619 mpt_entry->page_size = cl_hton32(mr->attr.page_shift - 12);
620 mpt_entry->key = cl_hton32(key);
621 mpt_entry->pd = cl_hton32(pd);
622 RtlZeroMemory(&mpt_entry->start,
623 sizeof *mpt_entry - offsetof(struct mthca_mpt_entry, start));
624 mpt_entry->mtt_seg = CPU_2_BE64(dev->mr_table.mtt_base + mtt_seg);
627 HCA_PRINT(TRACE_LEVEL_INFORMATION ,HCA_DBG_MEMORY ,("Dumping MPT entry %08x:\n", mr->ibmr.lkey));
628 for (i = 0; i < sizeof (struct mthca_mpt_entry) / 4; i=i+4) {
629 HCA_PRINT(TRACE_LEVEL_INFORMATION ,HCA_DBG_MEMORY ,("[%02x] %08x %08x %08x %08x \n",i,
630 cl_ntoh32(((__be32 *) mpt_entry)[i]),
631 cl_ntoh32(((__be32 *) mpt_entry)[i+1]),
632 cl_ntoh32(((__be32 *) mpt_entry)[i+2]),
633 cl_ntoh32(((__be32 *) mpt_entry)[i+3])));
637 err = mthca_SW2HW_MPT(dev, mailbox,
638 key & (dev->limits.num_mpts - 1),
642 HCA_PRINT(TRACE_LEVEL_WARNING ,HCA_DBG_MEMORY ,("SW2HW_MPT failed (%d)\n", err));
643 goto err_out_mailbox_free;
646 HCA_PRINT(TRACE_LEVEL_WARNING,HCA_DBG_MEMORY,("SW2HW_MPT returned status 0x%02x\n",
649 goto err_out_mailbox_free;
652 mthca_free_mailbox(dev, mailbox);
655 err_out_mailbox_free:
656 mthca_free_mailbox(dev, mailbox);
659 mthca_free_mtt(dev, mr->mtt);
662 mthca_table_put(dev, dev->mr_table.mpt_table, key);
665 mthca_free(&dev->mr_table.mpt_alloc, mr->ibmr.lkey);
670 int mthca_free_fmr(struct mthca_dev *dev, struct mthca_fmr *fmr)
675 mthca_free_region(dev, fmr->ibmr.lkey);
676 mthca_free_mtt(dev, fmr->mtt);
682 static inline int mthca_check_fmr(struct mthca_fmr *fmr, u64 *page_list,
683 int list_len, u64 iova)
686 UNREFERENCED_PARAMETER(page_list);
688 if (list_len > fmr->attr.max_pages)
691 page_mask = (1 << fmr->attr.page_shift) - 1;
693 /* We are getting page lists, so va must be page aligned. */
694 if (iova & page_mask)
697 /* Trust the user not to pass misaligned data in page_list */
699 for (i = 0; i < list_len; ++i) {
700 if (page_list[i] & ~page_mask)
705 if (fmr->maps >= fmr->attr.max_maps)
712 int mthca_tavor_map_phys_fmr(struct ib_fmr *ibfmr, u64 *page_list,
713 int list_len, u64 iova)
715 struct mthca_fmr *fmr = to_mfmr(ibfmr);
716 struct mthca_dev *dev = to_mdev(ibfmr->device);
717 struct mthca_mpt_entry mpt_entry;
722 err = mthca_check_fmr(fmr, page_list, list_len, iova);
728 key = tavor_key_to_hw_index(fmr->ibmr.lkey);
729 key += dev->limits.num_mpts;
730 fmr->ibmr.lkey = fmr->ibmr.rkey = tavor_hw_index_to_key(key);
732 writeb(MTHCA_MPT_STATUS_SW, fmr->mem.tavor.mpt);
734 for (i = 0; i < list_len; ++i) {
736 u64 val = page_list[i];
737 // BUG in compiler: it can't perform OR on u64 !!! We perform OR on the low dword
738 *(PULONG)&val |= MTHCA_MTT_FLAG_PRESENT;
739 mtt_entry = cl_hton64(val);
740 mthca_write64_raw(mtt_entry, fmr->mem.tavor.mtts + i);
743 mpt_entry.lkey = cl_hton32(key);
744 mpt_entry.length = CPU_2_BE64(list_len * (1Ui64 << fmr->attr.page_shift));
745 mpt_entry.start = cl_hton64(iova);
747 __raw_writel((u32) mpt_entry.lkey, &fmr->mem.tavor.mpt->key);
748 memcpy_toio(&fmr->mem.tavor.mpt->start, &mpt_entry.start,
749 offsetof(struct mthca_mpt_entry, window_count) -
750 offsetof(struct mthca_mpt_entry, start));
752 writeb(MTHCA_MPT_STATUS_HW, fmr->mem.tavor.mpt);
757 int mthca_arbel_map_phys_fmr(struct ib_fmr *ibfmr, u64 *page_list,
758 int list_len, u64 iova)
760 struct mthca_fmr *fmr = to_mfmr(ibfmr);
761 struct mthca_dev *dev = to_mdev(ibfmr->device);
766 err = mthca_check_fmr(fmr, page_list, list_len, iova);
772 key = arbel_key_to_hw_index(fmr->ibmr.lkey);
773 if (dev->mthca_flags & MTHCA_FLAG_SINAI_OPT)
774 key += SINAI_FMR_KEY_INC;
776 key += dev->limits.num_mpts;
777 fmr->ibmr.lkey = fmr->ibmr.rkey = arbel_hw_index_to_key(key);
779 *(u8 *) fmr->mem.arbel.mpt = MTHCA_MPT_STATUS_SW;
783 for (i = 0; i < list_len; ++i) {
784 // BUG in compiler: it can't perform OR on u64 !!! We perform OR on the low dword
785 u64 val = page_list[i];
786 *(PULONG)&val |= MTHCA_MTT_FLAG_PRESENT;
787 fmr->mem.arbel.mtts[i] = cl_hton64(val);
790 fmr->mem.arbel.mpt->key = cl_hton32(key);
791 fmr->mem.arbel.mpt->lkey = cl_hton32(key);
792 fmr->mem.arbel.mpt->length = CPU_2_BE64(list_len * (1Ui64 << fmr->attr.page_shift));
793 fmr->mem.arbel.mpt->start = cl_hton64(iova);
797 *(u8 *) fmr->mem.arbel.mpt = MTHCA_MPT_STATUS_HW;
805 void mthca_tavor_fmr_unmap(struct mthca_dev *dev, struct mthca_fmr *fmr)
812 key = tavor_key_to_hw_index(fmr->ibmr.lkey);
813 key &= dev->limits.num_mpts - 1;
814 fmr->ibmr.lkey = fmr->ibmr.rkey = tavor_hw_index_to_key(key);
818 writeb(MTHCA_MPT_STATUS_SW, fmr->mem.tavor.mpt);
822 void mthca_arbel_fmr_unmap(struct mthca_dev *dev, struct mthca_fmr *fmr)
829 key = arbel_key_to_hw_index(fmr->ibmr.lkey);
830 key &= dev->limits.num_mpts - 1;
831 fmr->ibmr.lkey = fmr->ibmr.rkey = arbel_hw_index_to_key(key);
835 *(u8 *) fmr->mem.arbel.mpt = MTHCA_MPT_STATUS_SW;
838 int mthca_init_mr_table(struct mthca_dev *dev)
842 err = mthca_alloc_init(&dev->mr_table.mpt_alloc,
843 (u32)dev->limits.num_mpts,
844 (u32)~0, (u32)dev->limits.reserved_mrws);
848 if (!mthca_is_memfree(dev) &&
849 (dev->mthca_flags & MTHCA_FLAG_DDR_HIDDEN))
850 dev->limits.fmr_reserved_mtts = 0;
852 dev->mthca_flags |= MTHCA_FLAG_FMR;
854 if (dev->mthca_flags & MTHCA_FLAG_SINAI_OPT)
855 HCA_PRINT(TRACE_LEVEL_INFORMATION ,HCA_DBG_MEMORY ,("Memory key throughput optimization activated.\n"));
857 err = mthca_buddy_init(&dev->mr_table.mtt_buddy,
858 fls(dev->limits.num_mtt_segs - 1));
863 dev->mr_table.tavor_fmr.mpt_base = NULL;
864 dev->mr_table.tavor_fmr.mtt_base = NULL;
866 if (dev->limits.fmr_reserved_mtts) {
867 i = fls(dev->limits.fmr_reserved_mtts - 1);
870 HCA_PRINT(TRACE_LEVEL_WARNING ,HCA_DBG_MEMORY ,("Unable to reserve 2^31 FMR MTTs.\n"));
875 dev->mr_table.tavor_fmr.mpt_base =
876 ioremap(dev->mr_table.mpt_base,
877 (1 << i) * sizeof (struct mthca_mpt_entry),
878 &dev->mr_table.tavor_fmr.mpt_base_size);
880 if (!dev->mr_table.tavor_fmr.mpt_base) {
881 HCA_PRINT(TRACE_LEVEL_WARNING ,HCA_DBG_MEMORY ,("MPT ioremap for FMR failed.\n"));
886 dev->mr_table.tavor_fmr.mtt_base =
887 ioremap(dev->mr_table.mtt_base,
888 (1 << i) * MTHCA_MTT_SEG_SIZE,
889 &dev->mr_table.tavor_fmr.mtt_base_size );
891 if (!dev->mr_table.tavor_fmr.mtt_base) {
892 HCA_PRINT(TRACE_LEVEL_WARNING ,HCA_DBG_MEMORY ,("MTT ioremap for FMR failed.\n"));
897 err = mthca_buddy_init(&dev->mr_table.tavor_fmr.mtt_buddy, i);
899 goto err_fmr_mtt_buddy;
901 /* Prevent regular MRs from using FMR keys */
902 err = mthca_buddy_alloc(&dev->mr_table.mtt_buddy, i);
904 goto err_reserve_fmr;
906 dev->mr_table.fmr_mtt_buddy =
907 &dev->mr_table.tavor_fmr.mtt_buddy;
909 dev->mr_table.fmr_mtt_buddy = &dev->mr_table.mtt_buddy;
911 /* FMR table is always the first, take reserved MTTs out of there */
912 if (dev->limits.reserved_mtts) {
913 i = fls(dev->limits.reserved_mtts - 1);
915 if (mthca_alloc_mtt_range(dev, i,
916 dev->mr_table.fmr_mtt_buddy) == -1) {
917 HCA_PRINT(TRACE_LEVEL_WARNING,HCA_DBG_MEMORY,("MTT table of order %d is too small.\n",
918 dev->mr_table.fmr_mtt_buddy->max_order));
920 goto err_reserve_mtts;
928 if (dev->limits.fmr_reserved_mtts)
929 mthca_buddy_cleanup(&dev->mr_table.tavor_fmr.mtt_buddy);
932 if (dev->mr_table.tavor_fmr.mtt_base)
933 iounmap(dev->mr_table.tavor_fmr.mtt_base,
934 dev->mr_table.tavor_fmr.mtt_base_size);
937 if (dev->mr_table.tavor_fmr.mpt_base)
938 iounmap(dev->mr_table.tavor_fmr.mpt_base,
939 dev->mr_table.tavor_fmr.mpt_base_size);
942 mthca_buddy_cleanup(&dev->mr_table.mtt_buddy);
945 mthca_alloc_cleanup(&dev->mr_table.mpt_alloc);
950 void mthca_cleanup_mr_table(struct mthca_dev *dev)
952 /* XXX check if any MRs are still allocated? */
953 if (dev->limits.fmr_reserved_mtts)
954 mthca_buddy_cleanup(&dev->mr_table.tavor_fmr.mtt_buddy);
956 mthca_buddy_cleanup(&dev->mr_table.mtt_buddy);
958 if (dev->mr_table.tavor_fmr.mtt_base)
959 iounmap(dev->mr_table.tavor_fmr.mtt_base,
960 dev->mr_table.tavor_fmr.mtt_base_size);
961 if (dev->mr_table.tavor_fmr.mpt_base)
962 iounmap(dev->mr_table.tavor_fmr.mpt_base,
963 dev->mr_table.tavor_fmr.mpt_base_size);
965 mthca_alloc_cleanup(&dev->mr_table.mpt_alloc);