From 1a2fb2295b1378d7b3e4f139e121db6989c6a271 Mon Sep 17 00:00:00 2001 From: Moshe Lazer Date: Sun, 8 Sep 2013 08:59:09 +0200 Subject: [PATCH] mlx4_core: fix FMR unmapping to allow remapping afterward The FMR common use flow (as implemented in fmr_pool) is: - Allocate FMR (ib_alloc_fmr) - Use the FMR to remap DMA memory until remaps limit exceeded (ib_map_phys_fmr) - Unmap the FMR (ib_unmap_fmr) - Use the FMR to remap DMA memory until remaps limit exceeded (ib_map_phys_fmr) - ... The current implementation of mlx4_fmr_unmap is not following this use flow since it is using the HW2SW MPT command. The HW2SW MPT command notifies the FW that the MPT entry is not used by HW anymore. The FW may act according to this information, therefore it is not safe for the driver to manipulate the MPT directly. The patch fixes this by manipulating the MPT directly to unmap the memory instead of using the HW2SW MPT command. Signed-off-by: Moshe Lazer (Ported from Mellanox OFED 2.4) Signed-off-by: Mukesh Kacker --- drivers/net/ethernet/mellanox/mlx4/mr.c | 40 ++++++++++++++----------- 1 file changed, 22 insertions(+), 18 deletions(-) diff --git a/drivers/net/ethernet/mellanox/mlx4/mr.c b/drivers/net/ethernet/mellanox/mlx4/mr.c index c8dc251ea569..bc7fd3282b4f 100644 --- a/drivers/net/ethernet/mellanox/mlx4/mr.c +++ b/drivers/net/ethernet/mellanox/mlx4/mr.c @@ -1110,30 +1110,34 @@ EXPORT_SYMBOL_GPL(mlx4_fmr_enable); void mlx4_fmr_unmap(struct mlx4_dev *dev, struct mlx4_fmr *fmr, u32 *lkey, u32 *rkey) { - struct mlx4_cmd_mailbox *mailbox; - int err; + u32 key; if (!fmr->maps) return; - fmr->maps = 0; + key = key_to_hw_index(fmr->mr.key) & (dev->caps.num_mpts - 1); - mailbox = mlx4_alloc_cmd_mailbox(dev); - if (IS_ERR(mailbox)) { - err = PTR_ERR(mailbox); - pr_warn("mlx4_ib: mlx4_alloc_cmd_mailbox failed (%d)\n", err); - return; - } + *(u8 *)fmr->mpt = MLX4_MPT_STATUS_SW; - err = mlx4_HW2SW_MPT(dev, NULL, - key_to_hw_index(fmr->mr.key) & - (dev->caps.num_mpts - 1)); - mlx4_free_cmd_mailbox(dev, mailbox); - if (err) { - pr_warn("mlx4_ib: mlx4_HW2SW_MPT failed (%d)\n", err); - return; - } - fmr->mr.enabled = MLX4_MPT_EN_SW; + /* Make sure MPT status is visible before changing MPT fields */ + wmb(); + + fmr->mr.key = hw_index_to_key(key); + + fmr->mpt->key = cpu_to_be32(key); + fmr->mpt->lkey = cpu_to_be32(key); + fmr->mpt->length = 0; + fmr->mpt->start = 0; + + /* Make sure MPT data is visible before changing MPT status */ + wmb(); + + *(u8 *)fmr->mpt = MLX4_MPT_STATUS_HW; + + /* Make sure MPT satus is visible */ + wmb(); + + fmr->maps = 0; } EXPORT_SYMBOL_GPL(mlx4_fmr_unmap); -- 2.50.1