aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/infiniband
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/infiniband')
-rw-r--r--drivers/infiniband/hw/mthca/mthca_main.c2
-rw-r--r--drivers/infiniband/hw/mthca/mthca_memfree.c32
-rw-r--r--drivers/infiniband/hw/mthca/mthca_memfree.h4
-rw-r--r--drivers/infiniband/hw/mthca/mthca_mr.c79
4 files changed, 105 insertions, 12 deletions
diff --git a/drivers/infiniband/hw/mthca/mthca_main.c b/drivers/infiniband/hw/mthca/mthca_main.c
index 9e782bc1c38d..8bd2e3af016d 100644
--- a/drivers/infiniband/hw/mthca/mthca_main.c
+++ b/drivers/infiniband/hw/mthca/mthca_main.c
@@ -390,7 +390,7 @@ static int __devinit mthca_init_icm(struct mthca_dev *mdev,
390 } 390 }
391 391
392 mdev->mr_table.mtt_table = mthca_alloc_icm_table(mdev, init_hca->mtt_base, 392 mdev->mr_table.mtt_table = mthca_alloc_icm_table(mdev, init_hca->mtt_base,
393 init_hca->mtt_seg_sz, 393 dev_lim->mtt_seg_sz,
394 mdev->limits.num_mtt_segs, 394 mdev->limits.num_mtt_segs,
395 mdev->limits.reserved_mtts, 1); 395 mdev->limits.reserved_mtts, 1);
396 if (!mdev->mr_table.mtt_table) { 396 if (!mdev->mr_table.mtt_table) {
diff --git a/drivers/infiniband/hw/mthca/mthca_memfree.c b/drivers/infiniband/hw/mthca/mthca_memfree.c
index 7730b5960616..a70a1c712b4b 100644
--- a/drivers/infiniband/hw/mthca/mthca_memfree.c
+++ b/drivers/infiniband/hw/mthca/mthca_memfree.c
@@ -192,6 +192,38 @@ void mthca_table_put(struct mthca_dev *dev, struct mthca_icm_table *table, int o
192 up(&table->mutex); 192 up(&table->mutex);
193} 193}
194 194
195int mthca_table_get_range(struct mthca_dev *dev, struct mthca_icm_table *table,
196 int start, int end)
197{
198 int inc = MTHCA_TABLE_CHUNK_SIZE / table->obj_size;
199 int i, err;
200
201 for (i = start; i <= end; i += inc) {
202 err = mthca_table_get(dev, table, i);
203 if (err)
204 goto fail;
205 }
206
207 return 0;
208
209fail:
210 while (i > start) {
211 i -= inc;
212 mthca_table_put(dev, table, i);
213 }
214
215 return err;
216}
217
218void mthca_table_put_range(struct mthca_dev *dev, struct mthca_icm_table *table,
219 int start, int end)
220{
221 int i;
222
223 for (i = start; i <= end; i += MTHCA_TABLE_CHUNK_SIZE / table->obj_size)
224 mthca_table_put(dev, table, i);
225}
226
195struct mthca_icm_table *mthca_alloc_icm_table(struct mthca_dev *dev, 227struct mthca_icm_table *mthca_alloc_icm_table(struct mthca_dev *dev,
196 u64 virt, int obj_size, 228 u64 virt, int obj_size,
197 int nobj, int reserved, 229 int nobj, int reserved,
diff --git a/drivers/infiniband/hw/mthca/mthca_memfree.h b/drivers/infiniband/hw/mthca/mthca_memfree.h
index a8fa97e140f5..ef72e430250a 100644
--- a/drivers/infiniband/hw/mthca/mthca_memfree.h
+++ b/drivers/infiniband/hw/mthca/mthca_memfree.h
@@ -85,6 +85,10 @@ struct mthca_icm_table *mthca_alloc_icm_table(struct mthca_dev *dev,
85void mthca_free_icm_table(struct mthca_dev *dev, struct mthca_icm_table *table); 85void mthca_free_icm_table(struct mthca_dev *dev, struct mthca_icm_table *table);
86int mthca_table_get(struct mthca_dev *dev, struct mthca_icm_table *table, int obj); 86int mthca_table_get(struct mthca_dev *dev, struct mthca_icm_table *table, int obj);
87void mthca_table_put(struct mthca_dev *dev, struct mthca_icm_table *table, int obj); 87void mthca_table_put(struct mthca_dev *dev, struct mthca_icm_table *table, int obj);
88int mthca_table_get_range(struct mthca_dev *dev, struct mthca_icm_table *table,
89 int start, int end);
90void mthca_table_put_range(struct mthca_dev *dev, struct mthca_icm_table *table,
91 int start, int end);
88 92
89static inline void mthca_icm_first(struct mthca_icm *icm, 93static inline void mthca_icm_first(struct mthca_icm *icm,
90 struct mthca_icm_iter *iter) 94 struct mthca_icm_iter *iter)
diff --git a/drivers/infiniband/hw/mthca/mthca_mr.c b/drivers/infiniband/hw/mthca/mthca_mr.c
index 80a0cd97881b..5eb6e07f35bb 100644
--- a/drivers/infiniband/hw/mthca/mthca_mr.c
+++ b/drivers/infiniband/hw/mthca/mthca_mr.c
@@ -38,6 +38,7 @@
38 38
39#include "mthca_dev.h" 39#include "mthca_dev.h"
40#include "mthca_cmd.h" 40#include "mthca_cmd.h"
41#include "mthca_memfree.h"
41 42
42/* 43/*
43 * Must be packed because mtt_seg is 64 bits but only aligned to 32 bits. 44 * Must be packed because mtt_seg is 64 bits but only aligned to 32 bits.
@@ -71,7 +72,7 @@ struct mthca_mpt_entry {
71 * through the bitmaps) 72 * through the bitmaps)
72 */ 73 */
73 74
74static u32 mthca_alloc_mtt(struct mthca_dev *dev, int order) 75static u32 __mthca_alloc_mtt(struct mthca_dev *dev, int order)
75{ 76{
76 int o; 77 int o;
77 int m; 78 int m;
@@ -105,7 +106,7 @@ static u32 mthca_alloc_mtt(struct mthca_dev *dev, int order)
105 return seg; 106 return seg;
106} 107}
107 108
108static void mthca_free_mtt(struct mthca_dev *dev, u32 seg, int order) 109static void __mthca_free_mtt(struct mthca_dev *dev, u32 seg, int order)
109{ 110{
110 seg >>= order; 111 seg >>= order;
111 112
@@ -122,6 +123,32 @@ static void mthca_free_mtt(struct mthca_dev *dev, u32 seg, int order)
122 spin_unlock(&dev->mr_table.mpt_alloc.lock); 123 spin_unlock(&dev->mr_table.mpt_alloc.lock);
123} 124}
124 125
126static u32 mthca_alloc_mtt(struct mthca_dev *dev, int order)
127{
128 u32 seg = __mthca_alloc_mtt(dev, order);
129
130 if (seg == -1)
131 return -1;
132
133 if (dev->hca_type == ARBEL_NATIVE)
134 if (mthca_table_get_range(dev, dev->mr_table.mtt_table, seg,
135 seg + (1 << order) - 1)) {
136 __mthca_free_mtt(dev, seg, order);
137 seg = -1;
138 }
139
140 return seg;
141}
142
143static void mthca_free_mtt(struct mthca_dev *dev, u32 seg, int order)
144{
145 __mthca_free_mtt(dev, seg, order);
146
147 if (dev->hca_type == ARBEL_NATIVE)
148 mthca_table_put_range(dev, dev->mr_table.mtt_table, seg,
149 seg + (1 << order) - 1);
150}
151
125static inline u32 hw_index_to_key(struct mthca_dev *dev, u32 ind) 152static inline u32 hw_index_to_key(struct mthca_dev *dev, u32 ind)
126{ 153{
127 if (dev->hca_type == ARBEL_NATIVE) 154 if (dev->hca_type == ARBEL_NATIVE)
@@ -141,7 +168,7 @@ static inline u32 key_to_hw_index(struct mthca_dev *dev, u32 key)
141int mthca_mr_alloc_notrans(struct mthca_dev *dev, u32 pd, 168int mthca_mr_alloc_notrans(struct mthca_dev *dev, u32 pd,
142 u32 access, struct mthca_mr *mr) 169 u32 access, struct mthca_mr *mr)
143{ 170{
144 void *mailbox; 171 void *mailbox = NULL;
145 struct mthca_mpt_entry *mpt_entry; 172 struct mthca_mpt_entry *mpt_entry;
146 u32 key; 173 u32 key;
147 int err; 174 int err;
@@ -155,11 +182,17 @@ int mthca_mr_alloc_notrans(struct mthca_dev *dev, u32 pd,
155 return -ENOMEM; 182 return -ENOMEM;
156 mr->ibmr.rkey = mr->ibmr.lkey = hw_index_to_key(dev, key); 183 mr->ibmr.rkey = mr->ibmr.lkey = hw_index_to_key(dev, key);
157 184
185 if (dev->hca_type == ARBEL_NATIVE) {
186 err = mthca_table_get(dev, dev->mr_table.mpt_table, key);
187 if (err)
188 goto err_out_mpt_free;
189 }
190
158 mailbox = kmalloc(sizeof *mpt_entry + MTHCA_CMD_MAILBOX_EXTRA, 191 mailbox = kmalloc(sizeof *mpt_entry + MTHCA_CMD_MAILBOX_EXTRA,
159 GFP_KERNEL); 192 GFP_KERNEL);
160 if (!mailbox) { 193 if (!mailbox) {
161 mthca_free(&dev->mr_table.mpt_alloc, mr->ibmr.lkey); 194 err = -ENOMEM;
162 return -ENOMEM; 195 goto err_out_table;
163 } 196 }
164 mpt_entry = MAILBOX_ALIGN(mailbox); 197 mpt_entry = MAILBOX_ALIGN(mailbox);
165 198
@@ -180,16 +213,27 @@ int mthca_mr_alloc_notrans(struct mthca_dev *dev, u32 pd,
180 err = mthca_SW2HW_MPT(dev, mpt_entry, 213 err = mthca_SW2HW_MPT(dev, mpt_entry,
181 key & (dev->limits.num_mpts - 1), 214 key & (dev->limits.num_mpts - 1),
182 &status); 215 &status);
183 if (err) 216 if (err) {
184 mthca_warn(dev, "SW2HW_MPT failed (%d)\n", err); 217 mthca_warn(dev, "SW2HW_MPT failed (%d)\n", err);
185 else if (status) { 218 goto err_out_table;
219 } else if (status) {
186 mthca_warn(dev, "SW2HW_MPT returned status 0x%02x\n", 220 mthca_warn(dev, "SW2HW_MPT returned status 0x%02x\n",
187 status); 221 status);
188 err = -EINVAL; 222 err = -EINVAL;
223 goto err_out_table;
189 } 224 }
190 225
191 kfree(mailbox); 226 kfree(mailbox);
192 return err; 227 return err;
228
229err_out_table:
230 if (dev->hca_type == ARBEL_NATIVE)
231 mthca_table_put(dev, dev->mr_table.mpt_table, key);
232
233err_out_mpt_free:
234 mthca_free(&dev->mr_table.mpt_alloc, mr->ibmr.lkey);
235 kfree(mailbox);
236 return err;
193} 237}
194 238
195int mthca_mr_alloc_phys(struct mthca_dev *dev, u32 pd, 239int mthca_mr_alloc_phys(struct mthca_dev *dev, u32 pd,
@@ -213,6 +257,12 @@ int mthca_mr_alloc_phys(struct mthca_dev *dev, u32 pd,
213 return -ENOMEM; 257 return -ENOMEM;
214 mr->ibmr.rkey = mr->ibmr.lkey = hw_index_to_key(dev, key); 258 mr->ibmr.rkey = mr->ibmr.lkey = hw_index_to_key(dev, key);
215 259
260 if (dev->hca_type == ARBEL_NATIVE) {
261 err = mthca_table_get(dev, dev->mr_table.mpt_table, key);
262 if (err)
263 goto err_out_mpt_free;
264 }
265
216 for (i = dev->limits.mtt_seg_size / 8, mr->order = 0; 266 for (i = dev->limits.mtt_seg_size / 8, mr->order = 0;
217 i < list_len; 267 i < list_len;
218 i <<= 1, ++mr->order) 268 i <<= 1, ++mr->order)
@@ -220,7 +270,7 @@ int mthca_mr_alloc_phys(struct mthca_dev *dev, u32 pd,
220 270
221 mr->first_seg = mthca_alloc_mtt(dev, mr->order); 271 mr->first_seg = mthca_alloc_mtt(dev, mr->order);
222 if (mr->first_seg == -1) 272 if (mr->first_seg == -1)
223 goto err_out_mpt_free; 273 goto err_out_table;
224 274
225 /* 275 /*
226 * If list_len is odd, we add one more dummy entry for 276 * If list_len is odd, we add one more dummy entry for
@@ -307,13 +357,17 @@ int mthca_mr_alloc_phys(struct mthca_dev *dev, u32 pd,
307 kfree(mailbox); 357 kfree(mailbox);
308 return err; 358 return err;
309 359
310 err_out_mailbox_free: 360err_out_mailbox_free:
311 kfree(mailbox); 361 kfree(mailbox);
312 362
313 err_out_free_mtt: 363err_out_free_mtt:
314 mthca_free_mtt(dev, mr->first_seg, mr->order); 364 mthca_free_mtt(dev, mr->first_seg, mr->order);
315 365
316 err_out_mpt_free: 366err_out_table:
367 if (dev->hca_type == ARBEL_NATIVE)
368 mthca_table_put(dev, dev->mr_table.mpt_table, key);
369
370err_out_mpt_free:
317 mthca_free(&dev->mr_table.mpt_alloc, mr->ibmr.lkey); 371 mthca_free(&dev->mr_table.mpt_alloc, mr->ibmr.lkey);
318 return err; 372 return err;
319} 373}
@@ -338,6 +392,9 @@ void mthca_free_mr(struct mthca_dev *dev, struct mthca_mr *mr)
338 if (mr->order >= 0) 392 if (mr->order >= 0)
339 mthca_free_mtt(dev, mr->first_seg, mr->order); 393 mthca_free_mtt(dev, mr->first_seg, mr->order);
340 394
395 if (dev->hca_type == ARBEL_NATIVE)
396 mthca_table_put(dev, dev->mr_table.mpt_table,
397 key_to_hw_index(dev, mr->ibmr.lkey));
341 mthca_free(&dev->mr_table.mpt_alloc, key_to_hw_index(dev, mr->ibmr.lkey)); 398 mthca_free(&dev->mr_table.mpt_alloc, key_to_hw_index(dev, mr->ibmr.lkey));
342} 399}
343 400