Commit 86562a13 authored by Roland Dreier's avatar Roland Dreier Committed by Linus Torvalds

[PATCH] IB/mthca: map MPT/MTT context in mem-free mode

In mem-free mode, when allocating memory regions, make sure that the HCA has
context memory mapped to cover the virtual space used for the MPT and MTTs
being used.
Signed-off-by: default avatarRoland Dreier <roland@topspin.com>
Signed-off-by: default avatarAndrew Morton <akpm@osdl.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent 79b61dce
...@@ -390,7 +390,7 @@ static int __devinit mthca_init_icm(struct mthca_dev *mdev, ...@@ -390,7 +390,7 @@ static int __devinit mthca_init_icm(struct mthca_dev *mdev,
} }
mdev->mr_table.mtt_table = mthca_alloc_icm_table(mdev, init_hca->mtt_base, mdev->mr_table.mtt_table = mthca_alloc_icm_table(mdev, init_hca->mtt_base,
init_hca->mtt_seg_sz, dev_lim->mtt_seg_sz,
mdev->limits.num_mtt_segs, mdev->limits.num_mtt_segs,
mdev->limits.reserved_mtts, 1); mdev->limits.reserved_mtts, 1);
if (!mdev->mr_table.mtt_table) { if (!mdev->mr_table.mtt_table) {
......
...@@ -192,6 +192,38 @@ void mthca_table_put(struct mthca_dev *dev, struct mthca_icm_table *table, int o ...@@ -192,6 +192,38 @@ void mthca_table_put(struct mthca_dev *dev, struct mthca_icm_table *table, int o
up(&table->mutex); up(&table->mutex);
} }
int mthca_table_get_range(struct mthca_dev *dev, struct mthca_icm_table *table,
int start, int end)
{
int inc = MTHCA_TABLE_CHUNK_SIZE / table->obj_size;
int i, err;
for (i = start; i <= end; i += inc) {
err = mthca_table_get(dev, table, i);
if (err)
goto fail;
}
return 0;
fail:
while (i > start) {
i -= inc;
mthca_table_put(dev, table, i);
}
return err;
}
void mthca_table_put_range(struct mthca_dev *dev, struct mthca_icm_table *table,
int start, int end)
{
int i;
for (i = start; i <= end; i += MTHCA_TABLE_CHUNK_SIZE / table->obj_size)
mthca_table_put(dev, table, i);
}
struct mthca_icm_table *mthca_alloc_icm_table(struct mthca_dev *dev, struct mthca_icm_table *mthca_alloc_icm_table(struct mthca_dev *dev,
u64 virt, int obj_size, u64 virt, int obj_size,
int nobj, int reserved, int nobj, int reserved,
......
...@@ -85,6 +85,10 @@ struct mthca_icm_table *mthca_alloc_icm_table(struct mthca_dev *dev, ...@@ -85,6 +85,10 @@ struct mthca_icm_table *mthca_alloc_icm_table(struct mthca_dev *dev,
void mthca_free_icm_table(struct mthca_dev *dev, struct mthca_icm_table *table); void mthca_free_icm_table(struct mthca_dev *dev, struct mthca_icm_table *table);
int mthca_table_get(struct mthca_dev *dev, struct mthca_icm_table *table, int obj); int mthca_table_get(struct mthca_dev *dev, struct mthca_icm_table *table, int obj);
void mthca_table_put(struct mthca_dev *dev, struct mthca_icm_table *table, int obj); void mthca_table_put(struct mthca_dev *dev, struct mthca_icm_table *table, int obj);
int mthca_table_get_range(struct mthca_dev *dev, struct mthca_icm_table *table,
int start, int end);
void mthca_table_put_range(struct mthca_dev *dev, struct mthca_icm_table *table,
int start, int end);
static inline void mthca_icm_first(struct mthca_icm *icm, static inline void mthca_icm_first(struct mthca_icm *icm,
struct mthca_icm_iter *iter) struct mthca_icm_iter *iter)
......
...@@ -38,6 +38,7 @@ ...@@ -38,6 +38,7 @@
#include "mthca_dev.h" #include "mthca_dev.h"
#include "mthca_cmd.h" #include "mthca_cmd.h"
#include "mthca_memfree.h"
/* /*
* Must be packed because mtt_seg is 64 bits but only aligned to 32 bits. * Must be packed because mtt_seg is 64 bits but only aligned to 32 bits.
...@@ -71,7 +72,7 @@ struct mthca_mpt_entry { ...@@ -71,7 +72,7 @@ struct mthca_mpt_entry {
* through the bitmaps) * through the bitmaps)
*/ */
static u32 mthca_alloc_mtt(struct mthca_dev *dev, int order) static u32 __mthca_alloc_mtt(struct mthca_dev *dev, int order)
{ {
int o; int o;
int m; int m;
...@@ -105,7 +106,7 @@ static u32 mthca_alloc_mtt(struct mthca_dev *dev, int order) ...@@ -105,7 +106,7 @@ static u32 mthca_alloc_mtt(struct mthca_dev *dev, int order)
return seg; return seg;
} }
static void mthca_free_mtt(struct mthca_dev *dev, u32 seg, int order) static void __mthca_free_mtt(struct mthca_dev *dev, u32 seg, int order)
{ {
seg >>= order; seg >>= order;
...@@ -122,6 +123,32 @@ static void mthca_free_mtt(struct mthca_dev *dev, u32 seg, int order) ...@@ -122,6 +123,32 @@ static void mthca_free_mtt(struct mthca_dev *dev, u32 seg, int order)
spin_unlock(&dev->mr_table.mpt_alloc.lock); spin_unlock(&dev->mr_table.mpt_alloc.lock);
} }
static u32 mthca_alloc_mtt(struct mthca_dev *dev, int order)
{
u32 seg = __mthca_alloc_mtt(dev, order);
if (seg == -1)
return -1;
if (dev->hca_type == ARBEL_NATIVE)
if (mthca_table_get_range(dev, dev->mr_table.mtt_table, seg,
seg + (1 << order) - 1)) {
__mthca_free_mtt(dev, seg, order);
seg = -1;
}
return seg;
}
static void mthca_free_mtt(struct mthca_dev *dev, u32 seg, int order)
{
__mthca_free_mtt(dev, seg, order);
if (dev->hca_type == ARBEL_NATIVE)
mthca_table_put_range(dev, dev->mr_table.mtt_table, seg,
seg + (1 << order) - 1);
}
static inline u32 hw_index_to_key(struct mthca_dev *dev, u32 ind) static inline u32 hw_index_to_key(struct mthca_dev *dev, u32 ind)
{ {
if (dev->hca_type == ARBEL_NATIVE) if (dev->hca_type == ARBEL_NATIVE)
...@@ -141,7 +168,7 @@ static inline u32 key_to_hw_index(struct mthca_dev *dev, u32 key) ...@@ -141,7 +168,7 @@ static inline u32 key_to_hw_index(struct mthca_dev *dev, u32 key)
int mthca_mr_alloc_notrans(struct mthca_dev *dev, u32 pd, int mthca_mr_alloc_notrans(struct mthca_dev *dev, u32 pd,
u32 access, struct mthca_mr *mr) u32 access, struct mthca_mr *mr)
{ {
void *mailbox; void *mailbox = NULL;
struct mthca_mpt_entry *mpt_entry; struct mthca_mpt_entry *mpt_entry;
u32 key; u32 key;
int err; int err;
...@@ -155,11 +182,17 @@ int mthca_mr_alloc_notrans(struct mthca_dev *dev, u32 pd, ...@@ -155,11 +182,17 @@ int mthca_mr_alloc_notrans(struct mthca_dev *dev, u32 pd,
return -ENOMEM; return -ENOMEM;
mr->ibmr.rkey = mr->ibmr.lkey = hw_index_to_key(dev, key); mr->ibmr.rkey = mr->ibmr.lkey = hw_index_to_key(dev, key);
if (dev->hca_type == ARBEL_NATIVE) {
err = mthca_table_get(dev, dev->mr_table.mpt_table, key);
if (err)
goto err_out_mpt_free;
}
mailbox = kmalloc(sizeof *mpt_entry + MTHCA_CMD_MAILBOX_EXTRA, mailbox = kmalloc(sizeof *mpt_entry + MTHCA_CMD_MAILBOX_EXTRA,
GFP_KERNEL); GFP_KERNEL);
if (!mailbox) { if (!mailbox) {
mthca_free(&dev->mr_table.mpt_alloc, mr->ibmr.lkey); err = -ENOMEM;
return -ENOMEM; goto err_out_table;
} }
mpt_entry = MAILBOX_ALIGN(mailbox); mpt_entry = MAILBOX_ALIGN(mailbox);
...@@ -180,16 +213,27 @@ int mthca_mr_alloc_notrans(struct mthca_dev *dev, u32 pd, ...@@ -180,16 +213,27 @@ int mthca_mr_alloc_notrans(struct mthca_dev *dev, u32 pd,
err = mthca_SW2HW_MPT(dev, mpt_entry, err = mthca_SW2HW_MPT(dev, mpt_entry,
key & (dev->limits.num_mpts - 1), key & (dev->limits.num_mpts - 1),
&status); &status);
if (err) if (err) {
mthca_warn(dev, "SW2HW_MPT failed (%d)\n", err); mthca_warn(dev, "SW2HW_MPT failed (%d)\n", err);
else if (status) { goto err_out_table;
} else if (status) {
mthca_warn(dev, "SW2HW_MPT returned status 0x%02x\n", mthca_warn(dev, "SW2HW_MPT returned status 0x%02x\n",
status); status);
err = -EINVAL; err = -EINVAL;
goto err_out_table;
} }
kfree(mailbox); kfree(mailbox);
return err; return err;
err_out_table:
if (dev->hca_type == ARBEL_NATIVE)
mthca_table_put(dev, dev->mr_table.mpt_table, key);
err_out_mpt_free:
mthca_free(&dev->mr_table.mpt_alloc, mr->ibmr.lkey);
kfree(mailbox);
return err;
} }
int mthca_mr_alloc_phys(struct mthca_dev *dev, u32 pd, int 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,6 +257,12 @@ int mthca_mr_alloc_phys(struct mthca_dev *dev, u32 pd,
return -ENOMEM; return -ENOMEM;
mr->ibmr.rkey = mr->ibmr.lkey = hw_index_to_key(dev, key); mr->ibmr.rkey = mr->ibmr.lkey = hw_index_to_key(dev, key);
if (dev->hca_type == ARBEL_NATIVE) {
err = mthca_table_get(dev, dev->mr_table.mpt_table, key);
if (err)
goto err_out_mpt_free;
}
for (i = dev->limits.mtt_seg_size / 8, mr->order = 0; for (i = dev->limits.mtt_seg_size / 8, mr->order = 0;
i < list_len; i < list_len;
i <<= 1, ++mr->order) i <<= 1, ++mr->order)
...@@ -220,7 +270,7 @@ int mthca_mr_alloc_phys(struct mthca_dev *dev, u32 pd, ...@@ -220,7 +270,7 @@ int mthca_mr_alloc_phys(struct mthca_dev *dev, u32 pd,
mr->first_seg = mthca_alloc_mtt(dev, mr->order); mr->first_seg = mthca_alloc_mtt(dev, mr->order);
if (mr->first_seg == -1) if (mr->first_seg == -1)
goto err_out_mpt_free; goto err_out_table;
/* /*
* If list_len is odd, we add one more dummy entry for * 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,13 +357,17 @@ int mthca_mr_alloc_phys(struct mthca_dev *dev, u32 pd,
kfree(mailbox); kfree(mailbox);
return err; return err;
err_out_mailbox_free: err_out_mailbox_free:
kfree(mailbox); kfree(mailbox);
err_out_free_mtt: err_out_free_mtt:
mthca_free_mtt(dev, mr->first_seg, mr->order); mthca_free_mtt(dev, mr->first_seg, mr->order);
err_out_mpt_free: err_out_table:
if (dev->hca_type == ARBEL_NATIVE)
mthca_table_put(dev, dev->mr_table.mpt_table, key);
err_out_mpt_free:
mthca_free(&dev->mr_table.mpt_alloc, mr->ibmr.lkey); mthca_free(&dev->mr_table.mpt_alloc, mr->ibmr.lkey);
return err; return err;
} }
...@@ -338,6 +392,9 @@ void mthca_free_mr(struct mthca_dev *dev, struct mthca_mr *mr) ...@@ -338,6 +392,9 @@ void mthca_free_mr(struct mthca_dev *dev, struct mthca_mr *mr)
if (mr->order >= 0) if (mr->order >= 0)
mthca_free_mtt(dev, mr->first_seg, mr->order); mthca_free_mtt(dev, mr->first_seg, mr->order);
if (dev->hca_type == ARBEL_NATIVE)
mthca_table_put(dev, dev->mr_table.mpt_table,
key_to_hw_index(dev, mr->ibmr.lkey));
mthca_free(&dev->mr_table.mpt_alloc, key_to_hw_index(dev, mr->ibmr.lkey)); mthca_free(&dev->mr_table.mpt_alloc, key_to_hw_index(dev, mr->ibmr.lkey));
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment