aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/infiniband/hw/mthca/mthca_mr.c
diff options
context:
space:
mode:
authorMichael S. Tsirkin <mst@mellanox.co.il>2007-02-10 16:14:25 -0500
committerRoland Dreier <rolandd@cisco.com>2007-02-12 19:16:29 -0500
commitb2875d4c39759a732203db32f245cc6d8bbdd7cf (patch)
treeeba8311c0242da3298796d33e86a990aa2a7637f /drivers/infiniband/hw/mthca/mthca_mr.c
parentc20e20ab0f3af9a44842ea11287c9ecd034a5d33 (diff)
IB/mthca: Always fill MTTs from CPU
Speed up memory registration by filling in MTTs directly when the CPU can write directly to the whole table (all mem-free cards, and to Tavor mode on 64-bit systems with the patch I posted earlier). This reduces the number of FW commands needed to register an MR by at least a factor of 2 and speeds up memory registration significantly. Signed-off-by: Michael S. Tsirkin <mst@mellanox.co.il> Signed-off-by: Roland Dreier <rolandd@cisco.com>
Diffstat (limited to 'drivers/infiniband/hw/mthca/mthca_mr.c')
-rw-r--r--drivers/infiniband/hw/mthca/mthca_mr.c82
1 files changed, 80 insertions, 2 deletions
diff --git a/drivers/infiniband/hw/mthca/mthca_mr.c b/drivers/infiniband/hw/mthca/mthca_mr.c
index 958c6d5b6bc0..6037dd3f87df 100644
--- a/drivers/infiniband/hw/mthca/mthca_mr.c
+++ b/drivers/infiniband/hw/mthca/mthca_mr.c
@@ -243,8 +243,8 @@ void mthca_free_mtt(struct mthca_dev *dev, struct mthca_mtt *mtt)
243 kfree(mtt); 243 kfree(mtt);
244} 244}
245 245
246int mthca_write_mtt(struct mthca_dev *dev, struct mthca_mtt *mtt, 246static int __mthca_write_mtt(struct mthca_dev *dev, struct mthca_mtt *mtt,
247 int start_index, u64 *buffer_list, int list_len) 247 int start_index, u64 *buffer_list, int list_len)
248{ 248{
249 struct mthca_mailbox *mailbox; 249 struct mthca_mailbox *mailbox;
250 __be64 *mtt_entry; 250 __be64 *mtt_entry;
@@ -295,6 +295,84 @@ out:
295 return err; 295 return err;
296} 296}
297 297
298int mthca_write_mtt_size(struct mthca_dev *dev)
299{
300 if (dev->mr_table.fmr_mtt_buddy != &dev->mr_table.mtt_buddy)
301 /*
302 * Be friendly to WRITE_MTT command
303 * and leave two empty slots for the
304 * index and reserved fields of the
305 * mailbox.
306 */
307 return PAGE_SIZE / sizeof (u64) - 2;
308
309 /* For Arbel, all MTTs must fit in the same page. */
310 return mthca_is_memfree(dev) ? (PAGE_SIZE / sizeof (u64)) : 0x7ffffff;
311}
312
313void mthca_tavor_write_mtt_seg(struct mthca_dev *dev, struct mthca_mtt *mtt,
314 int start_index, u64 *buffer_list, int list_len)
315{
316 u64 __iomem *mtts;
317 int i;
318
319 mtts = dev->mr_table.tavor_fmr.mtt_base + mtt->first_seg * MTHCA_MTT_SEG_SIZE +
320 start_index * sizeof (u64);
321 for (i = 0; i < list_len; ++i)
322 mthca_write64_raw(cpu_to_be64(buffer_list[i] | MTHCA_MTT_FLAG_PRESENT),
323 mtts + i);
324}
325
326void mthca_arbel_write_mtt_seg(struct mthca_dev *dev, struct mthca_mtt *mtt,
327 int start_index, u64 *buffer_list, int list_len)
328{
329 __be64 *mtts;
330 dma_addr_t dma_handle;
331 int i;
332 int s = start_index * sizeof (u64);
333
334 /* For Arbel, all MTTs must fit in the same page. */
335 BUG_ON(s / PAGE_SIZE != (s + list_len * sizeof(u64) - 1) / PAGE_SIZE);
336 /* Require full segments */
337 BUG_ON(s % MTHCA_MTT_SEG_SIZE);
338
339 mtts = mthca_table_find(dev->mr_table.mtt_table, mtt->first_seg +
340 s / MTHCA_MTT_SEG_SIZE, &dma_handle);
341
342 BUG_ON(!mtts);
343
344 for (i = 0; i < list_len; ++i)
345 mtts[i] = cpu_to_be64(buffer_list[i] | MTHCA_MTT_FLAG_PRESENT);
346
347 dma_sync_single(&dev->pdev->dev, dma_handle, list_len * sizeof (u64), DMA_TO_DEVICE);
348}
349
350int mthca_write_mtt(struct mthca_dev *dev, struct mthca_mtt *mtt,
351 int start_index, u64 *buffer_list, int list_len)
352{
353 int size = mthca_write_mtt_size(dev);
354 int chunk;
355
356 if (dev->mr_table.fmr_mtt_buddy != &dev->mr_table.mtt_buddy)
357 return __mthca_write_mtt(dev, mtt, start_index, buffer_list, list_len);
358
359 while (list_len > 0) {
360 chunk = min(size, list_len);
361 if (mthca_is_memfree(dev))
362 mthca_arbel_write_mtt_seg(dev, mtt, start_index,
363 buffer_list, chunk);
364 else
365 mthca_tavor_write_mtt_seg(dev, mtt, start_index,
366 buffer_list, chunk);
367
368 list_len -= chunk;
369 start_index += chunk;
370 buffer_list += chunk;
371 }
372
373 return 0;
374}
375
298static inline u32 tavor_hw_index_to_key(u32 ind) 376static inline u32 tavor_hw_index_to_key(u32 ind)
299{ 377{
300 return ind; 378 return ind;