Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 4ff0acca authored by Matan Barak's avatar Matan Barak Committed by Roland Dreier
Browse files

mlx4: Correct error flows in rereg_mr



This patch addresses feedback from Sagi Grimberg on the rereg_mr
implementation of mlx4.  The following are fixed:

1. Set the correct pd_flags
2. Make sure we change the iova and size MR fields only after
   successful write and allocation of the MTTs.
3. Make the error checking more robust

Fixes: e630664c ("mlx4_core: Add helper functions to support MR re-registration")
Signed-off-by: default avatarMatan Barak <matanb@mellanox.com>
Signed-off-by: default avatarOr Gerlitz <ogerlitz@mellanox.com>
Signed-off-by: default avatarRoland Dreier <roland@purestorage.com>
parent 50e2ec91
Loading
Loading
Loading
Loading
+5 −2
Original line number Diff line number Diff line
@@ -234,14 +234,13 @@ int mlx4_ib_rereg_user_mr(struct ib_mr *mr, int flags,
					0);
		if (IS_ERR(mmr->umem)) {
			err = PTR_ERR(mmr->umem);
			/* Prevent mlx4_ib_dereg_mr from free'ing invalid pointer */
			mmr->umem = NULL;
			goto release_mpt_entry;
		}
		n = ib_umem_page_count(mmr->umem);
		shift = ilog2(mmr->umem->page_size);

		mmr->mmr.iova       = virt_addr;
		mmr->mmr.size       = length;
		err = mlx4_mr_rereg_mem_write(dev->dev, &mmr->mmr,
					      virt_addr, length, n, shift,
					      *pmpt_entry);
@@ -249,6 +248,8 @@ int mlx4_ib_rereg_user_mr(struct ib_mr *mr, int flags,
			ib_umem_release(mmr->umem);
			goto release_mpt_entry;
		}
		mmr->mmr.iova       = virt_addr;
		mmr->mmr.size       = length;

		err = mlx4_ib_umem_write_mtt(dev, &mmr->mmr.mtt, mmr->umem);
		if (err) {
@@ -262,6 +263,8 @@ int mlx4_ib_rereg_user_mr(struct ib_mr *mr, int flags,
	 * return a failure. But dereg_mr will free the resources.
	 */
	err = mlx4_mr_hw_write_mpt(dev->dev, &mmr->mmr, pmpt_entry);
	if (!err && flags & IB_MR_REREG_ACCESS)
		mmr->mmr.access = mr_access_flags;

release_mpt_entry:
	mlx4_mr_hw_put_mpt(dev->dev, pmpt_entry);
+22 −11
Original line number Diff line number Diff line
@@ -298,6 +298,7 @@ static int mlx4_HW2SW_MPT(struct mlx4_dev *dev, struct mlx4_cmd_mailbox *mailbox
			    MLX4_CMD_TIME_CLASS_B, MLX4_CMD_WRAPPED);
}

/* Must protect against concurrent access */
int mlx4_mr_hw_get_mpt(struct mlx4_dev *dev, struct mlx4_mr *mmr,
		       struct mlx4_mpt_entry ***mpt_entry)
{
@@ -305,13 +306,10 @@ int mlx4_mr_hw_get_mpt(struct mlx4_dev *dev, struct mlx4_mr *mmr,
	int key = key_to_hw_index(mmr->key) & (dev->caps.num_mpts - 1);
	struct mlx4_cmd_mailbox *mailbox = NULL;

	/* Make sure that at this point we have single-threaded access only */

	if (mmr->enabled != MLX4_MPT_EN_HW)
		return -EINVAL;

	err = mlx4_HW2SW_MPT(dev, NULL, key);

	if (err) {
		mlx4_warn(dev, "HW2SW_MPT failed (%d).", err);
		mlx4_warn(dev, "Most likely the MR has MWs bound to it.\n");
@@ -333,7 +331,6 @@ int mlx4_mr_hw_get_mpt(struct mlx4_dev *dev, struct mlx4_mr *mmr,
				   0, MLX4_CMD_QUERY_MPT,
				   MLX4_CMD_TIME_CLASS_B,
				   MLX4_CMD_WRAPPED);

		if (err)
			goto free_mailbox;

@@ -378,9 +375,10 @@ int mlx4_mr_hw_write_mpt(struct mlx4_dev *dev, struct mlx4_mr *mmr,
		err = mlx4_SW2HW_MPT(dev, mailbox, key);
	}

	if (!err) {
		mmr->pd = be32_to_cpu((*mpt_entry)->pd_flags) & MLX4_MPT_PD_MASK;
	if (!err)
		mmr->enabled = MLX4_MPT_EN_HW;
	}
	return err;
}
EXPORT_SYMBOL_GPL(mlx4_mr_hw_write_mpt);
@@ -400,11 +398,12 @@ EXPORT_SYMBOL_GPL(mlx4_mr_hw_put_mpt);
int mlx4_mr_hw_change_pd(struct mlx4_dev *dev, struct mlx4_mpt_entry *mpt_entry,
			 u32 pdn)
{
	u32 pd_flags = be32_to_cpu(mpt_entry->pd_flags);
	u32 pd_flags = be32_to_cpu(mpt_entry->pd_flags) & ~MLX4_MPT_PD_MASK;
	/* The wrapper function will put the slave's id here */
	if (mlx4_is_mfunc(dev))
		pd_flags &= ~MLX4_MPT_PD_VF_MASK;
	mpt_entry->pd_flags = cpu_to_be32((pd_flags &  ~MLX4_MPT_PD_MASK) |

	mpt_entry->pd_flags = cpu_to_be32(pd_flags |
					  (pdn & MLX4_MPT_PD_MASK)
					  | MLX4_MPT_PD_FLAG_EN_INV);
	return 0;
@@ -600,14 +599,18 @@ int mlx4_mr_rereg_mem_write(struct mlx4_dev *dev, struct mlx4_mr *mr,
{
	int err;

	mpt_entry->start       = cpu_to_be64(mr->iova);
	mpt_entry->length      = cpu_to_be64(mr->size);
	mpt_entry->entity_size = cpu_to_be32(mr->mtt.page_shift);
	mpt_entry->start       = cpu_to_be64(iova);
	mpt_entry->length      = cpu_to_be64(size);
	mpt_entry->entity_size = cpu_to_be32(page_shift);

	err = mlx4_mtt_init(dev, npages, page_shift, &mr->mtt);
	if (err)
		return err;

	mpt_entry->pd_flags &= cpu_to_be32(MLX4_MPT_PD_MASK |
					   MLX4_MPT_PD_FLAG_EN_INV);
	mpt_entry->flags    &= cpu_to_be32(MLX4_MPT_FLAG_FREE |
					   MLX4_MPT_FLAG_SW_OWNS);
	if (mr->mtt.order < 0) {
		mpt_entry->flags |= cpu_to_be32(MLX4_MPT_FLAG_PHYSICAL);
		mpt_entry->mtt_addr = 0;
@@ -617,6 +620,14 @@ int mlx4_mr_rereg_mem_write(struct mlx4_dev *dev, struct mlx4_mr *mr,
		if (mr->mtt.page_shift == 0)
			mpt_entry->mtt_sz    = cpu_to_be32(1 << mr->mtt.order);
	}
	if (mr->mtt.order >= 0 && mr->mtt.page_shift == 0) {
		/* fast register MR in free state */
		mpt_entry->flags    |= cpu_to_be32(MLX4_MPT_FLAG_FREE);
		mpt_entry->pd_flags |= cpu_to_be32(MLX4_MPT_PD_FLAG_FAST_REG |
						   MLX4_MPT_PD_FLAG_RAE);
	} else {
		mpt_entry->flags    |= cpu_to_be32(MLX4_MPT_FLAG_SW_OWNS);
	}
	mr->enabled = MLX4_MPT_EN_SW;

	return 0;