diff options
Diffstat (limited to 'drivers/infiniband/hw/cxgb3/iwch_mem.c')
-rw-r--r-- | drivers/infiniband/hw/cxgb3/iwch_mem.c | 172 |
1 files changed, 172 insertions, 0 deletions
diff --git a/drivers/infiniband/hw/cxgb3/iwch_mem.c b/drivers/infiniband/hw/cxgb3/iwch_mem.c new file mode 100644 index 000000000000..2b6cd53bb3fc --- /dev/null +++ b/drivers/infiniband/hw/cxgb3/iwch_mem.c | |||
@@ -0,0 +1,172 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2006 Chelsio, Inc. All rights reserved. | ||
3 | * Copyright (c) 2006 Open Grid Computing, Inc. All rights reserved. | ||
4 | * | ||
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: | ||
10 | * | ||
11 | * Redistribution and use in source and binary forms, with or | ||
12 | * without modification, are permitted provided that the following | ||
13 | * conditions are met: | ||
14 | * | ||
15 | * - Redistributions of source code must retain the above | ||
16 | * copyright notice, this list of conditions and the following | ||
17 | * disclaimer. | ||
18 | * | ||
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. | ||
23 | * | ||
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 | ||
31 | * SOFTWARE. | ||
32 | */ | ||
33 | #include <asm/byteorder.h> | ||
34 | |||
35 | #include <rdma/iw_cm.h> | ||
36 | #include <rdma/ib_verbs.h> | ||
37 | |||
38 | #include "cxio_hal.h" | ||
39 | #include "iwch.h" | ||
40 | #include "iwch_provider.h" | ||
41 | |||
42 | int iwch_register_mem(struct iwch_dev *rhp, struct iwch_pd *php, | ||
43 | struct iwch_mr *mhp, | ||
44 | int shift, | ||
45 | __be64 *page_list) | ||
46 | { | ||
47 | u32 stag; | ||
48 | u32 mmid; | ||
49 | |||
50 | |||
51 | if (cxio_register_phys_mem(&rhp->rdev, | ||
52 | &stag, mhp->attr.pdid, | ||
53 | mhp->attr.perms, | ||
54 | mhp->attr.zbva, | ||
55 | mhp->attr.va_fbo, | ||
56 | mhp->attr.len, | ||
57 | shift-12, | ||
58 | page_list, | ||
59 | &mhp->attr.pbl_size, &mhp->attr.pbl_addr)) | ||
60 | return -ENOMEM; | ||
61 | mhp->attr.state = 1; | ||
62 | mhp->attr.stag = stag; | ||
63 | mmid = stag >> 8; | ||
64 | mhp->ibmr.rkey = mhp->ibmr.lkey = stag; | ||
65 | insert_handle(rhp, &rhp->mmidr, mhp, mmid); | ||
66 | PDBG("%s mmid 0x%x mhp %p\n", __FUNCTION__, mmid, mhp); | ||
67 | return 0; | ||
68 | } | ||
69 | |||
70 | int iwch_reregister_mem(struct iwch_dev *rhp, struct iwch_pd *php, | ||
71 | struct iwch_mr *mhp, | ||
72 | int shift, | ||
73 | __be64 *page_list, | ||
74 | int npages) | ||
75 | { | ||
76 | u32 stag; | ||
77 | u32 mmid; | ||
78 | |||
79 | |||
80 | /* We could support this... */ | ||
81 | if (npages > mhp->attr.pbl_size) | ||
82 | return -ENOMEM; | ||
83 | |||
84 | stag = mhp->attr.stag; | ||
85 | if (cxio_reregister_phys_mem(&rhp->rdev, | ||
86 | &stag, mhp->attr.pdid, | ||
87 | mhp->attr.perms, | ||
88 | mhp->attr.zbva, | ||
89 | mhp->attr.va_fbo, | ||
90 | mhp->attr.len, | ||
91 | shift-12, | ||
92 | page_list, | ||
93 | &mhp->attr.pbl_size, &mhp->attr.pbl_addr)) | ||
94 | return -ENOMEM; | ||
95 | mhp->attr.state = 1; | ||
96 | mhp->attr.stag = stag; | ||
97 | mmid = stag >> 8; | ||
98 | mhp->ibmr.rkey = mhp->ibmr.lkey = stag; | ||
99 | insert_handle(rhp, &rhp->mmidr, mhp, mmid); | ||
100 | PDBG("%s mmid 0x%x mhp %p\n", __FUNCTION__, mmid, mhp); | ||
101 | return 0; | ||
102 | } | ||
103 | |||
104 | int build_phys_page_list(struct ib_phys_buf *buffer_list, | ||
105 | int num_phys_buf, | ||
106 | u64 *iova_start, | ||
107 | u64 *total_size, | ||
108 | int *npages, | ||
109 | int *shift, | ||
110 | __be64 **page_list) | ||
111 | { | ||
112 | u64 mask; | ||
113 | int i, j, n; | ||
114 | |||
115 | mask = 0; | ||
116 | *total_size = 0; | ||
117 | for (i = 0; i < num_phys_buf; ++i) { | ||
118 | if (i != 0 && buffer_list[i].addr & ~PAGE_MASK) | ||
119 | return -EINVAL; | ||
120 | if (i != 0 && i != num_phys_buf - 1 && | ||
121 | (buffer_list[i].size & ~PAGE_MASK)) | ||
122 | return -EINVAL; | ||
123 | *total_size += buffer_list[i].size; | ||
124 | if (i > 0) | ||
125 | mask |= buffer_list[i].addr; | ||
126 | } | ||
127 | |||
128 | if (*total_size > 0xFFFFFFFFULL) | ||
129 | return -ENOMEM; | ||
130 | |||
131 | /* Find largest page shift we can use to cover buffers */ | ||
132 | for (*shift = PAGE_SHIFT; *shift < 27; ++(*shift)) | ||
133 | if (num_phys_buf > 1) { | ||
134 | if ((1ULL << *shift) & mask) | ||
135 | break; | ||
136 | } else | ||
137 | if (1ULL << *shift >= | ||
138 | buffer_list[0].size + | ||
139 | (buffer_list[0].addr & ((1ULL << *shift) - 1))) | ||
140 | break; | ||
141 | |||
142 | buffer_list[0].size += buffer_list[0].addr & ((1ULL << *shift) - 1); | ||
143 | buffer_list[0].addr &= ~0ull << *shift; | ||
144 | |||
145 | *npages = 0; | ||
146 | for (i = 0; i < num_phys_buf; ++i) | ||
147 | *npages += (buffer_list[i].size + | ||
148 | (1ULL << *shift) - 1) >> *shift; | ||
149 | |||
150 | if (!*npages) | ||
151 | return -EINVAL; | ||
152 | |||
153 | *page_list = kmalloc(sizeof(u64) * *npages, GFP_KERNEL); | ||
154 | if (!*page_list) | ||
155 | return -ENOMEM; | ||
156 | |||
157 | n = 0; | ||
158 | for (i = 0; i < num_phys_buf; ++i) | ||
159 | for (j = 0; | ||
160 | j < (buffer_list[i].size + (1ULL << *shift) - 1) >> *shift; | ||
161 | ++j) | ||
162 | (*page_list)[n++] = cpu_to_be64(buffer_list[i].addr + | ||
163 | ((u64) j << *shift)); | ||
164 | |||
165 | PDBG("%s va 0x%llx mask 0x%llx shift %d len %lld pbl_size %d\n", | ||
166 | __FUNCTION__, (unsigned long long) *iova_start, | ||
167 | (unsigned long long) mask, *shift, (unsigned long long) *total_size, | ||
168 | *npages); | ||
169 | |||
170 | return 0; | ||
171 | |||
172 | } | ||