mirror of https://gitee.com/openkylin/linux.git
[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: Roland Dreier <roland@topspin.com> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
This commit is contained in:
parent
79b61dceaf
commit
86562a1391
|
@ -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
|
||||||
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,
|
||||||
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 @@
|
||||||
|
|
||||||
#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 {
|
||||||
* 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)
|
||||||
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)
|
||||||
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)
|
||||||
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,
|
||||||
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,
|
||||||
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,
|
||||||
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,
|
||||||
|
|
||||||
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,
|
||||||
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)
|
||||||
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));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue