Merge tag 'rdma-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/roland/infiniband
Pull infiniband update from Roland Dreier: "Main batch of InfiniBand/RDMA changes for 3.9: - SRP error handling fixes from Bart Van Assche - Implementation of memory windows for mlx4 from Shani Michaeli - Lots of cxgb4 HW driver fixes from Vipul Pandya - Make iSER work for virtual functions, other fixes from Or Gerlitz - Fix for bug in qib HW driver from Mike Marciniszyn - IPoIB fixes from me, Itai Garbi, Shlomo Pongratz, Yan Burman - Various cleanups and warning fixes from Julia Lawall, Paul Bolle, Wei Yongjun" * tag 'rdma-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/roland/infiniband: (41 commits) IB/mlx4: Advertise MW support IB/mlx4: Support memory window binding mlx4: Implement memory windows allocation and deallocation mlx4_core: Enable memory windows in {INIT, QUERY}_HCA mlx4_core: Disable memory windows for virtual functions IPoIB: Free ipoib neigh on path record failure so path rec queries are retried IB/srp: Fail I/O requests if the transport is offline IB/srp: Avoid endless SCSI error handling loop IB/srp: Avoid sending a task management function needlessly IB/srp: Track connection state properly IB/mlx4: Remove redundant NULL check before kfree IB/mlx4: Fix compiler warning about uninitialized 'vlan' variable IB/mlx4: Convert is_xxx variables in build_mlx_header() to bool IB/iser: Enable iser when FMRs are not supported IB/iser: Avoid error prints on EAGAIN registration failures IB/iser: Use proper define for the commands per LUN value advertised to SCSI ML IB/uverbs: Implement memory windows support in uverbs IB/core: Add "type 2" memory windows support mlx4_core: Propagate MR deregistration failures to caller mlx4_core: Rename MPT-related functions to have mpt_ prefix ...
This commit is contained in:
@@ -198,7 +198,7 @@ static void mlx4_en_remove(struct mlx4_dev *dev, void *endev_ptr)
|
||||
|
||||
flush_workqueue(mdev->workqueue);
|
||||
destroy_workqueue(mdev->workqueue);
|
||||
mlx4_mr_free(dev, &mdev->mr);
|
||||
(void) mlx4_mr_free(dev, &mdev->mr);
|
||||
iounmap(mdev->uar_map);
|
||||
mlx4_uar_free(dev, &mdev->priv_uar);
|
||||
mlx4_pd_free(dev, mdev->priv_pdn);
|
||||
@@ -303,7 +303,7 @@ static void *mlx4_en_add(struct mlx4_dev *dev)
|
||||
return mdev;
|
||||
|
||||
err_mr:
|
||||
mlx4_mr_free(dev, &mdev->mr);
|
||||
(void) mlx4_mr_free(dev, &mdev->mr);
|
||||
err_map:
|
||||
if (!mdev->uar_map)
|
||||
iounmap(mdev->uar_map);
|
||||
|
@@ -762,15 +762,19 @@ int mlx4_QUERY_DEV_CAP_wrapper(struct mlx4_dev *dev, int slave,
|
||||
u64 flags;
|
||||
int err = 0;
|
||||
u8 field;
|
||||
u32 bmme_flags;
|
||||
|
||||
err = mlx4_cmd_box(dev, 0, outbox->dma, 0, 0, MLX4_CMD_QUERY_DEV_CAP,
|
||||
MLX4_CMD_TIME_CLASS_A, MLX4_CMD_NATIVE);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
/* add port mng change event capability unconditionally to slaves */
|
||||
/* add port mng change event capability and disable mw type 1
|
||||
* unconditionally to slaves
|
||||
*/
|
||||
MLX4_GET(flags, outbox->buf, QUERY_DEV_CAP_EXT_FLAGS_OFFSET);
|
||||
flags |= MLX4_DEV_CAP_FLAG_PORT_MNG_CHG_EV;
|
||||
flags &= ~MLX4_DEV_CAP_FLAG_MEM_WINDOW;
|
||||
MLX4_PUT(outbox->buf, flags, QUERY_DEV_CAP_EXT_FLAGS_OFFSET);
|
||||
|
||||
/* For guests, report Blueflame disabled */
|
||||
@@ -778,6 +782,11 @@ int mlx4_QUERY_DEV_CAP_wrapper(struct mlx4_dev *dev, int slave,
|
||||
field &= 0x7f;
|
||||
MLX4_PUT(outbox->buf, field, QUERY_DEV_CAP_BF_OFFSET);
|
||||
|
||||
/* For guests, disable mw type 2 */
|
||||
MLX4_GET(bmme_flags, outbox, QUERY_DEV_CAP_BMME_FLAGS_OFFSET);
|
||||
bmme_flags &= ~MLX4_BMME_FLAG_TYPE_2_WIN;
|
||||
MLX4_PUT(outbox->buf, bmme_flags, QUERY_DEV_CAP_BMME_FLAGS_OFFSET);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1203,6 +1212,7 @@ int mlx4_INIT_HCA(struct mlx4_dev *dev, struct mlx4_init_hca_param *param)
|
||||
#define INIT_HCA_FS_IB_NUM_ADDRS_OFFSET (INIT_HCA_FS_PARAM_OFFSET + 0x26)
|
||||
#define INIT_HCA_TPT_OFFSET 0x0f0
|
||||
#define INIT_HCA_DMPT_BASE_OFFSET (INIT_HCA_TPT_OFFSET + 0x00)
|
||||
#define INIT_HCA_TPT_MW_OFFSET (INIT_HCA_TPT_OFFSET + 0x08)
|
||||
#define INIT_HCA_LOG_MPT_SZ_OFFSET (INIT_HCA_TPT_OFFSET + 0x0b)
|
||||
#define INIT_HCA_MTT_BASE_OFFSET (INIT_HCA_TPT_OFFSET + 0x10)
|
||||
#define INIT_HCA_CMPT_BASE_OFFSET (INIT_HCA_TPT_OFFSET + 0x18)
|
||||
@@ -1319,6 +1329,7 @@ int mlx4_INIT_HCA(struct mlx4_dev *dev, struct mlx4_init_hca_param *param)
|
||||
/* TPT attributes */
|
||||
|
||||
MLX4_PUT(inbox, param->dmpt_base, INIT_HCA_DMPT_BASE_OFFSET);
|
||||
MLX4_PUT(inbox, param->mw_enabled, INIT_HCA_TPT_MW_OFFSET);
|
||||
MLX4_PUT(inbox, param->log_mpt_sz, INIT_HCA_LOG_MPT_SZ_OFFSET);
|
||||
MLX4_PUT(inbox, param->mtt_base, INIT_HCA_MTT_BASE_OFFSET);
|
||||
MLX4_PUT(inbox, param->cmpt_base, INIT_HCA_CMPT_BASE_OFFSET);
|
||||
@@ -1415,6 +1426,7 @@ int mlx4_QUERY_HCA(struct mlx4_dev *dev,
|
||||
/* TPT attributes */
|
||||
|
||||
MLX4_GET(param->dmpt_base, outbox, INIT_HCA_DMPT_BASE_OFFSET);
|
||||
MLX4_GET(param->mw_enabled, outbox, INIT_HCA_TPT_MW_OFFSET);
|
||||
MLX4_GET(param->log_mpt_sz, outbox, INIT_HCA_LOG_MPT_SZ_OFFSET);
|
||||
MLX4_GET(param->mtt_base, outbox, INIT_HCA_MTT_BASE_OFFSET);
|
||||
MLX4_GET(param->cmpt_base, outbox, INIT_HCA_CMPT_BASE_OFFSET);
|
||||
|
@@ -170,6 +170,7 @@ struct mlx4_init_hca_param {
|
||||
u8 log_mc_table_sz;
|
||||
u8 log_mpt_sz;
|
||||
u8 log_uar_sz;
|
||||
u8 mw_enabled; /* Enable memory windows */
|
||||
u8 uar_page_sz; /* log pg sz in 4k chunks */
|
||||
u8 steering_mode; /* for QUERY_HCA */
|
||||
u64 dev_cap_enabled;
|
||||
|
@@ -1431,6 +1431,10 @@ static int mlx4_init_hca(struct mlx4_dev *dev)
|
||||
|
||||
init_hca.log_uar_sz = ilog2(dev->caps.num_uars);
|
||||
init_hca.uar_page_sz = PAGE_SHIFT - 12;
|
||||
init_hca.mw_enabled = 0;
|
||||
if (dev->caps.flags & MLX4_DEV_CAP_FLAG_MEM_WINDOW ||
|
||||
dev->caps.bmme_flags & MLX4_BMME_FLAG_TYPE_2_WIN)
|
||||
init_hca.mw_enabled = INIT_HCA_TPT_MW_ENABLE;
|
||||
|
||||
err = mlx4_init_icm(dev, &dev_cap, &init_hca, icm_size);
|
||||
if (err)
|
||||
|
@@ -60,6 +60,8 @@
|
||||
#define MLX4_FS_MGM_LOG_ENTRY_SIZE 7
|
||||
#define MLX4_FS_NUM_MCG (1 << 17)
|
||||
|
||||
#define INIT_HCA_TPT_MW_ENABLE (1 << 7)
|
||||
|
||||
#define MLX4_NUM_UP 8
|
||||
#define MLX4_NUM_TC 8
|
||||
#define MLX4_RATELIMIT_UNITS 3 /* 100 Mbps */
|
||||
@@ -113,10 +115,10 @@ enum {
|
||||
MLX4_NUM_CMPTS = MLX4_CMPT_NUM_TYPE << MLX4_CMPT_SHIFT
|
||||
};
|
||||
|
||||
enum mlx4_mr_state {
|
||||
MLX4_MR_DISABLED = 0,
|
||||
MLX4_MR_EN_HW,
|
||||
MLX4_MR_EN_SW
|
||||
enum mlx4_mpt_state {
|
||||
MLX4_MPT_DISABLED = 0,
|
||||
MLX4_MPT_EN_HW,
|
||||
MLX4_MPT_EN_SW
|
||||
};
|
||||
|
||||
#define MLX4_COMM_TIME 10000
|
||||
@@ -263,6 +265,22 @@ struct mlx4_icm_table {
|
||||
struct mlx4_icm **icm;
|
||||
};
|
||||
|
||||
#define MLX4_MPT_FLAG_SW_OWNS (0xfUL << 28)
|
||||
#define MLX4_MPT_FLAG_FREE (0x3UL << 28)
|
||||
#define MLX4_MPT_FLAG_MIO (1 << 17)
|
||||
#define MLX4_MPT_FLAG_BIND_ENABLE (1 << 15)
|
||||
#define MLX4_MPT_FLAG_PHYSICAL (1 << 9)
|
||||
#define MLX4_MPT_FLAG_REGION (1 << 8)
|
||||
|
||||
#define MLX4_MPT_PD_FLAG_FAST_REG (1 << 27)
|
||||
#define MLX4_MPT_PD_FLAG_RAE (1 << 28)
|
||||
#define MLX4_MPT_PD_FLAG_EN_INV (3 << 24)
|
||||
|
||||
#define MLX4_MPT_QP_FLAG_BOUND_QP (1 << 7)
|
||||
|
||||
#define MLX4_MPT_STATUS_SW 0xF0
|
||||
#define MLX4_MPT_STATUS_HW 0x00
|
||||
|
||||
/*
|
||||
* Must be packed because mtt_seg is 64 bits but only aligned to 32 bits.
|
||||
*/
|
||||
@@ -863,10 +881,10 @@ int __mlx4_cq_alloc_icm(struct mlx4_dev *dev, int *cqn);
|
||||
void __mlx4_cq_free_icm(struct mlx4_dev *dev, int cqn);
|
||||
int __mlx4_srq_alloc_icm(struct mlx4_dev *dev, int *srqn);
|
||||
void __mlx4_srq_free_icm(struct mlx4_dev *dev, int srqn);
|
||||
int __mlx4_mr_reserve(struct mlx4_dev *dev);
|
||||
void __mlx4_mr_release(struct mlx4_dev *dev, u32 index);
|
||||
int __mlx4_mr_alloc_icm(struct mlx4_dev *dev, u32 index);
|
||||
void __mlx4_mr_free_icm(struct mlx4_dev *dev, u32 index);
|
||||
int __mlx4_mpt_reserve(struct mlx4_dev *dev);
|
||||
void __mlx4_mpt_release(struct mlx4_dev *dev, u32 index);
|
||||
int __mlx4_mpt_alloc_icm(struct mlx4_dev *dev, u32 index);
|
||||
void __mlx4_mpt_free_icm(struct mlx4_dev *dev, u32 index);
|
||||
u32 __mlx4_alloc_mtt_range(struct mlx4_dev *dev, int order);
|
||||
void __mlx4_free_mtt_range(struct mlx4_dev *dev, u32 first_seg, int order);
|
||||
|
||||
|
@@ -44,20 +44,6 @@
|
||||
#include "mlx4.h"
|
||||
#include "icm.h"
|
||||
|
||||
#define MLX4_MPT_FLAG_SW_OWNS (0xfUL << 28)
|
||||
#define MLX4_MPT_FLAG_FREE (0x3UL << 28)
|
||||
#define MLX4_MPT_FLAG_MIO (1 << 17)
|
||||
#define MLX4_MPT_FLAG_BIND_ENABLE (1 << 15)
|
||||
#define MLX4_MPT_FLAG_PHYSICAL (1 << 9)
|
||||
#define MLX4_MPT_FLAG_REGION (1 << 8)
|
||||
|
||||
#define MLX4_MPT_PD_FLAG_FAST_REG (1 << 27)
|
||||
#define MLX4_MPT_PD_FLAG_RAE (1 << 28)
|
||||
#define MLX4_MPT_PD_FLAG_EN_INV (3 << 24)
|
||||
|
||||
#define MLX4_MPT_STATUS_SW 0xF0
|
||||
#define MLX4_MPT_STATUS_HW 0x00
|
||||
|
||||
static u32 mlx4_buddy_alloc(struct mlx4_buddy *buddy, int order)
|
||||
{
|
||||
int o;
|
||||
@@ -321,7 +307,7 @@ static int mlx4_mr_alloc_reserved(struct mlx4_dev *dev, u32 mridx, u32 pd,
|
||||
mr->size = size;
|
||||
mr->pd = pd;
|
||||
mr->access = access;
|
||||
mr->enabled = MLX4_MR_DISABLED;
|
||||
mr->enabled = MLX4_MPT_DISABLED;
|
||||
mr->key = hw_index_to_key(mridx);
|
||||
|
||||
return mlx4_mtt_init(dev, npages, page_shift, &mr->mtt);
|
||||
@@ -335,14 +321,14 @@ static int mlx4_WRITE_MTT(struct mlx4_dev *dev,
|
||||
MLX4_CMD_TIME_CLASS_A, MLX4_CMD_WRAPPED);
|
||||
}
|
||||
|
||||
int __mlx4_mr_reserve(struct mlx4_dev *dev)
|
||||
int __mlx4_mpt_reserve(struct mlx4_dev *dev)
|
||||
{
|
||||
struct mlx4_priv *priv = mlx4_priv(dev);
|
||||
|
||||
return mlx4_bitmap_alloc(&priv->mr_table.mpt_bitmap);
|
||||
}
|
||||
|
||||
static int mlx4_mr_reserve(struct mlx4_dev *dev)
|
||||
static int mlx4_mpt_reserve(struct mlx4_dev *dev)
|
||||
{
|
||||
u64 out_param;
|
||||
|
||||
@@ -353,17 +339,17 @@ static int mlx4_mr_reserve(struct mlx4_dev *dev)
|
||||
return -1;
|
||||
return get_param_l(&out_param);
|
||||
}
|
||||
return __mlx4_mr_reserve(dev);
|
||||
return __mlx4_mpt_reserve(dev);
|
||||
}
|
||||
|
||||
void __mlx4_mr_release(struct mlx4_dev *dev, u32 index)
|
||||
void __mlx4_mpt_release(struct mlx4_dev *dev, u32 index)
|
||||
{
|
||||
struct mlx4_priv *priv = mlx4_priv(dev);
|
||||
|
||||
mlx4_bitmap_free(&priv->mr_table.mpt_bitmap, index);
|
||||
}
|
||||
|
||||
static void mlx4_mr_release(struct mlx4_dev *dev, u32 index)
|
||||
static void mlx4_mpt_release(struct mlx4_dev *dev, u32 index)
|
||||
{
|
||||
u64 in_param;
|
||||
|
||||
@@ -376,17 +362,17 @@ static void mlx4_mr_release(struct mlx4_dev *dev, u32 index)
|
||||
index);
|
||||
return;
|
||||
}
|
||||
__mlx4_mr_release(dev, index);
|
||||
__mlx4_mpt_release(dev, index);
|
||||
}
|
||||
|
||||
int __mlx4_mr_alloc_icm(struct mlx4_dev *dev, u32 index)
|
||||
int __mlx4_mpt_alloc_icm(struct mlx4_dev *dev, u32 index)
|
||||
{
|
||||
struct mlx4_mr_table *mr_table = &mlx4_priv(dev)->mr_table;
|
||||
|
||||
return mlx4_table_get(dev, &mr_table->dmpt_table, index);
|
||||
}
|
||||
|
||||
static int mlx4_mr_alloc_icm(struct mlx4_dev *dev, u32 index)
|
||||
static int mlx4_mpt_alloc_icm(struct mlx4_dev *dev, u32 index)
|
||||
{
|
||||
u64 param;
|
||||
|
||||
@@ -397,17 +383,17 @@ static int mlx4_mr_alloc_icm(struct mlx4_dev *dev, u32 index)
|
||||
MLX4_CMD_TIME_CLASS_A,
|
||||
MLX4_CMD_WRAPPED);
|
||||
}
|
||||
return __mlx4_mr_alloc_icm(dev, index);
|
||||
return __mlx4_mpt_alloc_icm(dev, index);
|
||||
}
|
||||
|
||||
void __mlx4_mr_free_icm(struct mlx4_dev *dev, u32 index)
|
||||
void __mlx4_mpt_free_icm(struct mlx4_dev *dev, u32 index)
|
||||
{
|
||||
struct mlx4_mr_table *mr_table = &mlx4_priv(dev)->mr_table;
|
||||
|
||||
mlx4_table_put(dev, &mr_table->dmpt_table, index);
|
||||
}
|
||||
|
||||
static void mlx4_mr_free_icm(struct mlx4_dev *dev, u32 index)
|
||||
static void mlx4_mpt_free_icm(struct mlx4_dev *dev, u32 index)
|
||||
{
|
||||
u64 in_param;
|
||||
|
||||
@@ -420,7 +406,7 @@ static void mlx4_mr_free_icm(struct mlx4_dev *dev, u32 index)
|
||||
index);
|
||||
return;
|
||||
}
|
||||
return __mlx4_mr_free_icm(dev, index);
|
||||
return __mlx4_mpt_free_icm(dev, index);
|
||||
}
|
||||
|
||||
int mlx4_mr_alloc(struct mlx4_dev *dev, u32 pd, u64 iova, u64 size, u32 access,
|
||||
@@ -429,41 +415,52 @@ int mlx4_mr_alloc(struct mlx4_dev *dev, u32 pd, u64 iova, u64 size, u32 access,
|
||||
u32 index;
|
||||
int err;
|
||||
|
||||
index = mlx4_mr_reserve(dev);
|
||||
index = mlx4_mpt_reserve(dev);
|
||||
if (index == -1)
|
||||
return -ENOMEM;
|
||||
|
||||
err = mlx4_mr_alloc_reserved(dev, index, pd, iova, size,
|
||||
access, npages, page_shift, mr);
|
||||
if (err)
|
||||
mlx4_mr_release(dev, index);
|
||||
mlx4_mpt_release(dev, index);
|
||||
|
||||
return err;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mlx4_mr_alloc);
|
||||
|
||||
static void mlx4_mr_free_reserved(struct mlx4_dev *dev, struct mlx4_mr *mr)
|
||||
static int mlx4_mr_free_reserved(struct mlx4_dev *dev, struct mlx4_mr *mr)
|
||||
{
|
||||
int err;
|
||||
|
||||
if (mr->enabled == MLX4_MR_EN_HW) {
|
||||
if (mr->enabled == MLX4_MPT_EN_HW) {
|
||||
err = mlx4_HW2SW_MPT(dev, NULL,
|
||||
key_to_hw_index(mr->key) &
|
||||
(dev->caps.num_mpts - 1));
|
||||
if (err)
|
||||
mlx4_warn(dev, "xxx HW2SW_MPT failed (%d)\n", err);
|
||||
if (err) {
|
||||
mlx4_warn(dev, "HW2SW_MPT failed (%d),", err);
|
||||
mlx4_warn(dev, "MR has MWs bound to it.\n");
|
||||
return err;
|
||||
}
|
||||
|
||||
mr->enabled = MLX4_MR_EN_SW;
|
||||
mr->enabled = MLX4_MPT_EN_SW;
|
||||
}
|
||||
mlx4_mtt_cleanup(dev, &mr->mtt);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void mlx4_mr_free(struct mlx4_dev *dev, struct mlx4_mr *mr)
|
||||
int mlx4_mr_free(struct mlx4_dev *dev, struct mlx4_mr *mr)
|
||||
{
|
||||
mlx4_mr_free_reserved(dev, mr);
|
||||
int ret;
|
||||
|
||||
ret = mlx4_mr_free_reserved(dev, mr);
|
||||
if (ret)
|
||||
return ret;
|
||||
if (mr->enabled)
|
||||
mlx4_mr_free_icm(dev, key_to_hw_index(mr->key));
|
||||
mlx4_mr_release(dev, key_to_hw_index(mr->key));
|
||||
mlx4_mpt_free_icm(dev, key_to_hw_index(mr->key));
|
||||
mlx4_mpt_release(dev, key_to_hw_index(mr->key));
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mlx4_mr_free);
|
||||
|
||||
@@ -473,7 +470,7 @@ int mlx4_mr_enable(struct mlx4_dev *dev, struct mlx4_mr *mr)
|
||||
struct mlx4_mpt_entry *mpt_entry;
|
||||
int err;
|
||||
|
||||
err = mlx4_mr_alloc_icm(dev, key_to_hw_index(mr->key));
|
||||
err = mlx4_mpt_alloc_icm(dev, key_to_hw_index(mr->key));
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
@@ -520,7 +517,7 @@ int mlx4_mr_enable(struct mlx4_dev *dev, struct mlx4_mr *mr)
|
||||
mlx4_warn(dev, "SW2HW_MPT failed (%d)\n", err);
|
||||
goto err_cmd;
|
||||
}
|
||||
mr->enabled = MLX4_MR_EN_HW;
|
||||
mr->enabled = MLX4_MPT_EN_HW;
|
||||
|
||||
mlx4_free_cmd_mailbox(dev, mailbox);
|
||||
|
||||
@@ -530,7 +527,7 @@ err_cmd:
|
||||
mlx4_free_cmd_mailbox(dev, mailbox);
|
||||
|
||||
err_table:
|
||||
mlx4_mr_free_icm(dev, key_to_hw_index(mr->key));
|
||||
mlx4_mpt_free_icm(dev, key_to_hw_index(mr->key));
|
||||
return err;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mlx4_mr_enable);
|
||||
@@ -657,6 +654,101 @@ int mlx4_buf_write_mtt(struct mlx4_dev *dev, struct mlx4_mtt *mtt,
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mlx4_buf_write_mtt);
|
||||
|
||||
int mlx4_mw_alloc(struct mlx4_dev *dev, u32 pd, enum mlx4_mw_type type,
|
||||
struct mlx4_mw *mw)
|
||||
{
|
||||
u32 index;
|
||||
|
||||
if ((type == MLX4_MW_TYPE_1 &&
|
||||
!(dev->caps.flags & MLX4_DEV_CAP_FLAG_MEM_WINDOW)) ||
|
||||
(type == MLX4_MW_TYPE_2 &&
|
||||
!(dev->caps.bmme_flags & MLX4_BMME_FLAG_TYPE_2_WIN)))
|
||||
return -ENOTSUPP;
|
||||
|
||||
index = mlx4_mpt_reserve(dev);
|
||||
if (index == -1)
|
||||
return -ENOMEM;
|
||||
|
||||
mw->key = hw_index_to_key(index);
|
||||
mw->pd = pd;
|
||||
mw->type = type;
|
||||
mw->enabled = MLX4_MPT_DISABLED;
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mlx4_mw_alloc);
|
||||
|
||||
int mlx4_mw_enable(struct mlx4_dev *dev, struct mlx4_mw *mw)
|
||||
{
|
||||
struct mlx4_cmd_mailbox *mailbox;
|
||||
struct mlx4_mpt_entry *mpt_entry;
|
||||
int err;
|
||||
|
||||
err = mlx4_mpt_alloc_icm(dev, key_to_hw_index(mw->key));
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
mailbox = mlx4_alloc_cmd_mailbox(dev);
|
||||
if (IS_ERR(mailbox)) {
|
||||
err = PTR_ERR(mailbox);
|
||||
goto err_table;
|
||||
}
|
||||
mpt_entry = mailbox->buf;
|
||||
|
||||
memset(mpt_entry, 0, sizeof(*mpt_entry));
|
||||
|
||||
/* Note that the MLX4_MPT_FLAG_REGION bit in mpt_entry->flags is turned
|
||||
* off, thus creating a memory window and not a memory region.
|
||||
*/
|
||||
mpt_entry->key = cpu_to_be32(key_to_hw_index(mw->key));
|
||||
mpt_entry->pd_flags = cpu_to_be32(mw->pd);
|
||||
if (mw->type == MLX4_MW_TYPE_2) {
|
||||
mpt_entry->flags |= cpu_to_be32(MLX4_MPT_FLAG_FREE);
|
||||
mpt_entry->qpn = cpu_to_be32(MLX4_MPT_QP_FLAG_BOUND_QP);
|
||||
mpt_entry->pd_flags |= cpu_to_be32(MLX4_MPT_PD_FLAG_EN_INV);
|
||||
}
|
||||
|
||||
err = mlx4_SW2HW_MPT(dev, mailbox,
|
||||
key_to_hw_index(mw->key) &
|
||||
(dev->caps.num_mpts - 1));
|
||||
if (err) {
|
||||
mlx4_warn(dev, "SW2HW_MPT failed (%d)\n", err);
|
||||
goto err_cmd;
|
||||
}
|
||||
mw->enabled = MLX4_MPT_EN_HW;
|
||||
|
||||
mlx4_free_cmd_mailbox(dev, mailbox);
|
||||
|
||||
return 0;
|
||||
|
||||
err_cmd:
|
||||
mlx4_free_cmd_mailbox(dev, mailbox);
|
||||
|
||||
err_table:
|
||||
mlx4_mpt_free_icm(dev, key_to_hw_index(mw->key));
|
||||
return err;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mlx4_mw_enable);
|
||||
|
||||
void mlx4_mw_free(struct mlx4_dev *dev, struct mlx4_mw *mw)
|
||||
{
|
||||
int err;
|
||||
|
||||
if (mw->enabled == MLX4_MPT_EN_HW) {
|
||||
err = mlx4_HW2SW_MPT(dev, NULL,
|
||||
key_to_hw_index(mw->key) &
|
||||
(dev->caps.num_mpts - 1));
|
||||
if (err)
|
||||
mlx4_warn(dev, "xxx HW2SW_MPT failed (%d)\n", err);
|
||||
|
||||
mw->enabled = MLX4_MPT_EN_SW;
|
||||
}
|
||||
if (mw->enabled)
|
||||
mlx4_mpt_free_icm(dev, key_to_hw_index(mw->key));
|
||||
mlx4_mpt_release(dev, key_to_hw_index(mw->key));
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mlx4_mw_free);
|
||||
|
||||
int mlx4_init_mr_table(struct mlx4_dev *dev)
|
||||
{
|
||||
struct mlx4_priv *priv = mlx4_priv(dev);
|
||||
@@ -831,7 +923,7 @@ int mlx4_fmr_alloc(struct mlx4_dev *dev, u32 pd, u32 access, int max_pages,
|
||||
return 0;
|
||||
|
||||
err_free:
|
||||
mlx4_mr_free(dev, &fmr->mr);
|
||||
(void) mlx4_mr_free(dev, &fmr->mr);
|
||||
return err;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mlx4_fmr_alloc);
|
||||
@@ -882,17 +974,21 @@ void mlx4_fmr_unmap(struct mlx4_dev *dev, struct mlx4_fmr *fmr,
|
||||
err);
|
||||
return;
|
||||
}
|
||||
fmr->mr.enabled = MLX4_MR_EN_SW;
|
||||
fmr->mr.enabled = MLX4_MPT_EN_SW;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mlx4_fmr_unmap);
|
||||
|
||||
int mlx4_fmr_free(struct mlx4_dev *dev, struct mlx4_fmr *fmr)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (fmr->maps)
|
||||
return -EBUSY;
|
||||
|
||||
mlx4_mr_free(dev, &fmr->mr);
|
||||
fmr->mr.enabled = MLX4_MR_DISABLED;
|
||||
ret = mlx4_mr_free(dev, &fmr->mr);
|
||||
if (ret)
|
||||
return ret;
|
||||
fmr->mr.enabled = MLX4_MPT_DISABLED;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@@ -1231,14 +1231,14 @@ static int mpt_alloc_res(struct mlx4_dev *dev, int slave, int op, int cmd,
|
||||
|
||||
switch (op) {
|
||||
case RES_OP_RESERVE:
|
||||
index = __mlx4_mr_reserve(dev);
|
||||
index = __mlx4_mpt_reserve(dev);
|
||||
if (index == -1)
|
||||
break;
|
||||
id = index & mpt_mask(dev);
|
||||
|
||||
err = add_res_range(dev, slave, id, 1, RES_MPT, index);
|
||||
if (err) {
|
||||
__mlx4_mr_release(dev, index);
|
||||
__mlx4_mpt_release(dev, index);
|
||||
break;
|
||||
}
|
||||
set_param_l(out_param, index);
|
||||
@@ -1251,7 +1251,7 @@ static int mpt_alloc_res(struct mlx4_dev *dev, int slave, int op, int cmd,
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
err = __mlx4_mr_alloc_icm(dev, mpt->key);
|
||||
err = __mlx4_mpt_alloc_icm(dev, mpt->key);
|
||||
if (err) {
|
||||
res_abort_move(dev, slave, RES_MPT, id);
|
||||
return err;
|
||||
@@ -1586,7 +1586,7 @@ static int mpt_free_res(struct mlx4_dev *dev, int slave, int op, int cmd,
|
||||
err = rem_res_range(dev, slave, id, 1, RES_MPT, 0);
|
||||
if (err)
|
||||
break;
|
||||
__mlx4_mr_release(dev, index);
|
||||
__mlx4_mpt_release(dev, index);
|
||||
break;
|
||||
case RES_OP_MAP_ICM:
|
||||
index = get_param_l(&in_param);
|
||||
@@ -1596,7 +1596,7 @@ static int mpt_free_res(struct mlx4_dev *dev, int slave, int op, int cmd,
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
__mlx4_mr_free_icm(dev, mpt->key);
|
||||
__mlx4_mpt_free_icm(dev, mpt->key);
|
||||
res_end_move(dev, slave, RES_MPT, id);
|
||||
return err;
|
||||
break;
|
||||
@@ -1796,6 +1796,26 @@ static int mr_get_mtt_size(struct mlx4_mpt_entry *mpt)
|
||||
return be32_to_cpu(mpt->mtt_sz);
|
||||
}
|
||||
|
||||
static u32 mr_get_pd(struct mlx4_mpt_entry *mpt)
|
||||
{
|
||||
return be32_to_cpu(mpt->pd_flags) & 0x00ffffff;
|
||||
}
|
||||
|
||||
static int mr_is_fmr(struct mlx4_mpt_entry *mpt)
|
||||
{
|
||||
return be32_to_cpu(mpt->pd_flags) & MLX4_MPT_PD_FLAG_FAST_REG;
|
||||
}
|
||||
|
||||
static int mr_is_bind_enabled(struct mlx4_mpt_entry *mpt)
|
||||
{
|
||||
return be32_to_cpu(mpt->flags) & MLX4_MPT_FLAG_BIND_ENABLE;
|
||||
}
|
||||
|
||||
static int mr_is_region(struct mlx4_mpt_entry *mpt)
|
||||
{
|
||||
return be32_to_cpu(mpt->flags) & MLX4_MPT_FLAG_REGION;
|
||||
}
|
||||
|
||||
static int qp_get_mtt_addr(struct mlx4_qp_context *qpc)
|
||||
{
|
||||
return be32_to_cpu(qpc->mtt_base_addr_l) & 0xfffffff8;
|
||||
@@ -1856,12 +1876,41 @@ int mlx4_SW2HW_MPT_wrapper(struct mlx4_dev *dev, int slave,
|
||||
int mtt_base = mr_get_mtt_addr(inbox->buf) / dev->caps.mtt_entry_sz;
|
||||
int phys;
|
||||
int id;
|
||||
u32 pd;
|
||||
int pd_slave;
|
||||
|
||||
id = index & mpt_mask(dev);
|
||||
err = mr_res_start_move_to(dev, slave, id, RES_MPT_HW, &mpt);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
/* Disable memory windows for VFs. */
|
||||
if (!mr_is_region(inbox->buf)) {
|
||||
err = -EPERM;
|
||||
goto ex_abort;
|
||||
}
|
||||
|
||||
/* Make sure that the PD bits related to the slave id are zeros. */
|
||||
pd = mr_get_pd(inbox->buf);
|
||||
pd_slave = (pd >> 17) & 0x7f;
|
||||
if (pd_slave != 0 && pd_slave != slave) {
|
||||
err = -EPERM;
|
||||
goto ex_abort;
|
||||
}
|
||||
|
||||
if (mr_is_fmr(inbox->buf)) {
|
||||
/* FMR and Bind Enable are forbidden in slave devices. */
|
||||
if (mr_is_bind_enabled(inbox->buf)) {
|
||||
err = -EPERM;
|
||||
goto ex_abort;
|
||||
}
|
||||
/* FMR and Memory Windows are also forbidden. */
|
||||
if (!mr_is_region(inbox->buf)) {
|
||||
err = -EPERM;
|
||||
goto ex_abort;
|
||||
}
|
||||
}
|
||||
|
||||
phys = mr_phys_mpt(inbox->buf);
|
||||
if (!phys) {
|
||||
err = get_res(dev, slave, mtt_base, RES_MTT, &mtt);
|
||||
@@ -3480,7 +3529,7 @@ static void rem_slave_mrs(struct mlx4_dev *dev, int slave)
|
||||
while (state != 0) {
|
||||
switch (state) {
|
||||
case RES_MPT_RESERVED:
|
||||
__mlx4_mr_release(dev, mpt->key);
|
||||
__mlx4_mpt_release(dev, mpt->key);
|
||||
spin_lock_irq(mlx4_tlock(dev));
|
||||
rb_erase(&mpt->com.node,
|
||||
&tracker->res_tree[RES_MPT]);
|
||||
@@ -3491,7 +3540,7 @@ static void rem_slave_mrs(struct mlx4_dev *dev, int slave)
|
||||
break;
|
||||
|
||||
case RES_MPT_MAPPED:
|
||||
__mlx4_mr_free_icm(dev, mpt->key);
|
||||
__mlx4_mpt_free_icm(dev, mpt->key);
|
||||
state = RES_MPT_RESERVED;
|
||||
break;
|
||||
|
||||
|
Reference in New Issue
Block a user